1*0fca6ea1SDimitry Andric //=- ClangBuiltinsEmitter.cpp - Generate Clang builtins tables -*- C++ -*-====// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This tablegen backend emits Clang's builtins tables. 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "TableGenBackends.h" 14*0fca6ea1SDimitry Andric #include "llvm/ADT/StringSwitch.h" 15*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 16*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 17*0fca6ea1SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric using namespace llvm; 20*0fca6ea1SDimitry Andric 21*0fca6ea1SDimitry Andric namespace { 22*0fca6ea1SDimitry Andric enum class BuiltinType { 23*0fca6ea1SDimitry Andric Builtin, 24*0fca6ea1SDimitry Andric AtomicBuiltin, 25*0fca6ea1SDimitry Andric LibBuiltin, 26*0fca6ea1SDimitry Andric LangBuiltin, 27*0fca6ea1SDimitry Andric TargetBuiltin, 28*0fca6ea1SDimitry Andric }; 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric class PrototypeParser { 31*0fca6ea1SDimitry Andric public: 32*0fca6ea1SDimitry Andric PrototypeParser(StringRef Substitution, const Record *Builtin) 33*0fca6ea1SDimitry Andric : Loc(Builtin->getFieldLoc("Prototype")), Substitution(Substitution) { 34*0fca6ea1SDimitry Andric ParsePrototype(Builtin->getValueAsString("Prototype")); 35*0fca6ea1SDimitry Andric } 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric private: 38*0fca6ea1SDimitry Andric void ParsePrototype(StringRef Prototype) { 39*0fca6ea1SDimitry Andric Prototype = Prototype.trim(); 40*0fca6ea1SDimitry Andric ParseTypes(Prototype); 41*0fca6ea1SDimitry Andric } 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric void ParseTypes(StringRef &Prototype) { 44*0fca6ea1SDimitry Andric auto ReturnType = Prototype.take_until([](char c) { return c == '('; }); 45*0fca6ea1SDimitry Andric ParseType(ReturnType); 46*0fca6ea1SDimitry Andric Prototype = Prototype.drop_front(ReturnType.size() + 1); 47*0fca6ea1SDimitry Andric if (!Prototype.ends_with(")")) 48*0fca6ea1SDimitry Andric PrintFatalError(Loc, "Expected closing brace at end of prototype"); 49*0fca6ea1SDimitry Andric Prototype = Prototype.drop_back(); 50*0fca6ea1SDimitry Andric 51*0fca6ea1SDimitry Andric // Look through the input parameters. 52*0fca6ea1SDimitry Andric const size_t end = Prototype.size(); 53*0fca6ea1SDimitry Andric for (size_t I = 0; I != end;) { 54*0fca6ea1SDimitry Andric const StringRef Current = Prototype.substr(I, end); 55*0fca6ea1SDimitry Andric // Skip any leading space or commas 56*0fca6ea1SDimitry Andric if (Current.starts_with(" ") || Current.starts_with(",")) { 57*0fca6ea1SDimitry Andric ++I; 58*0fca6ea1SDimitry Andric continue; 59*0fca6ea1SDimitry Andric } 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric // Check if we are in _ExtVector. We do this first because 62*0fca6ea1SDimitry Andric // extended vectors are written in template form with the syntax 63*0fca6ea1SDimitry Andric // _ExtVector< ..., ...>, so we need to make sure we are not 64*0fca6ea1SDimitry Andric // detecting the comma of the template class as a separator for 65*0fca6ea1SDimitry Andric // the parameters of the prototype. Note: the assumption is that 66*0fca6ea1SDimitry Andric // we cannot have nested _ExtVector. 67*0fca6ea1SDimitry Andric if (Current.starts_with("_ExtVector<")) { 68*0fca6ea1SDimitry Andric const size_t EndTemplate = Current.find('>', 0); 69*0fca6ea1SDimitry Andric ParseType(Current.substr(0, EndTemplate + 1)); 70*0fca6ea1SDimitry Andric // Move the prototype beyond _ExtVector<...> 71*0fca6ea1SDimitry Andric I += EndTemplate + 1; 72*0fca6ea1SDimitry Andric continue; 73*0fca6ea1SDimitry Andric } 74*0fca6ea1SDimitry Andric 75*0fca6ea1SDimitry Andric // We know that we are past _ExtVector, therefore the first seen 76*0fca6ea1SDimitry Andric // comma is the boundary of a parameter in the prototype. 77*0fca6ea1SDimitry Andric if (size_t CommaPos = Current.find(',', 0)) { 78*0fca6ea1SDimitry Andric if (CommaPos != StringRef::npos) { 79*0fca6ea1SDimitry Andric StringRef T = Current.substr(0, CommaPos); 80*0fca6ea1SDimitry Andric ParseType(T); 81*0fca6ea1SDimitry Andric // Move the prototype beyond the comma. 82*0fca6ea1SDimitry Andric I += CommaPos + 1; 83*0fca6ea1SDimitry Andric continue; 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric } 86*0fca6ea1SDimitry Andric 87*0fca6ea1SDimitry Andric // No more commas, parse final parameter. 88*0fca6ea1SDimitry Andric ParseType(Current); 89*0fca6ea1SDimitry Andric I = end; 90*0fca6ea1SDimitry Andric } 91*0fca6ea1SDimitry Andric } 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric void ParseType(StringRef T) { 94*0fca6ea1SDimitry Andric T = T.trim(); 95*0fca6ea1SDimitry Andric if (T.consume_back("*")) { 96*0fca6ea1SDimitry Andric ParseType(T); 97*0fca6ea1SDimitry Andric Type += "*"; 98*0fca6ea1SDimitry Andric } else if (T.consume_back("const")) { 99*0fca6ea1SDimitry Andric ParseType(T); 100*0fca6ea1SDimitry Andric Type += "C"; 101*0fca6ea1SDimitry Andric } else if (T.consume_back("volatile")) { 102*0fca6ea1SDimitry Andric ParseType(T); 103*0fca6ea1SDimitry Andric Type += "D"; 104*0fca6ea1SDimitry Andric } else if (T.consume_back("restrict")) { 105*0fca6ea1SDimitry Andric ParseType(T); 106*0fca6ea1SDimitry Andric Type += "R"; 107*0fca6ea1SDimitry Andric } else if (T.consume_back("&")) { 108*0fca6ea1SDimitry Andric ParseType(T); 109*0fca6ea1SDimitry Andric Type += "&"; 110*0fca6ea1SDimitry Andric } else if (T.consume_front("long")) { 111*0fca6ea1SDimitry Andric Type += "L"; 112*0fca6ea1SDimitry Andric ParseType(T); 113*0fca6ea1SDimitry Andric } else if (T.consume_front("unsigned")) { 114*0fca6ea1SDimitry Andric Type += "U"; 115*0fca6ea1SDimitry Andric ParseType(T); 116*0fca6ea1SDimitry Andric } else if (T.consume_front("_Complex")) { 117*0fca6ea1SDimitry Andric Type += "X"; 118*0fca6ea1SDimitry Andric ParseType(T); 119*0fca6ea1SDimitry Andric } else if (T.consume_front("_Constant")) { 120*0fca6ea1SDimitry Andric Type += "I"; 121*0fca6ea1SDimitry Andric ParseType(T); 122*0fca6ea1SDimitry Andric } else if (T.consume_front("T")) { 123*0fca6ea1SDimitry Andric if (Substitution.empty()) 124*0fca6ea1SDimitry Andric PrintFatalError(Loc, "Not a template"); 125*0fca6ea1SDimitry Andric ParseType(Substitution); 126*0fca6ea1SDimitry Andric } else if (T.consume_front("_ExtVector")) { 127*0fca6ea1SDimitry Andric // Clang extended vector types are mangled as follows: 128*0fca6ea1SDimitry Andric // 129*0fca6ea1SDimitry Andric // '_ExtVector<' <lanes> ',' <scalar type> '>' 130*0fca6ea1SDimitry Andric 131*0fca6ea1SDimitry Andric // Before parsing T(=<scalar type>), make sure the syntax of 132*0fca6ea1SDimitry Andric // `_ExtVector<N, T>` is correct... 133*0fca6ea1SDimitry Andric if (!T.consume_front("<")) 134*0fca6ea1SDimitry Andric PrintFatalError(Loc, "Expected '<' after '_ExtVector'"); 135*0fca6ea1SDimitry Andric unsigned long long Lanes; 136*0fca6ea1SDimitry Andric if (llvm::consumeUnsignedInteger(T, 10, Lanes)) 137*0fca6ea1SDimitry Andric PrintFatalError(Loc, "Expected number of lanes after '_ExtVector<'"); 138*0fca6ea1SDimitry Andric Type += "E" + std::to_string(Lanes); 139*0fca6ea1SDimitry Andric if (!T.consume_front(",")) 140*0fca6ea1SDimitry Andric PrintFatalError(Loc, 141*0fca6ea1SDimitry Andric "Expected ',' after number of lanes in '_ExtVector<'"); 142*0fca6ea1SDimitry Andric if (!T.consume_back(">")) 143*0fca6ea1SDimitry Andric PrintFatalError( 144*0fca6ea1SDimitry Andric Loc, "Expected '>' after scalar type in '_ExtVector<N, type>'"); 145*0fca6ea1SDimitry Andric 146*0fca6ea1SDimitry Andric // ...all good, we can check if we have a valid `<scalar type>`. 147*0fca6ea1SDimitry Andric ParseType(T); 148*0fca6ea1SDimitry Andric } else { 149*0fca6ea1SDimitry Andric auto ReturnTypeVal = StringSwitch<std::string>(T) 150*0fca6ea1SDimitry Andric .Case("__builtin_va_list_ref", "A") 151*0fca6ea1SDimitry Andric .Case("__builtin_va_list", "a") 152*0fca6ea1SDimitry Andric .Case("__float128", "LLd") 153*0fca6ea1SDimitry Andric .Case("__fp16", "h") 154*0fca6ea1SDimitry Andric .Case("__int128_t", "LLLi") 155*0fca6ea1SDimitry Andric .Case("_Float16", "x") 156*0fca6ea1SDimitry Andric .Case("bool", "b") 157*0fca6ea1SDimitry Andric .Case("char", "c") 158*0fca6ea1SDimitry Andric .Case("constant_CFString", "F") 159*0fca6ea1SDimitry Andric .Case("double", "d") 160*0fca6ea1SDimitry Andric .Case("FILE", "P") 161*0fca6ea1SDimitry Andric .Case("float", "f") 162*0fca6ea1SDimitry Andric .Case("id", "G") 163*0fca6ea1SDimitry Andric .Case("int", "i") 164*0fca6ea1SDimitry Andric .Case("int32_t", "Zi") 165*0fca6ea1SDimitry Andric .Case("int64_t", "Wi") 166*0fca6ea1SDimitry Andric .Case("jmp_buf", "J") 167*0fca6ea1SDimitry Andric .Case("msint32_t", "Ni") 168*0fca6ea1SDimitry Andric .Case("msuint32_t", "UNi") 169*0fca6ea1SDimitry Andric .Case("objc_super", "M") 170*0fca6ea1SDimitry Andric .Case("pid_t", "p") 171*0fca6ea1SDimitry Andric .Case("ptrdiff_t", "Y") 172*0fca6ea1SDimitry Andric .Case("SEL", "H") 173*0fca6ea1SDimitry Andric .Case("short", "s") 174*0fca6ea1SDimitry Andric .Case("sigjmp_buf", "SJ") 175*0fca6ea1SDimitry Andric .Case("size_t", "z") 176*0fca6ea1SDimitry Andric .Case("ucontext_t", "K") 177*0fca6ea1SDimitry Andric .Case("uint32_t", "UZi") 178*0fca6ea1SDimitry Andric .Case("uint64_t", "UWi") 179*0fca6ea1SDimitry Andric .Case("void", "v") 180*0fca6ea1SDimitry Andric .Case("wchar_t", "w") 181*0fca6ea1SDimitry Andric .Case("...", ".") 182*0fca6ea1SDimitry Andric .Default("error"); 183*0fca6ea1SDimitry Andric if (ReturnTypeVal == "error") 184*0fca6ea1SDimitry Andric PrintFatalError(Loc, "Unknown Type: " + T); 185*0fca6ea1SDimitry Andric Type += ReturnTypeVal; 186*0fca6ea1SDimitry Andric } 187*0fca6ea1SDimitry Andric } 188*0fca6ea1SDimitry Andric 189*0fca6ea1SDimitry Andric public: 190*0fca6ea1SDimitry Andric void Print(llvm::raw_ostream &OS) const { OS << ", \"" << Type << '\"'; } 191*0fca6ea1SDimitry Andric 192*0fca6ea1SDimitry Andric private: 193*0fca6ea1SDimitry Andric SMLoc Loc; 194*0fca6ea1SDimitry Andric StringRef Substitution; 195*0fca6ea1SDimitry Andric std::string Type; 196*0fca6ea1SDimitry Andric }; 197*0fca6ea1SDimitry Andric 198*0fca6ea1SDimitry Andric class HeaderNameParser { 199*0fca6ea1SDimitry Andric public: 200*0fca6ea1SDimitry Andric HeaderNameParser(const Record *Builtin) { 201*0fca6ea1SDimitry Andric for (char c : Builtin->getValueAsString("Header")) { 202*0fca6ea1SDimitry Andric if (std::islower(c)) 203*0fca6ea1SDimitry Andric HeaderName += static_cast<char>(std::toupper(c)); 204*0fca6ea1SDimitry Andric else if (c == '.' || c == '_' || c == '/' || c == '-') 205*0fca6ea1SDimitry Andric HeaderName += '_'; 206*0fca6ea1SDimitry Andric else 207*0fca6ea1SDimitry Andric PrintFatalError(Builtin->getLoc(), "Unexpected header name"); 208*0fca6ea1SDimitry Andric } 209*0fca6ea1SDimitry Andric } 210*0fca6ea1SDimitry Andric 211*0fca6ea1SDimitry Andric void Print(llvm::raw_ostream &OS) const { OS << HeaderName; } 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric private: 214*0fca6ea1SDimitry Andric std::string HeaderName; 215*0fca6ea1SDimitry Andric }; 216*0fca6ea1SDimitry Andric 217*0fca6ea1SDimitry Andric void PrintAttributes(const Record *Builtin, BuiltinType BT, 218*0fca6ea1SDimitry Andric llvm::raw_ostream &OS) { 219*0fca6ea1SDimitry Andric OS << '\"'; 220*0fca6ea1SDimitry Andric if (Builtin->isSubClassOf("LibBuiltin")) { 221*0fca6ea1SDimitry Andric if (BT == BuiltinType::LibBuiltin) { 222*0fca6ea1SDimitry Andric OS << 'f'; 223*0fca6ea1SDimitry Andric } else { 224*0fca6ea1SDimitry Andric OS << 'F'; 225*0fca6ea1SDimitry Andric if (Builtin->getValueAsBit("OnlyBuiltinPrefixedAliasIsConstexpr")) 226*0fca6ea1SDimitry Andric OS << 'E'; 227*0fca6ea1SDimitry Andric } 228*0fca6ea1SDimitry Andric } 229*0fca6ea1SDimitry Andric 230*0fca6ea1SDimitry Andric if (auto NS = Builtin->getValueAsOptionalString("Namespace")) { 231*0fca6ea1SDimitry Andric if (NS != "std") 232*0fca6ea1SDimitry Andric PrintFatalError(Builtin->getFieldLoc("Namespace"), "Unknown namespace: "); 233*0fca6ea1SDimitry Andric OS << "z"; 234*0fca6ea1SDimitry Andric } 235*0fca6ea1SDimitry Andric 236*0fca6ea1SDimitry Andric for (const auto *Attr : Builtin->getValueAsListOfDefs("Attributes")) { 237*0fca6ea1SDimitry Andric OS << Attr->getValueAsString("Mangling"); 238*0fca6ea1SDimitry Andric if (Attr->isSubClassOf("IndexedAttribute")) 239*0fca6ea1SDimitry Andric OS << ':' << Attr->getValueAsInt("Index") << ':'; 240*0fca6ea1SDimitry Andric } 241*0fca6ea1SDimitry Andric OS << '\"'; 242*0fca6ea1SDimitry Andric } 243*0fca6ea1SDimitry Andric 244*0fca6ea1SDimitry Andric void EmitBuiltinDef(llvm::raw_ostream &OS, StringRef Substitution, 245*0fca6ea1SDimitry Andric const Record *Builtin, Twine Spelling, BuiltinType BT) { 246*0fca6ea1SDimitry Andric if (Builtin->getValueAsBit("RequiresUndef")) 247*0fca6ea1SDimitry Andric OS << "#undef " << Spelling << '\n'; 248*0fca6ea1SDimitry Andric switch (BT) { 249*0fca6ea1SDimitry Andric case BuiltinType::LibBuiltin: 250*0fca6ea1SDimitry Andric OS << "LIBBUILTIN"; 251*0fca6ea1SDimitry Andric break; 252*0fca6ea1SDimitry Andric case BuiltinType::LangBuiltin: 253*0fca6ea1SDimitry Andric OS << "LANGBUILTIN"; 254*0fca6ea1SDimitry Andric break; 255*0fca6ea1SDimitry Andric case BuiltinType::Builtin: 256*0fca6ea1SDimitry Andric OS << "BUILTIN"; 257*0fca6ea1SDimitry Andric break; 258*0fca6ea1SDimitry Andric case BuiltinType::AtomicBuiltin: 259*0fca6ea1SDimitry Andric OS << "ATOMIC_BUILTIN"; 260*0fca6ea1SDimitry Andric break; 261*0fca6ea1SDimitry Andric case BuiltinType::TargetBuiltin: 262*0fca6ea1SDimitry Andric OS << "TARGET_BUILTIN"; 263*0fca6ea1SDimitry Andric break; 264*0fca6ea1SDimitry Andric } 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric OS << "(" << Spelling; 267*0fca6ea1SDimitry Andric PrototypeParser{Substitution, Builtin}.Print(OS); 268*0fca6ea1SDimitry Andric OS << ", "; 269*0fca6ea1SDimitry Andric PrintAttributes(Builtin, BT, OS); 270*0fca6ea1SDimitry Andric 271*0fca6ea1SDimitry Andric switch (BT) { 272*0fca6ea1SDimitry Andric case BuiltinType::LibBuiltin: { 273*0fca6ea1SDimitry Andric OS << ", "; 274*0fca6ea1SDimitry Andric HeaderNameParser{Builtin}.Print(OS); 275*0fca6ea1SDimitry Andric [[fallthrough]]; 276*0fca6ea1SDimitry Andric } 277*0fca6ea1SDimitry Andric case BuiltinType::LangBuiltin: { 278*0fca6ea1SDimitry Andric OS << ", " << Builtin->getValueAsString("Languages"); 279*0fca6ea1SDimitry Andric break; 280*0fca6ea1SDimitry Andric } 281*0fca6ea1SDimitry Andric case BuiltinType::TargetBuiltin: 282*0fca6ea1SDimitry Andric OS << ", \"" << Builtin->getValueAsString("Features") << "\""; 283*0fca6ea1SDimitry Andric break; 284*0fca6ea1SDimitry Andric case BuiltinType::AtomicBuiltin: 285*0fca6ea1SDimitry Andric case BuiltinType::Builtin: 286*0fca6ea1SDimitry Andric break; 287*0fca6ea1SDimitry Andric } 288*0fca6ea1SDimitry Andric OS << ")\n"; 289*0fca6ea1SDimitry Andric } 290*0fca6ea1SDimitry Andric 291*0fca6ea1SDimitry Andric struct TemplateInsts { 292*0fca6ea1SDimitry Andric std::vector<std::string> Substitution; 293*0fca6ea1SDimitry Andric std::vector<std::string> Affix; 294*0fca6ea1SDimitry Andric bool IsPrefix; 295*0fca6ea1SDimitry Andric }; 296*0fca6ea1SDimitry Andric 297*0fca6ea1SDimitry Andric TemplateInsts getTemplateInsts(const Record *R) { 298*0fca6ea1SDimitry Andric TemplateInsts temp; 299*0fca6ea1SDimitry Andric auto Substitutions = R->getValueAsListOfStrings("Substitutions"); 300*0fca6ea1SDimitry Andric auto Affixes = R->getValueAsListOfStrings("Affixes"); 301*0fca6ea1SDimitry Andric temp.IsPrefix = R->getValueAsBit("AsPrefix"); 302*0fca6ea1SDimitry Andric 303*0fca6ea1SDimitry Andric if (Substitutions.size() != Affixes.size()) 304*0fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), "Substitutions and affixes " 305*0fca6ea1SDimitry Andric "don't have the same lengths"); 306*0fca6ea1SDimitry Andric 307*0fca6ea1SDimitry Andric for (auto [Affix, Substitution] : llvm::zip(Affixes, Substitutions)) { 308*0fca6ea1SDimitry Andric temp.Substitution.emplace_back(Substitution); 309*0fca6ea1SDimitry Andric temp.Affix.emplace_back(Affix); 310*0fca6ea1SDimitry Andric } 311*0fca6ea1SDimitry Andric return temp; 312*0fca6ea1SDimitry Andric } 313*0fca6ea1SDimitry Andric 314*0fca6ea1SDimitry Andric void EmitBuiltin(llvm::raw_ostream &OS, const Record *Builtin) { 315*0fca6ea1SDimitry Andric TemplateInsts Templates = {}; 316*0fca6ea1SDimitry Andric if (Builtin->isSubClassOf("Template")) { 317*0fca6ea1SDimitry Andric Templates = getTemplateInsts(Builtin); 318*0fca6ea1SDimitry Andric } else { 319*0fca6ea1SDimitry Andric Templates.Affix.emplace_back(); 320*0fca6ea1SDimitry Andric Templates.Substitution.emplace_back(); 321*0fca6ea1SDimitry Andric } 322*0fca6ea1SDimitry Andric 323*0fca6ea1SDimitry Andric for (auto [Substitution, Affix] : 324*0fca6ea1SDimitry Andric llvm::zip(Templates.Substitution, Templates.Affix)) { 325*0fca6ea1SDimitry Andric for (StringRef Spelling : Builtin->getValueAsListOfStrings("Spellings")) { 326*0fca6ea1SDimitry Andric auto FullSpelling = 327*0fca6ea1SDimitry Andric (Templates.IsPrefix ? Affix + Spelling : Spelling + Affix).str(); 328*0fca6ea1SDimitry Andric BuiltinType BT = BuiltinType::Builtin; 329*0fca6ea1SDimitry Andric if (Builtin->isSubClassOf("AtomicBuiltin")) { 330*0fca6ea1SDimitry Andric BT = BuiltinType::AtomicBuiltin; 331*0fca6ea1SDimitry Andric } else if (Builtin->isSubClassOf("LangBuiltin")) { 332*0fca6ea1SDimitry Andric BT = BuiltinType::LangBuiltin; 333*0fca6ea1SDimitry Andric } else if (Builtin->isSubClassOf("TargetBuiltin")) { 334*0fca6ea1SDimitry Andric BT = BuiltinType::TargetBuiltin; 335*0fca6ea1SDimitry Andric } else if (Builtin->isSubClassOf("LibBuiltin")) { 336*0fca6ea1SDimitry Andric BT = BuiltinType::LibBuiltin; 337*0fca6ea1SDimitry Andric if (Builtin->getValueAsBit("AddBuiltinPrefixedAlias")) 338*0fca6ea1SDimitry Andric EmitBuiltinDef(OS, Substitution, Builtin, 339*0fca6ea1SDimitry Andric std::string("__builtin_") + FullSpelling, 340*0fca6ea1SDimitry Andric BuiltinType::Builtin); 341*0fca6ea1SDimitry Andric } 342*0fca6ea1SDimitry Andric EmitBuiltinDef(OS, Substitution, Builtin, FullSpelling, BT); 343*0fca6ea1SDimitry Andric } 344*0fca6ea1SDimitry Andric } 345*0fca6ea1SDimitry Andric } 346*0fca6ea1SDimitry Andric } // namespace 347*0fca6ea1SDimitry Andric 348*0fca6ea1SDimitry Andric void clang::EmitClangBuiltins(llvm::RecordKeeper &Records, 349*0fca6ea1SDimitry Andric llvm::raw_ostream &OS) { 350*0fca6ea1SDimitry Andric emitSourceFileHeader("List of builtins that Clang recognizes", OS); 351*0fca6ea1SDimitry Andric 352*0fca6ea1SDimitry Andric OS << R"c++( 353*0fca6ea1SDimitry Andric #if defined(BUILTIN) && !defined(LIBBUILTIN) 354*0fca6ea1SDimitry Andric # define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) 355*0fca6ea1SDimitry Andric #endif 356*0fca6ea1SDimitry Andric 357*0fca6ea1SDimitry Andric #if defined(BUILTIN) && !defined(LANGBUILTIN) 358*0fca6ea1SDimitry Andric # define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) 359*0fca6ea1SDimitry Andric #endif 360*0fca6ea1SDimitry Andric 361*0fca6ea1SDimitry Andric // Some of our atomics builtins are handled by AtomicExpr rather than 362*0fca6ea1SDimitry Andric // as normal builtin CallExprs. This macro is used for such builtins. 363*0fca6ea1SDimitry Andric #ifndef ATOMIC_BUILTIN 364*0fca6ea1SDimitry Andric # define ATOMIC_BUILTIN(ID, TYPE, ATTRS) BUILTIN(ID, TYPE, ATTRS) 365*0fca6ea1SDimitry Andric #endif 366*0fca6ea1SDimitry Andric 367*0fca6ea1SDimitry Andric #if defined(BUILTIN) && !defined(TARGET_BUILTIN) 368*0fca6ea1SDimitry Andric # define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) 369*0fca6ea1SDimitry Andric #endif 370*0fca6ea1SDimitry Andric )c++"; 371*0fca6ea1SDimitry Andric 372*0fca6ea1SDimitry Andric // AtomicBuiltins are order dependent 373*0fca6ea1SDimitry Andric // emit them first to make manual checking easier 374*0fca6ea1SDimitry Andric for (const auto *Builtin : Records.getAllDerivedDefinitions("AtomicBuiltin")) 375*0fca6ea1SDimitry Andric EmitBuiltin(OS, Builtin); 376*0fca6ea1SDimitry Andric 377*0fca6ea1SDimitry Andric for (const auto *Builtin : Records.getAllDerivedDefinitions("Builtin")) { 378*0fca6ea1SDimitry Andric if (Builtin->isSubClassOf("AtomicBuiltin")) 379*0fca6ea1SDimitry Andric continue; 380*0fca6ea1SDimitry Andric EmitBuiltin(OS, Builtin); 381*0fca6ea1SDimitry Andric } 382*0fca6ea1SDimitry Andric 383*0fca6ea1SDimitry Andric for (const auto *Entry : Records.getAllDerivedDefinitions("CustomEntry")) { 384*0fca6ea1SDimitry Andric OS << Entry->getValueAsString("Entry") << '\n'; 385*0fca6ea1SDimitry Andric } 386*0fca6ea1SDimitry Andric 387*0fca6ea1SDimitry Andric OS << R"c++( 388*0fca6ea1SDimitry Andric #undef ATOMIC_BUILTIN 389*0fca6ea1SDimitry Andric #undef BUILTIN 390*0fca6ea1SDimitry Andric #undef LIBBUILTIN 391*0fca6ea1SDimitry Andric #undef LANGBUILTIN 392*0fca6ea1SDimitry Andric #undef TARGET_BUILTIN 393*0fca6ea1SDimitry Andric )c++"; 394*0fca6ea1SDimitry Andric } 395