blob: e2bf5ca007b5123f469995d191c4dc52fe0950d3 [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"
Chris Lattnerc7229c32007-10-07 08:58:51 +000016#include "clang/Basic/IdentifierTable.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000017#include "clang/Basic/TargetInfo.h"
18using namespace clang;
19
20static const Builtin::Info BuiltinInfo[] = {
21 { "not a builtin function", 0, 0 },
22#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS },
23#include "clang/AST/Builtins.def"
24};
25
26const 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
34/// InitializeBuiltins - Mark the identifiers for all the builtins with their
35/// appropriate builtin ID # and mark any non-portable builtin identifiers as
36/// such.
37void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
38 const TargetInfo &Target) {
39 // Step #1: mark all target-independent builtins with their ID's.
40 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
41 Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
42
Chris Lattner42e67372008-03-05 01:18:20 +000043 // Step #2: Get target builtins.
44 Target.getTargetBuiltins(TSRecords, NumTSRecords);
Reid Spencer5f016e22007-07-11 17:01:13 +000045
Chris Lattner42e67372008-03-05 01:18:20 +000046 // Step #3: Register target-specific builtins.
Reid Spencer5f016e22007-07-11 17:01:13 +000047 for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
48 Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
Reid Spencer5f016e22007-07-11 17:01:13 +000049}
50
51/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
52/// pointer over the consumed characters. This returns the resultant type.
Anders Carlssondd1b5162007-11-28 05:19:59 +000053static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
54 bool AllowTypeModifiers = true) {
Reid Spencer5f016e22007-07-11 17:01:13 +000055 // Modifiers.
56 bool Long = false, LongLong = false, Signed = false, Unsigned = false;
57
58 // Read the modifiers first.
59 bool Done = false;
60 while (!Done) {
61 switch (*Str++) {
62 default: Done = true; --Str; break;
63 case 'S':
64 assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
65 assert(!Signed && "Can't use 'S' modifier multiple times!");
66 Signed = true;
67 break;
68 case 'U':
69 assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
70 assert(!Unsigned && "Can't use 'S' modifier multiple times!");
71 Unsigned = true;
72 break;
73 case 'L':
74 assert(!LongLong && "Can't have LLL modifier");
75 if (Long)
76 LongLong = true;
77 else
78 Long = true;
79 break;
80 }
81 }
82
Anders Carlsson71993dd2007-08-17 05:31:46 +000083 QualType Type;
84
Reid Spencer5f016e22007-07-11 17:01:13 +000085 // Read the base type.
86 switch (*Str++) {
87 default: assert(0 && "Unknown builtin type letter!");
88 case 'v':
Steve Naroffe8770422007-08-08 17:48:34 +000089 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'v'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +000090 Type = Context.VoidTy;
91 break;
Reid Spencer5f016e22007-07-11 17:01:13 +000092 case 'f':
93 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'f'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +000094 Type = Context.FloatTy;
95 break;
Reid Spencer5f016e22007-07-11 17:01:13 +000096 case 'd':
97 assert(!LongLong && !Signed && !Unsigned && "Bad modifiers used with 'd'!");
98 if (Long)
Anders Carlsson71993dd2007-08-17 05:31:46 +000099 Type = Context.LongDoubleTy;
100 else
101 Type = Context.DoubleTy;
102 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000103 case 's':
104 assert(!LongLong && "Bad modifiers used with 's'!");
105 if (Unsigned)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000106 Type = Context.UnsignedShortTy;
107 else
108 Type = Context.ShortTy;
109 break;
Steve Naroffe8770422007-08-08 17:48:34 +0000110 case 'i':
Anders Carlsson142f36d2007-11-27 07:22:09 +0000111 if (LongLong)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000112 Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000113 else if (Long)
114 Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000115 else if (Unsigned)
116 Type = Context.UnsignedIntTy;
117 else
118 Type = Context.IntTy; // default is signed.
119 break;
120 case 'c':
121 assert(!Long && !LongLong && "Bad modifiers used with 'c'!");
122 if (Signed)
123 Type = Context.SignedCharTy;
124 else if (Unsigned)
125 Type = Context.UnsignedCharTy;
126 else
127 Type = Context.CharTy;
128 break;
Chris Lattner52735a02007-10-29 04:18:06 +0000129 case 'z': // size_t.
130 assert(!Long && !Signed && !Unsigned && "Bad modifiers for 'z'!");
131 Type = Context.getSizeType();
132 break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000133 case 'F':
134 Type = Context.getCFConstantStringType();
135 break;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000136 case 'a':
Anders Carlssonb2cf3572007-10-11 01:00:40 +0000137 Type = Context.getBuiltinVaListType();
Anders Carlsson793680e2007-10-12 23:56:29 +0000138 assert(!Type.isNull() && "builtin va list type not initialized!");
Anders Carlssonb2cf3572007-10-11 01:00:40 +0000139 break;
Anders Carlsson142f36d2007-11-27 07:22:09 +0000140 case 'V': {
141 char *End;
142
143 unsigned NumElements = strtoul(Str, &End, 10);
144 assert(End != Str && "Missing vector size");
145
146 Str = End;
147
Anders Carlssondd1b5162007-11-28 05:19:59 +0000148 QualType ElementType = DecodeTypeFromStr(Str, Context, false);
Anders Carlsson142f36d2007-11-27 07:22:09 +0000149 Type = Context.getVectorType(ElementType, NumElements);
150 break;
151 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000152 }
Anders Carlsson71993dd2007-08-17 05:31:46 +0000153
Anders Carlssondd1b5162007-11-28 05:19:59 +0000154 if (!AllowTypeModifiers)
155 return Type;
156
Anders Carlsson71993dd2007-08-17 05:31:46 +0000157 Done = false;
158 while (!Done) {
159 switch (*Str++) {
Anders Carlssondd1b5162007-11-28 05:19:59 +0000160 default: Done = true; --Str; break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000161 case '*':
162 Type = Context.getPointerType(Type);
163 break;
Anders Carlsson793680e2007-10-12 23:56:29 +0000164 case '&':
165 Type = Context.getReferenceType(Type);
166 break;
Anders Carlsson71993dd2007-08-17 05:31:46 +0000167 case 'C':
168 Type = Type.getQualifiedType(QualType::Const);
169 break;
170 }
171 }
172
173 return Type;
Reid Spencer5f016e22007-07-11 17:01:13 +0000174}
175
176/// GetBuiltinType - Return the type for the specified builtin.
Chris Lattner22b73ba2007-10-10 23:42:28 +0000177QualType Builtin::Context::GetBuiltinType(unsigned id,
178 ASTContext &Context) const {
Reid Spencer5f016e22007-07-11 17:01:13 +0000179 const char *TypeStr = GetRecord(id).Type;
180
181 llvm::SmallVector<QualType, 8> ArgTypes;
182
183 QualType ResType = DecodeTypeFromStr(TypeStr, Context);
184 while (TypeStr[0] && TypeStr[0] != '.')
Anders Carlssondd1b5162007-11-28 05:19:59 +0000185 ArgTypes.push_back(DecodeTypeFromStr(TypeStr, Context));
186
Reid Spencer5f016e22007-07-11 17:01:13 +0000187 assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
188 "'.' should only occur at end of builtin type list!");
Steve Naroffe8770422007-08-08 17:48:34 +0000189
190 // handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
191 if (ArgTypes.size() == 0 && TypeStr[0] == '.')
192 return Context.getFunctionTypeNoProto(ResType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000193 return Context.getFunctionType(ResType, &ArgTypes[0], ArgTypes.size(),
194 TypeStr[0] == '.');
195}