IntrinsicEmitter.cpp revision 223017
1135446Strhodes//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===// 2262706Serwin// 3135446Strhodes// The LLVM Compiler Infrastructure 4135446Strhodes// 5174187Sdougb// This file is distributed under the University of Illinois Open Source 6135446Strhodes// License. See LICENSE.TXT for details. 7135446Strhodes// 8135446Strhodes//===----------------------------------------------------------------------===// 9135446Strhodes// 10135446Strhodes// This tablegen backend emits information about intrinsic functions. 11135446Strhodes// 12135446Strhodes//===----------------------------------------------------------------------===// 13135446Strhodes 14135446Strhodes#include "CodeGenTarget.h" 15135446Strhodes#include "IntrinsicEmitter.h" 16135446Strhodes#include "Record.h" 17135446Strhodes#include "StringMatcher.h" 18254897Serwin#include "llvm/ADT/StringExtras.h" 19135446Strhodes#include <algorithm> 20186462Sdougbusing namespace llvm; 21135446Strhodes 22170222Sdougb//===----------------------------------------------------------------------===// 23135446Strhodes// IntrinsicEmitter Implementation 24135446Strhodes//===----------------------------------------------------------------------===// 25135446Strhodes 26135446Strhodesvoid IntrinsicEmitter::run(raw_ostream &OS) { 27135446Strhodes EmitSourceFileHeader("Intrinsic Function Source Fragment", OS); 28135446Strhodes 29135446Strhodes std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly); 30135446Strhodes 31135446Strhodes if (TargetOnly && !Ints.empty()) 32135446Strhodes TargetPrefix = Ints[0].TargetPrefix; 33135446Strhodes 34135446Strhodes EmitPrefix(OS); 35135446Strhodes 36193149Sdougb // Emit the enum information. 37193149Sdougb EmitEnumInfo(Ints, OS); 38135446Strhodes 39135446Strhodes // Emit the intrinsic ID -> name table. 40135446Strhodes EmitIntrinsicToNameTable(Ints, OS); 41135446Strhodes 42135446Strhodes // Emit the intrinsic ID -> overload table. 43135446Strhodes EmitIntrinsicToOverloadTable(Ints, OS); 44135446Strhodes 45135446Strhodes // Emit the function name recognizer. 46135446Strhodes EmitFnNameRecognizer(Ints, OS); 47135446Strhodes 48170222Sdougb // Emit the intrinsic verifier. 49135446Strhodes EmitVerifier(Ints, OS); 50135446Strhodes 51193149Sdougb // Emit the intrinsic declaration generator. 52135446Strhodes EmitGenerator(Ints, OS); 53193149Sdougb 54193149Sdougb // Emit the intrinsic parameter attributes. 55193149Sdougb EmitAttributes(Ints, OS); 56193149Sdougb 57193149Sdougb // Emit intrinsic alias analysis mod/ref behavior. 58135446Strhodes EmitModRefBehavior(Ints, OS); 59193149Sdougb 60170222Sdougb // Emit a list of intrinsics with corresponding GCC builtins. 61193149Sdougb EmitGCCBuiltinList(Ints, OS); 62193149Sdougb 63193149Sdougb // Emit code to translate GCC builtins into LLVM intrinsics. 64193149Sdougb EmitIntrinsicToGCCBuiltinMap(Ints, OS); 65193149Sdougb 66193149Sdougb EmitSuffix(OS); 67135446Strhodes} 68186462Sdougb 69135446Strhodesvoid IntrinsicEmitter::EmitPrefix(raw_ostream &OS) { 70135446Strhodes OS << "// VisualStudio defines setjmp as _setjmp\n" 71135446Strhodes "#if defined(_MSC_VER) && defined(setjmp) && \\\n" 72135446Strhodes " !defined(setjmp_undefined_for_msvc)\n" 73135446Strhodes "# pragma push_macro(\"setjmp\")\n" 74193149Sdougb "# undef setjmp\n" 75193149Sdougb "# define setjmp_undefined_for_msvc\n" 76193149Sdougb "#endif\n\n"; 77135446Strhodes} 78170222Sdougb 79193149Sdougbvoid IntrinsicEmitter::EmitSuffix(raw_ostream &OS) { 80193149Sdougb OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n" 81193149Sdougb "// let's return it to _setjmp state\n" 82135446Strhodes "# pragma pop_macro(\"setjmp\")\n" 83193149Sdougb "# undef setjmp_undefined_for_msvc\n" 84193149Sdougb "#endif\n\n"; 85193149Sdougb} 86135446Strhodes 87193149Sdougbvoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, 88193149Sdougb raw_ostream &OS) { 89135446Strhodes OS << "// Enum values for Intrinsics.h\n"; 90193149Sdougb OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; 91135446Strhodes for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 92254402Serwin OS << " " << Ints[i].EnumName; 93135446Strhodes OS << ((i != e-1) ? ", " : " "); 94135446Strhodes OS << std::string(40-Ints[i].EnumName.size(), ' ') 95135446Strhodes << "// " << Ints[i].Name << "\n"; 96135446Strhodes } 97170222Sdougb OS << "#endif\n\n"; 98135446Strhodes} 99135446Strhodes 100135446Strhodesvoid IntrinsicEmitter:: 101135446StrhodesEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 102170222Sdougb raw_ostream &OS) { 103135446Strhodes // Build a 'first character of function name' -> intrinsic # mapping. 104193149Sdougb std::map<char, std::vector<unsigned> > IntMapping; 105135446Strhodes for (unsigned i = 0, e = Ints.size(); i != e; ++i) 106193149Sdougb IntMapping[Ints[i].Name[5]].push_back(i); 107193149Sdougb 108186462Sdougb OS << "// Function name -> enum value recognizer code.\n"; 109193149Sdougb OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; 110193149Sdougb OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n"; 111135446Strhodes OS << " switch (Name[5]) { // Dispatch on first letter.\n"; 112193149Sdougb OS << " default: break;\n"; 113193149Sdougb // Emit the intrinsic matching stuff by first letter. 114245163Serwin for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(), 115135446Strhodes E = IntMapping.end(); I != E; ++I) { 116193149Sdougb OS << " case '" << I->first << "':\n"; 117193149Sdougb std::vector<unsigned> &IntList = I->second; 118135446Strhodes 119193149Sdougb // Emit all the overloaded intrinsics first, build a table of the 120193149Sdougb // non-overloaded ones. 121135446Strhodes std::vector<StringMatcher::StringPair> MatchTable; 122193149Sdougb 123193149Sdougb for (unsigned i = 0, e = IntList.size(); i != e; ++i) { 124193149Sdougb unsigned IntNo = IntList[i]; 125193149Sdougb std::string Result = "return " + TargetPrefix + "Intrinsic::" + 126193149Sdougb Ints[IntNo].EnumName + ";"; 127193149Sdougb 128193149Sdougb if (!Ints[IntNo].isOverloaded) { 129193149Sdougb MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result)); 130193149Sdougb continue; 131170222Sdougb } 132135446Strhodes 133135446Strhodes // For overloaded intrinsics, only the prefix needs to match 134135446Strhodes std::string TheStr = Ints[IntNo].Name.substr(6); 135135446Strhodes TheStr += '.'; // Require "bswap." instead of bswap. 136224092Sdougb OS << " if (NameR.startswith(\"" << TheStr << "\")) " 137224092Sdougb << Result << '\n'; 138224092Sdougb } 139224092Sdougb 140224092Sdougb // Emit the matcher logic for the fixed length strings. 141224092Sdougb StringMatcher("NameR", MatchTable, OS).Emit(1); 142224092Sdougb OS << " break; // end of '" << I->first << "' case.\n"; 143224092Sdougb } 144135446Strhodes 145170222Sdougb OS << " }\n"; 146224092Sdougb OS << "#endif\n\n"; 147135446Strhodes} 148135446Strhodes 149135446Strhodesvoid IntrinsicEmitter:: 150224092SdougbEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, 151224092Sdougb raw_ostream &OS) { 152224092Sdougb OS << "// Intrinsic ID to name table\n"; 153224092Sdougb OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n"; 154224092Sdougb OS << " // Note that entry #0 is the invalid intrinsic!\n"; 155224092Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) 156224092Sdougb OS << " \"" << Ints[i].Name << "\",\n"; 157224092Sdougb OS << "#endif\n\n"; 158135446Strhodes} 159193149Sdougb 160193149Sdougbvoid IntrinsicEmitter:: 161193149SdougbEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, 162193149Sdougb raw_ostream &OS) { 163224092Sdougb OS << "// Intrinsic ID to overload table\n"; 164224092Sdougb OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; 165224092Sdougb OS << " // Note that entry #0 is the invalid intrinsic!\n"; 166224092Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 167135446Strhodes OS << " "; 168135446Strhodes if (Ints[i].isOverloaded) 169135446Strhodes OS << "true"; 170135446Strhodes else 171135446Strhodes OS << "false"; 172135446Strhodes OS << ",\n"; 173170222Sdougb } 174135446Strhodes OS << "#endif\n\n"; 175193149Sdougb} 176193149Sdougb 177193149Sdougbstatic void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) { 178193149Sdougb if (EVT(VT).isInteger()) { 179193149Sdougb unsigned BitWidth = EVT(VT).getSizeInBits(); 180193149Sdougb OS << "IntegerType::get(Context, " << BitWidth << ")"; 181193149Sdougb } else if (VT == MVT::Other) { 182193149Sdougb // MVT::OtherVT is used to mean the empty struct type here. 183193149Sdougb OS << "StructType::get(Context)"; 184193149Sdougb } else if (VT == MVT::f32) { 185193149Sdougb OS << "Type::getFloatTy(Context)"; 186193149Sdougb } else if (VT == MVT::f64) { 187193149Sdougb OS << "Type::getDoubleTy(Context)"; 188193149Sdougb } else if (VT == MVT::f80) { 189193149Sdougb OS << "Type::getX86_FP80Ty(Context)"; 190193149Sdougb } else if (VT == MVT::f128) { 191193149Sdougb OS << "Type::getFP128Ty(Context)"; 192193149Sdougb } else if (VT == MVT::ppcf128) { 193193149Sdougb OS << "Type::getPPC_FP128Ty(Context)"; 194193149Sdougb } else if (VT == MVT::isVoid) { 195193149Sdougb OS << "Type::getVoidTy(Context)"; 196193149Sdougb } else if (VT == MVT::Metadata) { 197135446Strhodes OS << "Type::getMetadataTy(Context)"; 198135446Strhodes } else if (VT == MVT::x86mmx) { 199170222Sdougb OS << "Type::getX86_MMXTy(Context)"; 200135446Strhodes } else { 201193149Sdougb assert(false && "Unsupported ValueType!"); 202193149Sdougb } 203193149Sdougb} 204275672Sdelphij 205135446Strhodesstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, 206135446Strhodes unsigned &ArgNo); 207170222Sdougb 208135446Strhodesstatic void EmitTypeGenerate(raw_ostream &OS, 209135446Strhodes const std::vector<Record*> &ArgTypes, 210135446Strhodes unsigned &ArgNo) { 211135446Strhodes if (ArgTypes.empty()) 212135446Strhodes return EmitTypeForValueType(OS, MVT::isVoid); 213193149Sdougb 214193149Sdougb if (ArgTypes.size() == 1) 215193149Sdougb return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); 216135446Strhodes 217135446Strhodes OS << "StructType::get(Context, "; 218170222Sdougb 219170222Sdougb for (std::vector<Record*>::const_iterator 220135446Strhodes I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) { 221135446Strhodes EmitTypeGenerate(OS, *I, ArgNo); 222135446Strhodes OS << ", "; 223170222Sdougb } 224193149Sdougb 225135446Strhodes OS << " NULL)"; 226193149Sdougb} 227193149Sdougb 228193149Sdougbstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, 229135446Strhodes unsigned &ArgNo) { 230193149Sdougb MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 231135446Strhodes 232135446Strhodes if (ArgType->isSubClassOf("LLVMMatchType")) { 233170222Sdougb unsigned Number = ArgType->getValueAsInt("Number"); 234135446Strhodes assert(Number < ArgNo && "Invalid matching number!"); 235135446Strhodes if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 236135446Strhodes OS << "VectorType::getExtendedElementVectorType" 237135446Strhodes << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; 238135446Strhodes else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 239193149Sdougb OS << "VectorType::getTruncatedElementVectorType" 240135446Strhodes << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; 241193149Sdougb else 242193149Sdougb OS << "Tys[" << Number << "]"; 243135446Strhodes } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) { 244193149Sdougb // NOTE: The ArgNo variable here is not the absolute argument number, it is 245193149Sdougb // the index of the "arbitrary" type in the Tys array passed to the 246193149Sdougb // Intrinsic::getDeclaration function. Consequently, we only want to 247135446Strhodes // increment it when we actually hit an overloaded type. Getting this wrong 248193149Sdougb // leads to very subtle bugs! 249170222Sdougb OS << "Tys[" << ArgNo++ << "]"; 250135446Strhodes } else if (EVT(VT).isVector()) { 251135446Strhodes EVT VVT = VT; 252135446Strhodes OS << "VectorType::get("; 253135446Strhodes EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy); 254135446Strhodes OS << ", " << VVT.getVectorNumElements() << ")"; 255135446Strhodes } else if (VT == MVT::iPTR) { 256135446Strhodes OS << "PointerType::getUnqual("; 257193149Sdougb EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); 258193149Sdougb OS << ")"; 259234010Sdougb } else if (VT == MVT::iPTRAny) { 260135446Strhodes // Make sure the user has passed us an argument type to overload. If not, 261135446Strhodes // treat it as an ordinary (not overloaded) intrinsic. 262135446Strhodes OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo 263135446Strhodes << "] : PointerType::getUnqual("; 264135446Strhodes EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); 265135446Strhodes OS << ")"; 266135446Strhodes ++ArgNo; 267135446Strhodes } else if (VT == MVT::isVoid) { 268135446Strhodes if (ArgNo == 0) 269135446Strhodes OS << "Type::getVoidTy(Context)"; 270170222Sdougb else 271170222Sdougb // MVT::isVoid is used to mean varargs here. 272170222Sdougb OS << "..."; 273135446Strhodes } else { 274135446Strhodes EmitTypeForValueType(OS, VT); 275135446Strhodes } 276135446Strhodes} 277135446Strhodes 278135446Strhodes/// RecordListComparator - Provide a deterministic comparator for lists of 279135446Strhodes/// records. 280135446Strhodesnamespace { 281135446Strhodes typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair; 282135446Strhodes struct RecordListComparator { 283135446Strhodes bool operator()(const RecPair &LHS, 284193149Sdougb const RecPair &RHS) const { 285193149Sdougb unsigned i = 0; 286143731Sdougb const std::vector<Record*> *LHSVec = &LHS.first; 287135446Strhodes const std::vector<Record*> *RHSVec = &RHS.first; 288135446Strhodes unsigned RHSSize = RHSVec->size(); 289135446Strhodes unsigned LHSSize = LHSVec->size(); 290135446Strhodes 291135446Strhodes for (; i != LHSSize; ++i) { 292135446Strhodes if (i == RHSSize) return false; // RHS is shorter than LHS. 293135446Strhodes if ((*LHSVec)[i] != (*RHSVec)[i]) 294135446Strhodes return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); 295135446Strhodes } 296135446Strhodes 297135446Strhodes if (i != RHSSize) return true; 298135446Strhodes 299214586Sdougb i = 0; 300214586Sdougb LHSVec = &LHS.second; 301135446Strhodes RHSVec = &RHS.second; 302135446Strhodes RHSSize = RHSVec->size(); 303135446Strhodes LHSSize = LHSVec->size(); 304135446Strhodes 305275672Sdelphij for (i = 0; i != LHSSize; ++i) { 306193149Sdougb if (i == RHSSize) return false; // RHS is shorter than LHS. 307193149Sdougb if ((*LHSVec)[i] != (*RHSVec)[i]) 308193149Sdougb return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); 309135446Strhodes } 310135446Strhodes 311135446Strhodes return i != RHSSize; 312135446Strhodes } 313275672Sdelphij }; 314135446Strhodes} 315135446Strhodes 316135446Strhodesvoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, 317135446Strhodes raw_ostream &OS) { 318135446Strhodes OS << "// Verifier::visitIntrinsicFunctionCall code.\n"; 319135446Strhodes OS << "#ifdef GET_INTRINSIC_VERIFIER\n"; 320135446Strhodes OS << " switch (ID) {\n"; 321135446Strhodes OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; 322135446Strhodes 323143731Sdougb // This checking can emit a lot of very common code. To reduce the amount of 324143731Sdougb // code that we emit, batch up cases that have identical types. This avoids 325135446Strhodes // problems where GCC can run out of memory compiling Verifier.cpp. 326135446Strhodes typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; 327135446Strhodes MapTy UniqueArgInfos; 328135446Strhodes 329193149Sdougb // Compute the unique argument type info. 330193149Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) 331193149Sdougb UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, 332193149Sdougb Ints[i].IS.ParamTypeDefs)].push_back(i); 333135446Strhodes 334193149Sdougb // Loop through the array, emitting one comparison for each batch. 335193149Sdougb for (MapTy::iterator I = UniqueArgInfos.begin(), 336193149Sdougb E = UniqueArgInfos.end(); I != E; ++I) { 337193149Sdougb for (unsigned i = 0, e = I->second.size(); i != e; ++i) 338193149Sdougb OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// " 339193149Sdougb << Ints[I->second[i]].Name << "\n"; 340193149Sdougb 341193149Sdougb const RecPair &ArgTypes = I->first; 342193149Sdougb const std::vector<Record*> &RetTys = ArgTypes.first; 343135446Strhodes const std::vector<Record*> &ParamTys = ArgTypes.second; 344135446Strhodes std::vector<unsigned> OverloadedTypeIndices; 345193149Sdougb 346193149Sdougb OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", " 347193149Sdougb << ParamTys.size(); 348193149Sdougb 349193149Sdougb // Emit return types. 350193149Sdougb for (unsigned j = 0, je = RetTys.size(); j != je; ++j) { 351135446Strhodes Record *ArgType = RetTys[j]; 352135446Strhodes OS << ", "; 353135446Strhodes 354193149Sdougb if (ArgType->isSubClassOf("LLVMMatchType")) { 355193149Sdougb unsigned Number = ArgType->getValueAsInt("Number"); 356193149Sdougb assert(Number < OverloadedTypeIndices.size() && 357135446Strhodes "Invalid matching number!"); 358135446Strhodes Number = OverloadedTypeIndices[Number]; 359135446Strhodes if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 360135446Strhodes OS << "~(ExtendedElementVectorType | " << Number << ")"; 361135446Strhodes else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 362135446Strhodes OS << "~(TruncatedElementVectorType | " << Number << ")"; 363135446Strhodes else 364135446Strhodes OS << "~" << Number; 365193149Sdougb } else { 366193149Sdougb MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 367193149Sdougb OS << getEnumName(VT); 368193149Sdougb 369193149Sdougb if (EVT(VT).isOverloaded()) 370135446Strhodes OverloadedTypeIndices.push_back(j); 371135446Strhodes 372135446Strhodes if (VT == MVT::isVoid && j != 0 && j != je - 1) 373135446Strhodes throw "Var arg type not last argument"; 374193149Sdougb } 375193149Sdougb } 376193149Sdougb 377135446Strhodes // Emit the parameter types. 378193149Sdougb for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) { 379135446Strhodes Record *ArgType = ParamTys[j]; 380193149Sdougb OS << ", "; 381193149Sdougb 382193149Sdougb if (ArgType->isSubClassOf("LLVMMatchType")) { 383193149Sdougb unsigned Number = ArgType->getValueAsInt("Number"); 384135446Strhodes assert(Number < OverloadedTypeIndices.size() && 385135446Strhodes "Invalid matching number!"); 386135446Strhodes Number = OverloadedTypeIndices[Number]; 387135446Strhodes if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 388135446Strhodes OS << "~(ExtendedElementVectorType | " << Number << ")"; 389193149Sdougb else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 390193149Sdougb OS << "~(TruncatedElementVectorType | " << Number << ")"; 391135446Strhodes else 392193149Sdougb OS << "~" << Number; 393135446Strhodes } else { 394135446Strhodes MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 395135446Strhodes OS << getEnumName(VT); 396135446Strhodes 397135446Strhodes if (EVT(VT).isOverloaded()) 398135446Strhodes OverloadedTypeIndices.push_back(j + RetTys.size()); 399135446Strhodes 400135446Strhodes if (VT == MVT::isVoid && j != 0 && j != je - 1) 401135446Strhodes throw "Var arg type not last argument"; 402135446Strhodes } 403135446Strhodes } 404135446Strhodes 405193149Sdougb OS << ");\n"; 406193149Sdougb OS << " break;\n"; 407193149Sdougb } 408193149Sdougb OS << " }\n"; 409193149Sdougb OS << "#endif\n\n"; 410135446Strhodes} 411193149Sdougb 412135446Strhodesvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 413193149Sdougb raw_ostream &OS) { 414135446Strhodes OS << "// Code for generating Intrinsic function declarations.\n"; 415193149Sdougb OS << "#ifdef GET_INTRINSIC_GENERATOR\n"; 416135446Strhodes OS << " switch (id) {\n"; 417193149Sdougb OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; 418135446Strhodes 419135446Strhodes // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical 420135446Strhodes // types. 421135446Strhodes typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; 422135446Strhodes MapTy UniqueArgInfos; 423135446Strhodes 424135446Strhodes // Compute the unique argument type info. 425193149Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) 426193149Sdougb UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, 427193149Sdougb Ints[i].IS.ParamTypeDefs)].push_back(i); 428193149Sdougb 429193149Sdougb // Loop through the array, emitting one generator for each batch. 430193149Sdougb std::string IntrinsicStr = TargetPrefix + "Intrinsic::"; 431193149Sdougb 432193149Sdougb for (MapTy::iterator I = UniqueArgInfos.begin(), 433135446Strhodes E = UniqueArgInfos.end(); I != E; ++I) { 434135446Strhodes for (unsigned i = 0, e = I->second.size(); i != e; ++i) 435135446Strhodes OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName 436135446Strhodes << ":\t\t// " << Ints[I->second[i]].Name << "\n"; 437135446Strhodes 438135446Strhodes const RecPair &ArgTypes = I->first; 439135446Strhodes const std::vector<Record*> &RetTys = ArgTypes.first; 440135446Strhodes const std::vector<Record*> &ParamTys = ArgTypes.second; 441135446Strhodes 442135446Strhodes unsigned N = ParamTys.size(); 443135446Strhodes 444193149Sdougb if (N > 1 && 445135446Strhodes getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) { 446135446Strhodes OS << " IsVarArg = true;\n"; 447135446Strhodes --N; 448135446Strhodes } 449135446Strhodes 450135446Strhodes unsigned ArgNo = 0; 451135446Strhodes OS << " ResultTy = "; 452135446Strhodes EmitTypeGenerate(OS, RetTys, ArgNo); 453193149Sdougb OS << ";\n"; 454135446Strhodes 455135446Strhodes for (unsigned j = 0; j != N; ++j) { 456135446Strhodes OS << " ArgTys.push_back("; 457135446Strhodes EmitTypeGenerate(OS, ParamTys[j], ArgNo); 458135446Strhodes OS << ");\n"; 459135446Strhodes } 460135446Strhodes 461135446Strhodes OS << " break;\n"; 462135446Strhodes } 463135446Strhodes 464135446Strhodes OS << " }\n"; 465135446Strhodes OS << "#endif\n\n"; 466135446Strhodes} 467135446Strhodes 468135446Strhodesnamespace { 469135446Strhodes enum ModRefKind { 470193149Sdougb MRK_none, 471193149Sdougb MRK_readonly, 472193149Sdougb MRK_readnone 473193149Sdougb }; 474193149Sdougb 475193149Sdougb ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { 476193149Sdougb switch (intrinsic.ModRef) { 477193149Sdougb case CodeGenIntrinsic::NoMem: 478193149Sdougb return MRK_readnone; 479135446Strhodes case CodeGenIntrinsic::ReadArgMem: 480135446Strhodes case CodeGenIntrinsic::ReadMem: 481135446Strhodes return MRK_readonly; 482135446Strhodes case CodeGenIntrinsic::ReadWriteArgMem: 483135446Strhodes case CodeGenIntrinsic::ReadWriteMem: 484135446Strhodes return MRK_none; 485135446Strhodes } 486135446Strhodes assert(0 && "bad mod-ref kind"); 487135446Strhodes return MRK_none; 488135446Strhodes } 489135446Strhodes 490224092Sdougb struct AttributeComparator { 491224092Sdougb bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { 492224092Sdougb // Sort throwing intrinsics after non-throwing intrinsics. 493224092Sdougb if (L->canThrow != R->canThrow) 494224092Sdougb return R->canThrow; 495224092Sdougb 496224092Sdougb // Try to order by readonly/readnone attribute. 497224092Sdougb ModRefKind LK = getModRefKind(*L); 498224092Sdougb ModRefKind RK = getModRefKind(*R); 499224092Sdougb if (LK != RK) return (LK > RK); 500224092Sdougb 501224092Sdougb // Order by argument attributes. 502224092Sdougb // This is reliable because each side is already sorted internally. 503224092Sdougb return (L->ArgumentAttributes < R->ArgumentAttributes); 504224092Sdougb } 505224092Sdougb }; 506224092Sdougb} 507224092Sdougb 508224092Sdougb/// EmitAttributes - This emits the Intrinsic::getAttributes method. 509224092Sdougbvoid IntrinsicEmitter:: 510224092SdougbEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { 511224092Sdougb OS << "// Add parameter attributes that are not common to all intrinsics.\n"; 512224092Sdougb OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; 513224092Sdougb if (TargetOnly) 514224092Sdougb OS << "static AttrListPtr getAttributes(" << TargetPrefix 515224092Sdougb << "Intrinsic::ID id) {\n"; 516224092Sdougb else 517224092Sdougb OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n"; 518224092Sdougb 519224092Sdougb // Compute the maximum number of attribute arguments. 520224092Sdougb std::vector<const CodeGenIntrinsic*> sortedIntrinsics(Ints.size()); 521224092Sdougb unsigned maxArgAttrs = 0; 522254402Serwin for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 523254402Serwin const CodeGenIntrinsic &intrinsic = Ints[i]; 524254402Serwin sortedIntrinsics[i] = &intrinsic; 525224092Sdougb maxArgAttrs = 526224092Sdougb std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size())); 527224092Sdougb } 528224092Sdougb 529224092Sdougb // Emit an array of AttributeWithIndex. Most intrinsics will have 530224092Sdougb // at least one entry, for the function itself (index ~1), which is 531224092Sdougb // usually nounwind. 532224092Sdougb OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; 533224092Sdougb OS << " unsigned NumAttrs = 0;\n"; 534224092Sdougb OS << " switch (id) {\n"; 535224092Sdougb OS << " default: break;\n"; 536224092Sdougb 537224092Sdougb AttributeComparator precedes; 538224092Sdougb 539224092Sdougb std::stable_sort(sortedIntrinsics.begin(), sortedIntrinsics.end(), precedes); 540224092Sdougb 541224092Sdougb for (unsigned i = 0, e = sortedIntrinsics.size(); i != e; ++i) { 542224092Sdougb const CodeGenIntrinsic &intrinsic = *sortedIntrinsics[i]; 543224092Sdougb OS << " case " << TargetPrefix << "Intrinsic::" 544224092Sdougb << intrinsic.EnumName << ":\n"; 545224092Sdougb 546224092Sdougb // Fill out the case if this is the last case for this range of 547224092Sdougb // intrinsics. 548224092Sdougb if (i + 1 != e && !precedes(&intrinsic, sortedIntrinsics[i + 1])) 549224092Sdougb continue; 550224092Sdougb 551224092Sdougb // Keep track of the number of attributes we're writing out. 552224092Sdougb unsigned numAttrs = 0; 553224092Sdougb 554224092Sdougb // The argument attributes are alreadys sorted by argument index. 555224092Sdougb for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) { 556224092Sdougb unsigned argNo = intrinsic.ArgumentAttributes[ai].first; 557224092Sdougb 558224092Sdougb OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(" 559224092Sdougb << argNo+1 << ", "; 560224092Sdougb 561224092Sdougb bool moreThanOne = false; 562224092Sdougb 563224092Sdougb do { 564224092Sdougb if (moreThanOne) OS << '|'; 565224092Sdougb 566224092Sdougb switch (intrinsic.ArgumentAttributes[ai].second) { 567224092Sdougb case CodeGenIntrinsic::NoCapture: 568224092Sdougb OS << "Attribute::NoCapture"; 569224092Sdougb break; 570224092Sdougb } 571224092Sdougb 572224092Sdougb ++ai; 573224092Sdougb moreThanOne = true; 574224092Sdougb } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo); 575224092Sdougb 576224092Sdougb OS << ");\n"; 577224092Sdougb } 578224092Sdougb 579224092Sdougb ModRefKind modRef = getModRefKind(intrinsic); 580224092Sdougb 581224092Sdougb if (!intrinsic.canThrow || modRef) { 582224092Sdougb OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, "; 583224092Sdougb if (!intrinsic.canThrow) { 584224092Sdougb OS << "Attribute::NoUnwind"; 585224092Sdougb if (modRef) OS << '|'; 586224092Sdougb } 587224092Sdougb switch (modRef) { 588224092Sdougb case MRK_none: break; 589224092Sdougb case MRK_readonly: OS << "Attribute::ReadOnly"; break; 590224092Sdougb case MRK_readnone: OS << "Attribute::ReadNone"; break; 591224092Sdougb } 592224092Sdougb OS << ");\n"; 593224092Sdougb } 594224092Sdougb 595224092Sdougb if (numAttrs) { 596224092Sdougb OS << " NumAttrs = " << numAttrs << ";\n"; 597224092Sdougb OS << " break;\n"; 598224092Sdougb } else { 599224092Sdougb OS << " return AttrListPtr();\n"; 600224092Sdougb } 601224092Sdougb } 602224092Sdougb 603224092Sdougb OS << " }\n"; 604224092Sdougb OS << " return AttrListPtr::get(AWI, NumAttrs);\n"; 605224092Sdougb OS << "}\n"; 606224092Sdougb OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; 607224092Sdougb} 608224092Sdougb 609224092Sdougb/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. 610224092Sdougbvoid IntrinsicEmitter:: 611224092SdougbEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ 612224092Sdougb OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"; 613224092Sdougb OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"; 614224092Sdougb OS << "switch (iid) {\n"; 615224092Sdougb OS << "default:\n return UnknownModRefBehavior;\n"; 616224092Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 617224092Sdougb if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem) 618224092Sdougb continue; 619224092Sdougb OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 620224092Sdougb << ":\n"; 621224092Sdougb switch (Ints[i].ModRef) { 622224092Sdougb default: 623224092Sdougb assert(false && "Unknown Mod/Ref type!"); 624224092Sdougb case CodeGenIntrinsic::NoMem: 625224092Sdougb OS << " return DoesNotAccessMemory;\n"; 626224092Sdougb break; 627224092Sdougb case CodeGenIntrinsic::ReadArgMem: 628224092Sdougb OS << " return OnlyReadsArgumentPointees;\n"; 629224092Sdougb break; 630224092Sdougb case CodeGenIntrinsic::ReadMem: 631224092Sdougb OS << " return OnlyReadsMemory;\n"; 632224092Sdougb break; 633224092Sdougb case CodeGenIntrinsic::ReadWriteArgMem: 634224092Sdougb OS << " return OnlyAccessesArgumentPointees;\n"; 635224092Sdougb break; 636224092Sdougb } 637224092Sdougb } 638224092Sdougb OS << "}\n"; 639224092Sdougb OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; 640224092Sdougb} 641224092Sdougb 642224092Sdougbvoid IntrinsicEmitter:: 643224092SdougbEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ 644224092Sdougb OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n"; 645224092Sdougb OS << "#ifdef GET_GCC_BUILTIN_NAME\n"; 646224092Sdougb OS << " switch (F->getIntrinsicID()) {\n"; 647224092Sdougb OS << " default: BuiltinName = \"\"; break;\n"; 648224092Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 649224092Sdougb if (!Ints[i].GCCBuiltinName.empty()) { 650224092Sdougb OS << " case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \"" 651224092Sdougb << Ints[i].GCCBuiltinName << "\"; break;\n"; 652254402Serwin } 653224092Sdougb } 654224092Sdougb OS << " }\n"; 655224092Sdougb OS << "#endif\n\n"; 656224092Sdougb} 657224092Sdougb 658224092Sdougb/// EmitTargetBuiltins - All of the builtins in the specified map are for the 659224092Sdougb/// same target, and we already checked it. 660224092Sdougbstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, 661224092Sdougb const std::string &TargetPrefix, 662224092Sdougb raw_ostream &OS) { 663224092Sdougb 664224092Sdougb std::vector<StringMatcher::StringPair> Results; 665224092Sdougb 666224092Sdougb for (std::map<std::string, std::string>::const_iterator I = BIM.begin(), 667224092Sdougb E = BIM.end(); I != E; ++I) { 668224092Sdougb std::string ResultCode = 669224092Sdougb "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; 670224092Sdougb Results.push_back(StringMatcher::StringPair(I->first, ResultCode)); 671224092Sdougb } 672224092Sdougb 673224092Sdougb StringMatcher("BuiltinName", Results, OS).Emit(); 674224092Sdougb} 675224092Sdougb 676224092Sdougb 677254402Serwinvoid IntrinsicEmitter:: 678254402SerwinEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, 679254402Serwin raw_ostream &OS) { 680224092Sdougb typedef std::map<std::string, std::map<std::string, std::string> > BIMTy; 681224092Sdougb BIMTy BuiltinMap; 682224092Sdougb for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 683224092Sdougb if (!Ints[i].GCCBuiltinName.empty()) { 684224092Sdougb // Get the map for this target prefix. 685224092Sdougb std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix]; 686224092Sdougb 687224092Sdougb if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName, 688224092Sdougb Ints[i].EnumName)).second) 689224092Sdougb throw "Intrinsic '" + Ints[i].TheDef->getName() + 690224092Sdougb "': duplicate GCC builtin name!"; 691224092Sdougb } 692224092Sdougb } 693224092Sdougb 694224092Sdougb OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n"; 695224092Sdougb OS << "// This is used by the C front-end. The GCC builtin name is passed\n"; 696224092Sdougb OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n"; 697224092Sdougb OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n"; 698224092Sdougb OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n"; 699224092Sdougb 700224092Sdougb if (TargetOnly) { 701224092Sdougb OS << "static " << TargetPrefix << "Intrinsic::ID " 702224092Sdougb << "getIntrinsicForGCCBuiltin(const char " 703224092Sdougb << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; 704224092Sdougb } else { 705224092Sdougb OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " 706224092Sdougb << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; 707224092Sdougb } 708224092Sdougb 709224092Sdougb OS << " StringRef BuiltinName(BuiltinNameStr);\n"; 710224092Sdougb OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n"; 711224092Sdougb 712224092Sdougb // Note: this could emit significantly better code if we cared. 713224092Sdougb for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ 714224092Sdougb OS << " "; 715224092Sdougb if (!I->first.empty()) 716224092Sdougb OS << "if (TargetPrefix == \"" << I->first << "\") "; 717224092Sdougb else 718224092Sdougb OS << "/* Target Independent Builtins */ "; 719224092Sdougb OS << "{\n"; 720224092Sdougb 721224092Sdougb // Emit the comparisons for this target prefix. 722224092Sdougb EmitTargetBuiltins(I->second, TargetPrefix, OS); 723224092Sdougb OS << " }\n"; 724224092Sdougb } 725224092Sdougb OS << " return "; 726224092Sdougb if (!TargetPrefix.empty()) 727224092Sdougb OS << "(" << TargetPrefix << "Intrinsic::ID)"; 728224092Sdougb OS << "Intrinsic::not_intrinsic;\n"; 729224092Sdougb OS << "}\n"; 730224092Sdougb OS << "#endif\n\n"; 731224092Sdougb} 732224092Sdougb