blob: 1823ee6055962a769c117be0d7c647b573d7f913 [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[] = {
22 { "not a builtin function", 0, 0 },
23#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS },
24#include "clang/AST/Builtins.def"
25};
26
27const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
28 if (ID < Builtin::FirstTSBuiltin)
29 return BuiltinInfo[ID];
30 assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
31 return TSRecords[ID - Builtin::FirstTSBuiltin];
32}
33
34
35/// InitializeBuiltins - Mark the identifiers for all the builtins with their
36/// appropriate builtin ID # and mark any non-portable builtin identifiers as
37/// such.
38void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
39 const TargetInfo &Target) {
40 // Step #1: mark all target-independent builtins with their ID's.
41 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
42 Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
43
Chris Lattner42e67372008-03-05 01:18:20 +000044 // Step #2: Get target builtins.
45 Target.getTargetBuiltins(TSRecords, NumTSRecords);
Reid Spencer5f016e22007-07-11 17:01:13 +000046
Chris Lattner42e67372008-03-05 01:18:20 +000047 // Step #3: Register target-specific builtins.
Reid Spencer5f016e22007-07-11 17:01:13 +000048 for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
49 Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
Reid Spencer5f016e22007-07-11 17:01:13 +000050}
51
52/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
53/// pointer over the consumed characters. This returns the resultant type.
Anders Carlssondd1b5162007-11-28 05:19:59 +000054static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
55 bool AllowTypeModifiers = true) {
Reid Spencer5f016e22007-07-11 17:01:13 +000056 // Modifiers.
57 bool Long = false, LongLong = false, Signed = false, Unsigned = false;
58
59 // Read the modifiers first.
60 bool Done = false;
61 while (!Done) {
62 switch (*Str++) {
63 default: Done = true; --Str; break;
64 case 'S':
65 assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
66 assert(!Signed && "Can't use 'S' modifier multiple times!");
67 Signed = true;
68 break;
69 case 'U':
70 assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
71 assert(!Unsigned && "Can't use 'S' modifier multiple times!");
72 Unsigned = true;
73 break;
74 case 'L':
75 assert(!LongLong && "Can't have LLL modifier");
76 if (Long)
77 LongLong = true;
78 else
79 Long = true;
80 break;
81 }
82 }
83
Anders Carlsson71993dd2007-08-17 05:31:46 +000084 QualType Type;
85
Reid Spencer5f016e22007-07-11 17:01:13 +000086 // Read the base type.
87 switch (*Str++) {
88 default: assert(0 && "Unknown builtin type letter!");
89 case 'v':
Steve Naroffe8770422007-08-08 17:48:34 +000090 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'v'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +000091 Type = Context.VoidTy;
92 break;
Reid Spencer5f016e22007-07-11 17:01:13 +000093 case 'f':
94 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'f'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +000095 Type = Context.FloatTy;
96 break;
Reid Spencer5f016e22007-07-11 17:01:13 +000097 case 'd':
98 assert(!LongLong && !Signed && !Unsigned && "Bad modifiers used with 'd'!");
99 if (Long)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000100 Type = Context.LongDoubleTy;
101 else
102 Type = Context.DoubleTy;
103 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000104 case 's':
105 assert(!LongLong && "Bad modifiers used with 's'!");
106 if (Unsigned)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000107 Type = Context.UnsignedShortTy;
108 else
109 Type = Context.ShortTy;
110 break;
Steve Naroffe8770422007-08-08 17:48:34 +0000111 case 'i':
Anders Carlsson142f36d2007-11-27 07:22:09 +0000112 if (LongLong)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000113 Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000114 else if (Long)
115 Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000116 else if (Unsigned)
117 Type = Context.UnsignedIntTy;
118 else
119 Type = Context.IntTy; // default is signed.
120 break;
121 case 'c':
122 assert(!Long && !LongLong && "Bad modifiers used with 'c'!");
123 if (Signed)
124 Type = Context.SignedCharTy;
125 else if (Unsigned)
126 Type = Context.UnsignedCharTy;
127 else
128 Type = Context.CharTy;
129 break;
Mon P Wang7ae48ee2008-10-18 02:49:28 +0000130 case 'b': // boolean
131 assert(!Long && !Signed && !Unsigned && "Bad modifiers for 'b'!");
132 Type = Context.BoolTy;
133 break;
Chris Lattner52735a02007-10-29 04:18:06 +0000134 case 'z': // size_t.
135 assert(!Long && !Signed && !Unsigned && "Bad modifiers for 'z'!");
136 Type = Context.getSizeType();
137 break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000138 case 'F':
139 Type = Context.getCFConstantStringType();
140 break;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000141 case 'a':
Anders Carlssonb2cf3572007-10-11 01:00:40 +0000142 Type = Context.getBuiltinVaListType();
Anders Carlsson793680e2007-10-12 23:56:29 +0000143 assert(!Type.isNull() && "builtin va list type not initialized!");
Anders Carlssonb2cf3572007-10-11 01:00:40 +0000144 break;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000145 case 'V': {
146 char *End;
147
148 unsigned NumElements = strtoul(Str, &End, 10);
149 assert(End != Str && "Missing vector size");
150
151 Str = End;
152
Anders Carlssondd1b5162007-11-28 05:19:59 +0000153 QualType ElementType = DecodeTypeFromStr(Str, Context, false);
Anders Carlsson142f36d2007-11-27 07:22:09 +0000154 Type = Context.getVectorType(ElementType, NumElements);
155 break;
156 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000157 }
Anders Carlsson71993dd2007-08-17 05:31:46 +0000158
Anders Carlssondd1b5162007-11-28 05:19:59 +0000159 if (!AllowTypeModifiers)
160 return Type;
161
Anders Carlsson71993dd2007-08-17 05:31:46 +0000162 Done = false;
163 while (!Done) {
164 switch (*Str++) {
Anders Carlssondd1b5162007-11-28 05:19:59 +0000165 default: Done = true; --Str; break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000166 case '*':
167 Type = Context.getPointerType(Type);
168 break;
Anders Carlsson793680e2007-10-12 23:56:29 +0000169 case '&':
170 Type = Context.getReferenceType(Type);
171 break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000172 case 'C':
173 Type = Type.getQualifiedType(QualType::Const);
174 break;
175 }
176 }
177
178 return Type;
Reid Spencer5f016e22007-07-11 17:01:13 +0000179}
180
181/// GetBuiltinType - Return the type for the specified builtin.
Chris Lattner22b73ba2007-10-10 23:42:28 +0000182QualType Builtin::Context::GetBuiltinType(unsigned id,
183 ASTContext &Context) const {
Reid Spencer5f016e22007-07-11 17:01:13 +0000184 const char *TypeStr = GetRecord(id).Type;
185
186 llvm::SmallVector<QualType, 8> ArgTypes;
187
188 QualType ResType = DecodeTypeFromStr(TypeStr, Context);
Chris Lattnerf77d5452008-09-29 22:28:25 +0000189 while (TypeStr[0] && TypeStr[0] != '.') {
190 QualType Ty = DecodeTypeFromStr(TypeStr, Context);
191
192 // Do array -> pointer decay. The builtin should use the decayed type.
193 if (Ty->isArrayType())
194 Ty = Context.getArrayDecayedType(Ty);
195
196 ArgTypes.push_back(Ty);
197 }
Anders Carlssondd1b5162007-11-28 05:19:59 +0000198
Reid Spencer5f016e22007-07-11 17:01:13 +0000199 assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
200 "'.' should only occur at end of builtin type list!");
Steve Naroffe8770422007-08-08 17:48:34 +0000201
202 // handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
203 if (ArgTypes.size() == 0 && TypeStr[0] == '.')
204 return Context.getFunctionTypeNoProto(ResType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000205 return Context.getFunctionType(ResType, &ArgTypes[0], ArgTypes.size(),
206 TypeStr[0] == '.');
207}