1*67e74705SXin Li //===--- Builtins.cpp - Builtin function implementation -------------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file implements various things for builtin functions.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "clang/Basic/Builtins.h"
15*67e74705SXin Li #include "clang/Basic/IdentifierTable.h"
16*67e74705SXin Li #include "clang/Basic/LangOptions.h"
17*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
18*67e74705SXin Li #include "llvm/ADT/StringRef.h"
19*67e74705SXin Li using namespace clang;
20*67e74705SXin Li
21*67e74705SXin Li static const Builtin::Info BuiltinInfo[] = {
22*67e74705SXin Li { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES,nullptr},
23*67e74705SXin Li #define BUILTIN(ID, TYPE, ATTRS) \
24*67e74705SXin Li { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
25*67e74705SXin Li #define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \
26*67e74705SXin Li { #ID, TYPE, ATTRS, nullptr, LANGS, nullptr },
27*67e74705SXin Li #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \
28*67e74705SXin Li { #ID, TYPE, ATTRS, HEADER, LANGS, nullptr },
29*67e74705SXin Li #include "clang/Basic/Builtins.def"
30*67e74705SXin Li };
31*67e74705SXin Li
getRecord(unsigned ID) const32*67e74705SXin Li const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {
33*67e74705SXin Li if (ID < Builtin::FirstTSBuiltin)
34*67e74705SXin Li return BuiltinInfo[ID];
35*67e74705SXin Li assert(((ID - Builtin::FirstTSBuiltin) <
36*67e74705SXin Li (TSRecords.size() + AuxTSRecords.size())) &&
37*67e74705SXin Li "Invalid builtin ID!");
38*67e74705SXin Li if (isAuxBuiltinID(ID))
39*67e74705SXin Li return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];
40*67e74705SXin Li return TSRecords[ID - Builtin::FirstTSBuiltin];
41*67e74705SXin Li }
42*67e74705SXin Li
InitializeTarget(const TargetInfo & Target,const TargetInfo * AuxTarget)43*67e74705SXin Li void Builtin::Context::InitializeTarget(const TargetInfo &Target,
44*67e74705SXin Li const TargetInfo *AuxTarget) {
45*67e74705SXin Li assert(TSRecords.empty() && "Already initialized target?");
46*67e74705SXin Li TSRecords = Target.getTargetBuiltins();
47*67e74705SXin Li if (AuxTarget)
48*67e74705SXin Li AuxTSRecords = AuxTarget->getTargetBuiltins();
49*67e74705SXin Li }
50*67e74705SXin Li
isBuiltinFunc(const char * Name)51*67e74705SXin Li bool Builtin::Context::isBuiltinFunc(const char *Name) {
52*67e74705SXin Li StringRef FuncName(Name);
53*67e74705SXin Li for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i)
54*67e74705SXin Li if (FuncName.equals(BuiltinInfo[i].Name))
55*67e74705SXin Li return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
56*67e74705SXin Li
57*67e74705SXin Li return false;
58*67e74705SXin Li }
59*67e74705SXin Li
builtinIsSupported(const Builtin::Info & BuiltinInfo,const LangOptions & LangOpts)60*67e74705SXin Li bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
61*67e74705SXin Li const LangOptions &LangOpts) {
62*67e74705SXin Li bool BuiltinsUnsupported =
63*67e74705SXin Li (LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) &&
64*67e74705SXin Li strchr(BuiltinInfo.Attributes, 'f');
65*67e74705SXin Li bool MathBuiltinsUnsupported =
66*67e74705SXin Li LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
67*67e74705SXin Li llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h");
68*67e74705SXin Li bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG);
69*67e74705SXin Li bool MSModeUnsupported =
70*67e74705SXin Li !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
71*67e74705SXin Li bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
72*67e74705SXin Li bool OclCUnsupported = LangOpts.OpenCLVersion != 200 &&
73*67e74705SXin Li BuiltinInfo.Langs == OCLC20_LANG;
74*67e74705SXin Li return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&
75*67e74705SXin Li !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;
76*67e74705SXin Li }
77*67e74705SXin Li
78*67e74705SXin Li /// initializeBuiltins - Mark the identifiers for all the builtins with their
79*67e74705SXin Li /// appropriate builtin ID # and mark any non-portable builtin identifiers as
80*67e74705SXin Li /// such.
initializeBuiltins(IdentifierTable & Table,const LangOptions & LangOpts)81*67e74705SXin Li void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
82*67e74705SXin Li const LangOptions& LangOpts) {
83*67e74705SXin Li // Step #1: mark all target-independent builtins with their ID's.
84*67e74705SXin Li for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
85*67e74705SXin Li if (builtinIsSupported(BuiltinInfo[i], LangOpts)) {
86*67e74705SXin Li Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li // Step #2: Register target-specific builtins.
90*67e74705SXin Li for (unsigned i = 0, e = TSRecords.size(); i != e; ++i)
91*67e74705SXin Li if (builtinIsSupported(TSRecords[i], LangOpts))
92*67e74705SXin Li Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin);
93*67e74705SXin Li
94*67e74705SXin Li // Step #3: Register target-specific builtins for AuxTarget.
95*67e74705SXin Li for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i)
96*67e74705SXin Li Table.get(AuxTSRecords[i].Name)
97*67e74705SXin Li .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());
98*67e74705SXin Li }
99*67e74705SXin Li
forgetBuiltin(unsigned ID,IdentifierTable & Table)100*67e74705SXin Li void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) {
101*67e74705SXin Li Table.get(getRecord(ID).Name).setBuiltinID(0);
102*67e74705SXin Li }
103*67e74705SXin Li
isLike(unsigned ID,unsigned & FormatIdx,bool & HasVAListArg,const char * Fmt) const104*67e74705SXin Li bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
105*67e74705SXin Li bool &HasVAListArg, const char *Fmt) const {
106*67e74705SXin Li assert(Fmt && "Not passed a format string");
107*67e74705SXin Li assert(::strlen(Fmt) == 2 &&
108*67e74705SXin Li "Format string needs to be two characters long");
109*67e74705SXin Li assert(::toupper(Fmt[0]) == Fmt[1] &&
110*67e74705SXin Li "Format string is not in the form \"xX\"");
111*67e74705SXin Li
112*67e74705SXin Li const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt);
113*67e74705SXin Li if (!Like)
114*67e74705SXin Li return false;
115*67e74705SXin Li
116*67e74705SXin Li HasVAListArg = (*Like == Fmt[1]);
117*67e74705SXin Li
118*67e74705SXin Li ++Like;
119*67e74705SXin Li assert(*Like == ':' && "Format specifier must be followed by a ':'");
120*67e74705SXin Li ++Like;
121*67e74705SXin Li
122*67e74705SXin Li assert(::strchr(Like, ':') && "Format specifier must end with a ':'");
123*67e74705SXin Li FormatIdx = ::strtol(Like, nullptr, 10);
124*67e74705SXin Li return true;
125*67e74705SXin Li }
126*67e74705SXin Li
isPrintfLike(unsigned ID,unsigned & FormatIdx,bool & HasVAListArg)127*67e74705SXin Li bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
128*67e74705SXin Li bool &HasVAListArg) {
129*67e74705SXin Li return isLike(ID, FormatIdx, HasVAListArg, "pP");
130*67e74705SXin Li }
131*67e74705SXin Li
isScanfLike(unsigned ID,unsigned & FormatIdx,bool & HasVAListArg)132*67e74705SXin Li bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
133*67e74705SXin Li bool &HasVAListArg) {
134*67e74705SXin Li return isLike(ID, FormatIdx, HasVAListArg, "sS");
135*67e74705SXin Li }
136