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) < 36 (TSRecords.size() + AuxTSRecords.size())) && 37 "Invalid builtin ID!"); 38 if (isAuxBuiltinID(ID)) 39 return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin]; 40 return TSRecords[ID - Builtin::FirstTSBuiltin]; 41 } 42 43 void Builtin::Context::InitializeTarget(const TargetInfo &Target, 44 const TargetInfo *AuxTarget) { 45 assert(TSRecords.empty() && "Already initialized target?"); 46 TSRecords = Target.getTargetBuiltins(); 47 if (AuxTarget) 48 AuxTSRecords = AuxTarget->getTargetBuiltins(); 49 } 50 51 bool Builtin::Context::isBuiltinFunc(const char *Name) { 52 StringRef FuncName(Name); 53 for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i) 54 if (FuncName.equals(BuiltinInfo[i].Name)) 55 return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr; 56 57 return false; 58 } 59 60 bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo, 61 const LangOptions &LangOpts) { 62 bool BuiltinsUnsupported = 63 (LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) && 64 strchr(BuiltinInfo.Attributes, 'f'); 65 bool MathBuiltinsUnsupported = 66 LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName && 67 llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h"); 68 bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG); 69 bool MSModeUnsupported = 70 !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG); 71 bool ObjCUnsupported = !LangOpts.ObjC && BuiltinInfo.Langs == OBJC_LANG; 72 bool OclC1Unsupported = (LangOpts.OpenCLVersion / 100) != 1 && 73 (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES ) == OCLC1X_LANG; 74 bool OclC2Unsupported = LangOpts.OpenCLVersion != 200 && 75 (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES) == OCLC20_LANG; 76 bool OclCUnsupported = !LangOpts.OpenCL && 77 (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES); 78 bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG; 79 return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported && 80 !OclC1Unsupported && !OclC2Unsupported && !OpenMPUnsupported && 81 !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; 82 } 83 84 /// initializeBuiltins - Mark the identifiers for all the builtins with their 85 /// appropriate builtin ID # and mark any non-portable builtin identifiers as 86 /// such. 87 void Builtin::Context::initializeBuiltins(IdentifierTable &Table, 88 const LangOptions& LangOpts) { 89 // Step #1: mark all target-independent builtins with their ID's. 90 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) 91 if (builtinIsSupported(BuiltinInfo[i], LangOpts)) { 92 Table.get(BuiltinInfo[i].Name).setBuiltinID(i); 93 } 94 95 // Step #2: Register target-specific builtins. 96 for (unsigned i = 0, e = TSRecords.size(); i != e; ++i) 97 if (builtinIsSupported(TSRecords[i], LangOpts)) 98 Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin); 99 100 // Step #3: Register target-specific builtins for AuxTarget. 101 for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i) 102 Table.get(AuxTSRecords[i].Name) 103 .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size()); 104 } 105 106 void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) { 107 Table.get(getRecord(ID).Name).setBuiltinID(0); 108 } 109 110 unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const { 111 const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V'); 112 if (!WidthPos) 113 return 0; 114 115 ++WidthPos; 116 assert(*WidthPos == ':' && 117 "Vector width specifier must be followed by a ':'"); 118 ++WidthPos; 119 120 char *EndPos; 121 unsigned Width = ::strtol(WidthPos, &EndPos, 10); 122 assert(*EndPos == ':' && "Vector width specific must end with a ':'"); 123 return Width; 124 } 125 126 bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx, 127 bool &HasVAListArg, const char *Fmt) const { 128 assert(Fmt && "Not passed a format string"); 129 assert(::strlen(Fmt) == 2 && 130 "Format string needs to be two characters long"); 131 assert(::toupper(Fmt[0]) == Fmt[1] && 132 "Format string is not in the form \"xX\""); 133 134 const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt); 135 if (!Like) 136 return false; 137 138 HasVAListArg = (*Like == Fmt[1]); 139 140 ++Like; 141 assert(*Like == ':' && "Format specifier must be followed by a ':'"); 142 ++Like; 143 144 assert(::strchr(Like, ':') && "Format specifier must end with a ':'"); 145 FormatIdx = ::strtol(Like, nullptr, 10); 146 return true; 147 } 148 149 bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, 150 bool &HasVAListArg) { 151 return isLike(ID, FormatIdx, HasVAListArg, "pP"); 152 } 153 154 bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, 155 bool &HasVAListArg) { 156 return isLike(ID, FormatIdx, HasVAListArg, "sS"); 157 } 158 159 bool Builtin::Context::canBeRedeclared(unsigned ID) const { 160 return ID == Builtin::NotBuiltin || 161 ID == Builtin::BI__va_start || 162 (!hasReferenceArgsOrResult(ID) && 163 !hasCustomTypechecking(ID)); 164 } 165