clang API Documentation
00001 //===--- Builtins.cpp - Builtin function implementation -------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements various things for builtin functions. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Basic/Builtins.h" 00015 #include "clang/Basic/IdentifierTable.h" 00016 #include "clang/Basic/LangOptions.h" 00017 #include "clang/Basic/TargetInfo.h" 00018 #include "llvm/ADT/SmallVector.h" 00019 #include "llvm/ADT/StringRef.h" 00020 using namespace clang; 00021 00022 static const Builtin::Info BuiltinInfo[] = { 00023 { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES}, 00024 #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, 00025 #define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) { #ID, TYPE, ATTRS, 0, BUILTIN_LANG }, 00026 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\ 00027 BUILTIN_LANG }, 00028 #include "clang/Basic/Builtins.def" 00029 }; 00030 00031 const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const { 00032 if (ID < Builtin::FirstTSBuiltin) 00033 return BuiltinInfo[ID]; 00034 assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!"); 00035 return TSRecords[ID - Builtin::FirstTSBuiltin]; 00036 } 00037 00038 Builtin::Context::Context() { 00039 // Get the target specific builtins from the target. 00040 TSRecords = nullptr; 00041 NumTSRecords = 0; 00042 } 00043 00044 void Builtin::Context::InitializeTarget(const TargetInfo &Target) { 00045 assert(NumTSRecords == 0 && "Already initialized target?"); 00046 Target.getTargetBuiltins(TSRecords, NumTSRecords); 00047 } 00048 00049 bool Builtin::Context::BuiltinIsSupported(const Builtin::Info &BuiltinInfo, 00050 const LangOptions &LangOpts) { 00051 bool BuiltinsUnsupported = LangOpts.NoBuiltin && 00052 strchr(BuiltinInfo.Attributes, 'f'); 00053 bool MathBuiltinsUnsupported = 00054 LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName && 00055 llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h"); 00056 bool GnuModeUnsupported = !LangOpts.GNUMode && 00057 (BuiltinInfo.builtin_lang & GNU_LANG); 00058 bool MSModeUnsupported = !LangOpts.MicrosoftExt && 00059 (BuiltinInfo.builtin_lang & MS_LANG); 00060 bool ObjCUnsupported = !LangOpts.ObjC1 && 00061 BuiltinInfo.builtin_lang == OBJC_LANG; 00062 return !BuiltinsUnsupported && !MathBuiltinsUnsupported && 00063 !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; 00064 } 00065 00066 /// InitializeBuiltins - Mark the identifiers for all the builtins with their 00067 /// appropriate builtin ID # and mark any non-portable builtin identifiers as 00068 /// such. 00069 void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, 00070 const LangOptions& LangOpts) { 00071 // Step #1: mark all target-independent builtins with their ID's. 00072 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) 00073 if (BuiltinIsSupported(BuiltinInfo[i], LangOpts)) { 00074 Table.get(BuiltinInfo[i].Name).setBuiltinID(i); 00075 } 00076 00077 // Step #2: Register target-specific builtins. 00078 for (unsigned i = 0, e = NumTSRecords; i != e; ++i) 00079 if (BuiltinIsSupported(TSRecords[i], LangOpts)) 00080 Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); 00081 } 00082 00083 void 00084 Builtin::Context::GetBuiltinNames(SmallVectorImpl<const char *> &Names) { 00085 // Final all target-independent names 00086 for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) 00087 if (!strchr(BuiltinInfo[i].Attributes, 'f')) 00088 Names.push_back(BuiltinInfo[i].Name); 00089 00090 // Find target-specific names. 00091 for (unsigned i = 0, e = NumTSRecords; i != e; ++i) 00092 if (!strchr(TSRecords[i].Attributes, 'f')) 00093 Names.push_back(TSRecords[i].Name); 00094 } 00095 00096 void Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) { 00097 Table.get(GetRecord(ID).Name).setBuiltinID(0); 00098 } 00099 00100 bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx, 00101 bool &HasVAListArg, const char *Fmt) const { 00102 assert(Fmt && "Not passed a format string"); 00103 assert(::strlen(Fmt) == 2 && 00104 "Format string needs to be two characters long"); 00105 assert(::toupper(Fmt[0]) == Fmt[1] && 00106 "Format string is not in the form \"xX\""); 00107 00108 const char *Like = ::strpbrk(GetRecord(ID).Attributes, Fmt); 00109 if (!Like) 00110 return false; 00111 00112 HasVAListArg = (*Like == Fmt[1]); 00113 00114 ++Like; 00115 assert(*Like == ':' && "Format specifier must be followed by a ':'"); 00116 ++Like; 00117 00118 assert(::strchr(Like, ':') && "Format specifier must end with a ':'"); 00119 FormatIdx = ::strtol(Like, nullptr, 10); 00120 return true; 00121 } 00122 00123 bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, 00124 bool &HasVAListArg) { 00125 return isLike(ID, FormatIdx, HasVAListArg, "pP"); 00126 } 00127 00128 bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, 00129 bool &HasVAListArg) { 00130 return isLike(ID, FormatIdx, HasVAListArg, "sS"); 00131 }