1194179Sed//===--- Builtins.cpp - Builtin function implementation -------------------===// 2194179Sed// 3194179Sed// The LLVM Compiler Infrastructure 4194179Sed// 5194179Sed// This file is distributed under the University of Illinois Open Source 6194179Sed// License. See LICENSE.TXT for details. 7194179Sed// 8194179Sed//===----------------------------------------------------------------------===// 9194179Sed// 10194179Sed// This file implements various things for builtin functions. 11194179Sed// 12194179Sed//===----------------------------------------------------------------------===// 13194179Sed 14194179Sed#include "clang/Basic/Builtins.h" 15194179Sed#include "clang/Basic/IdentifierTable.h" 16252723Sdim#include "clang/Basic/LangOptions.h" 17194179Sed#include "clang/Basic/TargetInfo.h" 18235633Sdim#include "llvm/ADT/SmallVector.h" 19263509Sdim#include "llvm/ADT/StringRef.h" 20194179Sedusing namespace clang; 21194179Sed 22194179Sedstatic const Builtin::Info BuiltinInfo[] = { 23224145Sdim { "not a builtin function", 0, 0, 0, ALL_LANGUAGES }, 24224145Sdim#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, 25263509Sdim#define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) { #ID, TYPE, ATTRS, 0, BUILTIN_LANG }, 26218893Sdim#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\ 27224145Sdim BUILTIN_LANG }, 28194179Sed#include "clang/Basic/Builtins.def" 29194179Sed}; 30194179Sed 31194179Sedconst Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const { 32194179Sed if (ID < Builtin::FirstTSBuiltin) 33194179Sed return BuiltinInfo[ID]; 34194179Sed assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!"); 35194179Sed return TSRecords[ID - Builtin::FirstTSBuiltin]; 36194179Sed} 37194179Sed 38226890SdimBuiltin::Context::Context() { 39194613Sed // Get the target specific builtins from the target. 40194613Sed TSRecords = 0; 41194613Sed NumTSRecords = 0; 42194613Sed} 43194613Sed 44226890Sdimvoid Builtin::Context::InitializeTarget(const TargetInfo &Target) { 45226890Sdim assert(NumTSRecords == 0 && "Already initialized target?"); 46226890Sdim Target.getTargetBuiltins(TSRecords, NumTSRecords); 47226890Sdim} 48226890Sdim 49263509Sdimbool Builtin::Context::BuiltinIsSupported(const Builtin::Info &BuiltinInfo, 50263509Sdim const LangOptions &LangOpts) { 51263509Sdim bool BuiltinsUnsupported = LangOpts.NoBuiltin && 52263509Sdim strchr(BuiltinInfo.Attributes, 'f'); 53263509Sdim bool MathBuiltinsUnsupported = 54263509Sdim LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName && 55263509Sdim llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h"); 56263509Sdim bool GnuModeUnsupported = !LangOpts.GNUMode && 57263509Sdim (BuiltinInfo.builtin_lang & GNU_LANG); 58263509Sdim bool MSModeUnsupported = !LangOpts.MicrosoftExt && 59263509Sdim (BuiltinInfo.builtin_lang & MS_LANG); 60263509Sdim bool ObjCUnsupported = !LangOpts.ObjC1 && 61263509Sdim BuiltinInfo.builtin_lang == OBJC_LANG; 62263509Sdim return !BuiltinsUnsupported && !MathBuiltinsUnsupported && 63263509Sdim !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; 64263509Sdim} 65263509Sdim 66194179Sed/// InitializeBuiltins - Mark the identifiers for all the builtins with their 67194179Sed/// appropriate builtin ID # and mark any non-portable builtin identifiers as 68194179Sed/// such. 69194179Sedvoid Builtin::Context::InitializeBuiltins(IdentifierTable &Table, 70218893Sdim const LangOptions& LangOpts) { 71194179Sed // Step #1: mark all target-independent builtins with their ID's. 72194179Sed for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) 73263509Sdim if (BuiltinIsSupported(BuiltinInfo[i], LangOpts)) { 74263509Sdim Table.get(BuiltinInfo[i].Name).setBuiltinID(i); 75218893Sdim } 76194179Sed 77194179Sed // Step #2: Register target-specific builtins. 78194179Sed for (unsigned i = 0, e = NumTSRecords; i != e; ++i) 79224145Sdim if (!LangOpts.NoBuiltin || !strchr(TSRecords[i].Attributes, 'f')) 80194179Sed Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); 81194179Sed} 82194179Sed 83198092Srdivackyvoid 84263509SdimBuiltin::Context::GetBuiltinNames(SmallVectorImpl<const char *> &Names) { 85194179Sed // Final all target-independent names 86194179Sed for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) 87263509Sdim if (!strchr(BuiltinInfo[i].Attributes, 'f')) 88194179Sed Names.push_back(BuiltinInfo[i].Name); 89198092Srdivacky 90194179Sed // Find target-specific names. 91194179Sed for (unsigned i = 0, e = NumTSRecords; i != e; ++i) 92263509Sdim if (!strchr(TSRecords[i].Attributes, 'f')) 93194179Sed Names.push_back(TSRecords[i].Name); 94194179Sed} 95194179Sed 96218893Sdimvoid Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) { 97218893Sdim Table.get(GetRecord(ID).Name).setBuiltinID(0); 98218893Sdim} 99218893Sdim 100198092Srdivackybool 101198092SrdivackyBuiltin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, 102194179Sed bool &HasVAListArg) { 103194179Sed const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP"); 104194179Sed if (!Printf) 105194179Sed return false; 106194179Sed 107194179Sed HasVAListArg = (*Printf == 'P'); 108194179Sed 109194179Sed ++Printf; 110194179Sed assert(*Printf == ':' && "p or P specifier must have be followed by a ':'"); 111194179Sed ++Printf; 112194179Sed 113194179Sed assert(strchr(Printf, ':') && "printf specifier must end with a ':'"); 114194179Sed FormatIdx = strtol(Printf, 0, 10); 115194179Sed return true; 116194179Sed} 117194179Sed 118212904Sdim// FIXME: Refactor with isPrintfLike. 119212904Sdimbool 120212904SdimBuiltin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx, 121212904Sdim bool &HasVAListArg) { 122212904Sdim const char *Scanf = strpbrk(GetRecord(ID).Attributes, "sS"); 123212904Sdim if (!Scanf) 124212904Sdim return false; 125212904Sdim 126212904Sdim HasVAListArg = (*Scanf == 'S'); 127212904Sdim 128212904Sdim ++Scanf; 129212904Sdim assert(*Scanf == ':' && "s or S specifier must have be followed by a ':'"); 130212904Sdim ++Scanf; 131212904Sdim 132212904Sdim assert(strchr(Scanf, ':') && "printf specifier must end with a ':'"); 133212904Sdim FormatIdx = strtol(Scanf, 0, 10); 134212904Sdim return true; 135212904Sdim} 136212904Sdim 137