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