xref: /llvm-project/clang/lib/Basic/Builtins.cpp (revision 5932c35138947e48c966b198858e51eafa4e725c)
1 //===--- Builtins.cpp - Builtin function implementation -------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements various things for builtin functions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Basic/Builtins.h"
15 #include "clang/Basic/IdentifierTable.h"
16 #include "clang/Basic/TargetInfo.h"
17 using namespace clang;
18 
19 static const Builtin::Info BuiltinInfo[] = {
20   { "not a builtin function", 0, 0, 0, false },
21 #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
22 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
23 #include "clang/Basic/Builtins.def"
24 };
25 
26 const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
27   if (ID < Builtin::FirstTSBuiltin)
28     return BuiltinInfo[ID];
29   assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
30   return TSRecords[ID - Builtin::FirstTSBuiltin];
31 }
32 
33 Builtin::Context::Context(const TargetInfo &Target) {
34   // Get the target specific builtins from the target.
35   TSRecords = 0;
36   NumTSRecords = 0;
37   Target.getTargetBuiltins(TSRecords, NumTSRecords);
38 }
39 
40 /// InitializeBuiltins - Mark the identifiers for all the builtins with their
41 /// appropriate builtin ID # and mark any non-portable builtin identifiers as
42 /// such.
43 void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
44                                           bool NoBuiltins) {
45   // Step #1: mark all target-independent builtins with their ID's.
46   for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
47     if (!BuiltinInfo[i].Suppressed &&
48         (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
49       Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
50 
51   // Step #2: Register target-specific builtins.
52   for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
53     if (!TSRecords[i].Suppressed &&
54         (!NoBuiltins ||
55          (TSRecords[i].Attributes &&
56           !strchr(TSRecords[i].Attributes, 'f'))))
57       Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
58 }
59 
60 void
61 Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
62                                   bool NoBuiltins) {
63   // Final all target-independent names
64   for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
65     if (!BuiltinInfo[i].Suppressed &&
66         (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
67       Names.push_back(BuiltinInfo[i].Name);
68 
69   // Find target-specific names.
70   for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
71     if (!TSRecords[i].Suppressed &&
72         (!NoBuiltins ||
73          (TSRecords[i].Attributes &&
74           !strchr(TSRecords[i].Attributes, 'f'))))
75       Names.push_back(TSRecords[i].Name);
76 }
77 
78 bool
79 Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
80                                bool &HasVAListArg) {
81   const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
82   if (!Printf)
83     return false;
84 
85   HasVAListArg = (*Printf == 'P');
86 
87   ++Printf;
88   assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
89   ++Printf;
90 
91   assert(strchr(Printf, ':') && "printf specifier must end with a ':'");
92   FormatIdx = strtol(Printf, 0, 10);
93   return true;
94 }
95 
96 // FIXME: Refactor with isPrintfLike.
97 bool
98 Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
99                               bool &HasVAListArg) {
100   const char *Scanf = strpbrk(GetRecord(ID).Attributes, "sS");
101   if (!Scanf)
102     return false;
103 
104   HasVAListArg = (*Scanf == 'S');
105 
106   ++Scanf;
107   assert(*Scanf == ':' && "s or S specifier must have be followed by a ':'");
108   ++Scanf;
109 
110   assert(strchr(Scanf, ':') && "printf specifier must end with a ':'");
111   FormatIdx = strtol(Scanf, 0, 10);
112   return true;
113 }
114 
115 
116