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/LangOptions.h" 17 #include "clang/Basic/TargetInfo.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringRef.h" 20 using namespace clang; 21 22 static const Builtin::Info BuiltinInfo[] = { 23 { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES}, 24 #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, 25 #define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \ 26 { #ID, TYPE, ATTRS, 0, LANGS } \ 27 , 28 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \ 29 { #ID, TYPE, ATTRS, HEADER, LANGS } \ 30 , 31 #include "clang/Basic/Builtins.def" 32 }; 33 34 const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const { 35 if (ID < Builtin::FirstTSBuiltin) 36 return BuiltinInfo[ID]; 37 assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!"); 38 return TSRecords[ID - Builtin::FirstTSBuiltin]; 39 } 40 41 Builtin::Context::Context() { 42 // Get the target specific builtins from the target. 43 TSRecords = nullptr; 44 NumTSRecords = 0; 45 } 46 47 void Builtin::Context::InitializeTarget(const TargetInfo &Target) { 48 assert(NumTSRecords == 0 && "Already initialized target?"); 49 Target.getTargetBuiltins(TSRecords, NumTSRecords); 50 } 51 52 bool Builtin::Context::BuiltinIsSupported(const Builtin::Info &BuiltinInfo, 53 const LangOptions &LangOpts) { 54 bool BuiltinsUnsupported = LangOpts.NoBuiltin && 55 strchr(BuiltinInfo.Attributes, 'f'); 56 bool MathBuiltinsUnsupported = 57 LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName && 58 llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h"); 59 bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG); 60 bool MSModeUnsupported = 61 !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG); 62 bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG; 63 return !BuiltinsUnsupported && !MathBuiltinsUnsupported && 64 !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; 65 } 66 67 /// InitializeBuiltins - Mark the identifiers for all the builtins with their 68 /// appropriate builtin ID # and mark any non-portable builtin identifiers as 69 /// such. 70 void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, 71 const LangOptions& LangOpts) { 72 // Step #1: mark all target-independent builtins with their ID's. 73 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) 74 if (BuiltinIsSupported(BuiltinInfo[i], LangOpts)) { 75 Table.get(BuiltinInfo[i].Name).setBuiltinID(i); 76 } 77 78 // Step #2: Register target-specific builtins. 79 for (unsigned i = 0, e = NumTSRecords; i != e; ++i) 80 if (BuiltinIsSupported(TSRecords[i], LangOpts)) 81 Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); 82 } 83 84 void Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) { 85 Table.get(GetRecord(ID).Name).setBuiltinID(0); 86 } 87 88 bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx, 89 bool &HasVAListArg, const char *Fmt) const { 90 assert(Fmt && "Not passed a format string"); 91 assert(::strlen(Fmt) == 2 && 92 "Format string needs to be two characters long"); 93 assert(::toupper(Fmt[0]) == Fmt[1] && 94 "Format string is not in the form \"xX\""); 95 96 const char *Like = ::strpbrk(GetRecord(ID).Attributes, Fmt); 97 if (!Like) 98 return false; 99 100 HasVAListArg = (*Like == Fmt[1]); 101 102 ++Like; 103 assert(*Like == ':' && "Format specifier must be followed by a ':'"); 104 ++Like; 105 106 assert(::strchr(Like, ':') && "Format specifier must end with a ':'"); 107 FormatIdx = ::strtol(Like, nullptr, 10); 108 return true; 109 } 110 111 bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, 112 bool &HasVAListArg) { 113 return isLike(ID, FormatIdx, HasVAListArg, "pP"); 114 } 115 116 bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, 117 bool &HasVAListArg) { 118 return isLike(ID, FormatIdx, HasVAListArg, "sS"); 119 } 120