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