clang API Documentation

Builtins.cpp
Go to the documentation of this file.
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/TargetInfo.h"
00017 #include "clang/Basic/LangOptions.h"
00018 #include "llvm/ADT/SmallVector.h"
00019 using namespace clang;
00020 
00021 static const Builtin::Info BuiltinInfo[] = {
00022   { "not a builtin function", 0, 0, 0, ALL_LANGUAGES },
00023 #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
00024 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\
00025                                                             BUILTIN_LANG },
00026 #include "clang/Basic/Builtins.def"
00027 };
00028 
00029 const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
00030   if (ID < Builtin::FirstTSBuiltin)
00031     return BuiltinInfo[ID];
00032   assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
00033   return TSRecords[ID - Builtin::FirstTSBuiltin];
00034 }
00035 
00036 Builtin::Context::Context() {
00037   // Get the target specific builtins from the target.
00038   TSRecords = 0;
00039   NumTSRecords = 0;
00040 }
00041 
00042 void Builtin::Context::InitializeTarget(const TargetInfo &Target) {
00043   assert(NumTSRecords == 0 && "Already initialized target?");
00044   Target.getTargetBuiltins(TSRecords, NumTSRecords);  
00045 }
00046 
00047 /// InitializeBuiltins - Mark the identifiers for all the builtins with their
00048 /// appropriate builtin ID # and mark any non-portable builtin identifiers as
00049 /// such.
00050 void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
00051                                           const LangOptions& LangOpts) {
00052   // Step #1: mark all target-independent builtins with their ID's.
00053   for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
00054     if (!LangOpts.NoBuiltin || !strchr(BuiltinInfo[i].Attributes, 'f')) {
00055       if (LangOpts.ObjC1 || 
00056           BuiltinInfo[i].builtin_lang != clang::OBJC_LANG)
00057         Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
00058     }
00059 
00060   // Step #2: Register target-specific builtins.
00061   for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
00062     if (!LangOpts.NoBuiltin || !strchr(TSRecords[i].Attributes, 'f'))
00063       Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
00064 }
00065 
00066 void
00067 Builtin::Context::GetBuiltinNames(SmallVectorImpl<const char *> &Names,
00068                                   bool NoBuiltins) {
00069   // Final all target-independent names
00070   for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
00071     if (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f'))
00072       Names.push_back(BuiltinInfo[i].Name);
00073 
00074   // Find target-specific names.
00075   for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
00076     if (!NoBuiltins || !strchr(TSRecords[i].Attributes, 'f'))
00077       Names.push_back(TSRecords[i].Name);
00078 }
00079 
00080 void Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) {
00081   Table.get(GetRecord(ID).Name).setBuiltinID(0);
00082 }
00083 
00084 bool
00085 Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
00086                                bool &HasVAListArg) {
00087   const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
00088   if (!Printf)
00089     return false;
00090 
00091   HasVAListArg = (*Printf == 'P');
00092 
00093   ++Printf;
00094   assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
00095   ++Printf;
00096 
00097   assert(strchr(Printf, ':') && "printf specifier must end with a ':'");
00098   FormatIdx = strtol(Printf, 0, 10);
00099   return true;
00100 }
00101 
00102 // FIXME: Refactor with isPrintfLike.
00103 bool
00104 Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
00105                               bool &HasVAListArg) {
00106   const char *Scanf = strpbrk(GetRecord(ID).Attributes, "sS");
00107   if (!Scanf)
00108     return false;
00109 
00110   HasVAListArg = (*Scanf == 'S');
00111 
00112   ++Scanf;
00113   assert(*Scanf == ':' && "s or S specifier must have be followed by a ':'");
00114   ++Scanf;
00115 
00116   assert(strchr(Scanf, ':') && "printf specifier must end with a ':'");
00117   FormatIdx = strtol(Scanf, 0, 10);
00118   return true;
00119 }
00120