blob: 408e28d229e9e8297f7e4aa0d3881ca909d3628a [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- Builtins.cpp - Builtin function implementation -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
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"
16#include "clang/Lex/IdentifierTable.h"
17#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
43 // Step #2: handle target builtins.
44 std::vector<const char *> NonPortableBuiltins;
45 Target.getTargetBuiltins(TSRecords, NumTSRecords, NonPortableBuiltins);
46
47 // Step #2a: Register target-specific builtins.
48 for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
49 Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
50
51 // Step #2b: Mark non-portable builtins as such.
52 for (unsigned i = 0, e = NonPortableBuiltins.size(); i != e; ++i)
53 Table.get(NonPortableBuiltins[i]).setNonPortableBuiltin(true);
54}
55
56/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
57/// pointer over the consumed characters. This returns the resultant type.
58static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context) {
59 // Modifiers.
60 bool Long = false, LongLong = false, Signed = false, Unsigned = false;
61
62 // Read the modifiers first.
63 bool Done = false;
64 while (!Done) {
65 switch (*Str++) {
66 default: Done = true; --Str; break;
67 case 'S':
68 assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
69 assert(!Signed && "Can't use 'S' modifier multiple times!");
70 Signed = true;
71 break;
72 case 'U':
73 assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
74 assert(!Unsigned && "Can't use 'S' modifier multiple times!");
75 Unsigned = true;
76 break;
77 case 'L':
78 assert(!LongLong && "Can't have LLL modifier");
79 if (Long)
80 LongLong = true;
81 else
82 Long = true;
83 break;
84 }
85 }
86
Anders Carlsson71993dd2007-08-17 05:31:46 +000087 QualType Type;
88
Reid Spencer5f016e22007-07-11 17:01:13 +000089 // Read the base type.
90 switch (*Str++) {
91 default: assert(0 && "Unknown builtin type letter!");
92 case 'v':
Steve Naroffe8770422007-08-08 17:48:34 +000093 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'v'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +000094 Type = Context.VoidTy;
95 break;
Reid Spencer5f016e22007-07-11 17:01:13 +000096 case 'f':
97 assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'f'!");
Anders Carlsson71993dd2007-08-17 05:31:46 +000098 Type = Context.FloatTy;
99 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000100 case 'd':
101 assert(!LongLong && !Signed && !Unsigned && "Bad modifiers used with 'd'!");
102 if (Long)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000103 Type = Context.LongDoubleTy;
104 else
105 Type = Context.DoubleTy;
106 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000107 case 's':
108 assert(!LongLong && "Bad modifiers used with 's'!");
109 if (Unsigned)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000110 Type = Context.UnsignedShortTy;
111 else
112 Type = Context.ShortTy;
113 break;
Steve Naroffe8770422007-08-08 17:48:34 +0000114 case 'i':
115 if (Long)
Anders Carlsson71993dd2007-08-17 05:31:46 +0000116 Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
117 else if (LongLong)
118 Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
119 else if (Unsigned)
120 Type = Context.UnsignedIntTy;
121 else
122 Type = Context.IntTy; // default is signed.
123 break;
124 case 'c':
125 assert(!Long && !LongLong && "Bad modifiers used with 'c'!");
126 if (Signed)
127 Type = Context.SignedCharTy;
128 else if (Unsigned)
129 Type = Context.UnsignedCharTy;
130 else
131 Type = Context.CharTy;
132 break;
133 case 'F':
134 Type = Context.getCFConstantStringType();
135 break;
Reid Spencer5f016e22007-07-11 17:01:13 +0000136 }
Anders Carlsson71993dd2007-08-17 05:31:46 +0000137
138 Done = false;
139 while (!Done) {
140 switch (*Str++) {
141 default: Done = true; --Str; break;
142 case '*':
143 Type = Context.getPointerType(Type);
144 break;
145 case 'C':
146 Type = Type.getQualifiedType(QualType::Const);
147 break;
148 }
149 }
150
151 return Type;
Reid Spencer5f016e22007-07-11 17:01:13 +0000152}
153
154/// GetBuiltinType - Return the type for the specified builtin.
155QualType Builtin::Context::GetBuiltinType(unsigned id, ASTContext &Context)const{
156 const char *TypeStr = GetRecord(id).Type;
157
158 llvm::SmallVector<QualType, 8> ArgTypes;
159
160 QualType ResType = DecodeTypeFromStr(TypeStr, Context);
161 while (TypeStr[0] && TypeStr[0] != '.')
162 ArgTypes.push_back(DecodeTypeFromStr(TypeStr, Context));
163
164 assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
165 "'.' should only occur at end of builtin type list!");
Steve Naroffe8770422007-08-08 17:48:34 +0000166
167 // handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
168 if (ArgTypes.size() == 0 && TypeStr[0] == '.')
169 return Context.getFunctionTypeNoProto(ResType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000170 return Context.getFunctionType(ResType, &ArgTypes[0], ArgTypes.size(),
171 TypeStr[0] == '.');
172}