blob: e4a79e4a380df586b19d211cc486dde83408b738 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- Builtins.cpp - Builtin function implementation -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements various things for builtin functions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/Builtins.h"
15#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000016#include "clang/AST/Decl.h"
Chris Lattnerc7229c32007-10-07 08:58:51 +000017#include "clang/Basic/IdentifierTable.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000018#include "clang/Basic/TargetInfo.h"
19using namespace clang;
20
21static const Builtin::Info BuiltinInfo[] = {
Douglas Gregorb1152d82009-02-16 21:58:21 +000022 { "not a builtin function", 0, 0, 0, false },
23#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
24#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
Reid Spencer5f016e22007-07-11 17:01:13 +000025#include "clang/AST/Builtins.def"
26};
27
28const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
29 if (ID < Builtin::FirstTSBuiltin)
30 return BuiltinInfo[ID];
31 assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
32 return TSRecords[ID - Builtin::FirstTSBuiltin];
33}
34
35
36/// InitializeBuiltins - Mark the identifiers for all the builtins with their
37/// appropriate builtin ID # and mark any non-portable builtin identifiers as
38/// such.
39void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
Douglas Gregor3573c0c2009-02-14 20:49:29 +000040 const TargetInfo &Target,
41 bool Freestanding) {
Reid Spencer5f016e22007-07-11 17:01:13 +000042 // Step #1: mark all target-independent builtins with their ID's.
43 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
Douglas Gregor3573c0c2009-02-14 20:49:29 +000044 if (!BuiltinInfo[i].Suppressed &&
45 (!Freestanding ||
46 !strchr(BuiltinInfo[i].Attributes, 'f')))
47 Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
Reid Spencer5f016e22007-07-11 17:01:13 +000048
Chris Lattner42e67372008-03-05 01:18:20 +000049 // Step #2: Get target builtins.
50 Target.getTargetBuiltins(TSRecords, NumTSRecords);
Reid Spencer5f016e22007-07-11 17:01:13 +000051
Chris Lattner42e67372008-03-05 01:18:20 +000052 // Step #3: Register target-specific builtins.
Reid Spencer5f016e22007-07-11 17:01:13 +000053 for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
Douglas Gregor3573c0c2009-02-14 20:49:29 +000054 if (!TSRecords[i].Suppressed &&
55 (!Freestanding ||
Daniel Dunbare8699902009-02-15 18:23:07 +000056 (TSRecords[i].Attributes &&
57 !strchr(TSRecords[i].Attributes, 'f'))))
Douglas Gregor3573c0c2009-02-14 20:49:29 +000058 Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
Reid Spencer5f016e22007-07-11 17:01:13 +000059}
60
Douglas Gregora316e7b2009-02-14 00:32:47 +000061bool
62Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
63 bool &HasVAListArg) {
Cedric Venetea684e62009-02-14 16:15:20 +000064 const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
Douglas Gregora316e7b2009-02-14 00:32:47 +000065 if (!Printf)
66 return false;
67
68 HasVAListArg = (*Printf == 'P');
69
70 ++Printf;
71 assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
72 ++Printf;
73
Cedric Venetea684e62009-02-14 16:15:20 +000074 const char *PrintfEnd = strchr(Printf, ':');
Douglas Gregora316e7b2009-02-14 00:32:47 +000075 assert(PrintfEnd && "printf specifier must end with a ':'");
76
77 FormatIdx = strtol(Printf, 0, 10);
78 return true;
79}
80
Reid Spencer5f016e22007-07-11 17:01:13 +000081/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
82/// pointer over the consumed characters. This returns the resultant type.
Anders Carlssondd1b5162007-11-28 05:19:59 +000083static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
Douglas Gregor370ab3f2009-02-14 01:52:53 +000084 Builtin::Context::GetBuiltinTypeError &Error,
Anders Carlssondd1b5162007-11-28 05:19:59 +000085 bool AllowTypeModifiers = true) {
Reid Spencer5f016e22007-07-11 17:01:13 +000086 // Modifiers.
87 bool Long = false, LongLong = false, Signed = false, Unsigned = false;
88
89 // Read the modifiers first.
90 bool Done = false;
91 while (!Done) {
92 switch (*Str++) {
93 default: Done = true; --Str; break;
94 case 'S':
95 assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
96 assert(!Signed && "Can't use 'S' modifier multiple times!");
97 Signed = true;
98 break;
99 case 'U':
100 assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
101 assert(!Unsigned && "Can't use 'S' modifier multiple times!");
102 Unsigned = true;
103 break;
104 case 'L':
105 assert(!LongLong && "Can't have LLL modifier");
106 if (Long)
107 LongLong = true;
108 else
109 Long = true;
110 break;
111 }
112 }
113
Anders Carlsson71993dd2007-08-17 05:31:46 +0000114 QualType Type;
115
Reid Spencer5f016e22007-07-11 17:01:13 +0000116 // Read the base type.
117 switch (*Str++) {
118 default: assert(0 && "Unknown builtin type letter!");
119 case 'v':
Steve Naroffe8770422007-08-08 17:48:34 +0000120 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'v'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +0000121 Type = Context.VoidTy;
122 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000123 case 'f':
124 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'f'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +0000125 Type = Context.FloatTy;
126 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000127 case 'd':
128 assert(!LongLong && !Signed && !Unsigned && "Bad modifiers used with 'd'!");
129 if (Long)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000130 Type = Context.LongDoubleTy;
131 else
132 Type = Context.DoubleTy;
133 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000134 case 's':
135 assert(!LongLong && "Bad modifiers used with 's'!");
136 if (Unsigned)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000137 Type = Context.UnsignedShortTy;
138 else
139 Type = Context.ShortTy;
140 break;
Steve Naroffe8770422007-08-08 17:48:34 +0000141 case 'i':
Anders Carlsson142f36d2007-11-27 07:22:09 +0000142 if (LongLong)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000143 Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000144 else if (Long)
145 Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000146 else if (Unsigned)
147 Type = Context.UnsignedIntTy;
148 else
149 Type = Context.IntTy; // default is signed.
150 break;
151 case 'c':
152 assert(!Long && !LongLong && "Bad modifiers used with 'c'!");
153 if (Signed)
154 Type = Context.SignedCharTy;
155 else if (Unsigned)
156 Type = Context.UnsignedCharTy;
157 else
158 Type = Context.CharTy;
159 break;
Mon P Wang7ae48ee2008-10-18 02:49:28 +0000160 case 'b': // boolean
161 assert(!Long && !Signed && !Unsigned && "Bad modifiers for 'b'!");
162 Type = Context.BoolTy;
163 break;
Chris Lattner52735a02007-10-29 04:18:06 +0000164 case 'z': // size_t.
165 assert(!Long && !Signed && !Unsigned && "Bad modifiers for 'z'!");
166 Type = Context.getSizeType();
167 break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000168 case 'F':
169 Type = Context.getCFConstantStringType();
170 break;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000171 case 'a':
Anders Carlssonb2cf3572007-10-11 01:00:40 +0000172 Type = Context.getBuiltinVaListType();
Anders Carlsson793680e2007-10-12 23:56:29 +0000173 assert(!Type.isNull() && "builtin va list type not initialized!");
Anders Carlssonb2cf3572007-10-11 01:00:40 +0000174 break;
Eli Friedman6597f982009-01-20 07:46:22 +0000175 case 'A':
176 // This is a "reference" to a va_list; however, what exactly
177 // this means depends on how va_list is defined. There are two
178 // different kinds of va_list: ones passed by value, and ones
179 // passed by reference. An example of a by-value va_list is
180 // x86, where va_list is a char*. An example of by-ref va_list
181 // is x86-64, where va_list is a __va_list_tag[1]. For x86,
182 // we want this argument to be a char*&; for x86-64, we want
183 // it to be a __va_list_tag*.
184 Type = Context.getBuiltinVaListType();
185 assert(!Type.isNull() && "builtin va list type not initialized!");
186 if (Type->isArrayType()) {
187 Type = Context.getArrayDecayedType(Type);
188 } else {
189 Type = Context.getReferenceType(Type);
190 }
191 break;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000192 case 'V': {
193 char *End;
194
195 unsigned NumElements = strtoul(Str, &End, 10);
196 assert(End != Str && "Missing vector size");
197
198 Str = End;
199
Douglas Gregor370ab3f2009-02-14 01:52:53 +0000200 QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
Anders Carlsson142f36d2007-11-27 07:22:09 +0000201 Type = Context.getVectorType(ElementType, NumElements);
202 break;
203 }
Douglas Gregor370ab3f2009-02-14 01:52:53 +0000204 case 'P': {
205 IdentifierInfo *II = &Context.Idents.get("FILE");
206 DeclContext::lookup_result Lookup
207 = Context.getTranslationUnitDecl()->lookup(II);
208 if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) {
209 Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
210 break;
211 }
212 else {
213 Error = Builtin::Context::GE_Missing_FILE;
214 return QualType();
215 }
216 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000217 }
Anders Carlsson71993dd2007-08-17 05:31:46 +0000218
Anders Carlssondd1b5162007-11-28 05:19:59 +0000219 if (!AllowTypeModifiers)
220 return Type;
221
Anders Carlsson71993dd2007-08-17 05:31:46 +0000222 Done = false;
223 while (!Done) {
224 switch (*Str++) {
Anders Carlssondd1b5162007-11-28 05:19:59 +0000225 default: Done = true; --Str; break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000226 case '*':
227 Type = Context.getPointerType(Type);
228 break;
Anders Carlsson793680e2007-10-12 23:56:29 +0000229 case '&':
230 Type = Context.getReferenceType(Type);
231 break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000232 case 'C':
233 Type = Type.getQualifiedType(QualType::Const);
234 break;
235 }
236 }
237
238 return Type;
Reid Spencer5f016e22007-07-11 17:01:13 +0000239}
240
241/// GetBuiltinType - Return the type for the specified builtin.
Douglas Gregor370ab3f2009-02-14 01:52:53 +0000242QualType Builtin::Context::GetBuiltinType(unsigned id, ASTContext &Context,
243 GetBuiltinTypeError &Error) const {
Reid Spencer5f016e22007-07-11 17:01:13 +0000244 const char *TypeStr = GetRecord(id).Type;
245
246 llvm::SmallVector<QualType, 8> ArgTypes;
247
Douglas Gregor370ab3f2009-02-14 01:52:53 +0000248 Error = GE_None;
249 QualType ResType = DecodeTypeFromStr(TypeStr, Context, Error);
250 if (Error != GE_None)
251 return QualType();
Chris Lattnerf77d5452008-09-29 22:28:25 +0000252 while (TypeStr[0] && TypeStr[0] != '.') {
Douglas Gregor370ab3f2009-02-14 01:52:53 +0000253 QualType Ty = DecodeTypeFromStr(TypeStr, Context, Error);
254 if (Error != GE_None)
255 return QualType();
256
Chris Lattnerf77d5452008-09-29 22:28:25 +0000257 // Do array -> pointer decay. The builtin should use the decayed type.
258 if (Ty->isArrayType())
259 Ty = Context.getArrayDecayedType(Ty);
260
261 ArgTypes.push_back(Ty);
262 }
Anders Carlssondd1b5162007-11-28 05:19:59 +0000263
Reid Spencer5f016e22007-07-11 17:01:13 +0000264 assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
265 "'.' should only occur at end of builtin type list!");
Steve Naroffe8770422007-08-08 17:48:34 +0000266
267 // handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
268 if (ArgTypes.size() == 0 && TypeStr[0] == '.')
269 return Context.getFunctionTypeNoProto(ResType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000270 return Context.getFunctionType(ResType, &ArgTypes[0], ArgTypes.size(),
Argyrios Kyrtzidis7fb5e482008-10-26 16:43:14 +0000271 TypeStr[0] == '.', 0);
Reid Spencer5f016e22007-07-11 17:01:13 +0000272}