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