IntrinsicEmitter.cpp revision da4231f134989af7dc6bd3408821ba573def27b2
19e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===// 29e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// 39e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// The LLVM Compiler Infrastructure 49e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// 53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// This file is distributed under the University of Illinois Open Source 63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// License. See LICENSE.TXT for details. 79e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// 89e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===// 99e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// 109e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// This tablegen backend emits information about intrinsic functions. 119e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// 129e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===// 139e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner 146994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth#include "CodeGenTarget.h" 159e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "IntrinsicEmitter.h" 169e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "Record.h" 1718faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner#include "llvm/ADT/StringExtras.h" 1871c3bc3d966bd874f760abf055c559673f925029Jeff Cohen#include <algorithm> 199e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnerusing namespace llvm; 209e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner 219e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===// 229e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// IntrinsicEmitter Implementation 239e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===// 249e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner 259e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::run(std::ostream &OS) { 269e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner EmitSourceFileHeader("Intrinsic Function Source Fragment", OS); 279e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner 2849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly); 2949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen 3049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen if (TargetOnly && !Ints.empty()) 3149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen TargetPrefix = Ints[0].TargetPrefix; 329e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner 339e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner // Emit the enum information. 349e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner EmitEnumInfo(Ints, OS); 35fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner 36fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner // Emit the intrinsic ID -> name table. 37fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner EmitIntrinsicToNameTable(Ints, OS); 380d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang 390d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang // Emit the intrinsic ID -> overload table. 400d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang EmitIntrinsicToOverloadTable(Ints, OS); 410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang 429b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner // Emit the function name recognizer. 439b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner EmitFnNameRecognizer(Ints, OS); 44fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner 45f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner // Emit the intrinsic verifier. 46f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner EmitVerifier(Ints, OS); 476448ee44c6f232f215d5d9f145a0d71a983c4a3fChris Lattner 4895af592a631f403e1458ec1155f89fc31011572cJim Laskey // Emit the intrinsic declaration generator. 4995af592a631f403e1458ec1155f89fc31011572cJim Laskey EmitGenerator(Ints, OS); 5095af592a631f403e1458ec1155f89fc31011572cJim Laskey 51a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands // Emit the intrinsic parameter attributes. 52a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands EmitAttributes(Ints, OS); 53022f64fbbc4669623e79b805379266fed519017dChris Lattner 54d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands // Emit intrinsic alias analysis mod/ref behavior. 55d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands EmitModRefBehavior(Ints, OS); 56d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands 57022f64fbbc4669623e79b805379266fed519017dChris Lattner // Emit a list of intrinsics with corresponding GCC builtins. 58022f64fbbc4669623e79b805379266fed519017dChris Lattner EmitGCCBuiltinList(Ints, OS); 593f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner 603f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner // Emit code to translate GCC builtins into LLVM intrinsics. 613f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner EmitIntrinsicToGCCBuiltinMap(Ints, OS); 629e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner} 639e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner 649e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, 659e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner std::ostream &OS) { 669b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner OS << "// Enum values for Intrinsics.h\n"; 679e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; 689e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 699e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner OS << " " << Ints[i].EnumName; 709e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner OS << ((i != e-1) ? ", " : " "); 719e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner OS << std::string(40-Ints[i].EnumName.size(), ' ') 729e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner << "// " << Ints[i].Name << "\n"; 739e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner } 749e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner OS << "#endif\n\n"; 759e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner} 769b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner 779b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattnervoid IntrinsicEmitter:: 789b843b249462980ae4630dc37d1bcccde884a5a7Chris LattnerEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 799b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner std::ostream &OS) { 809b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner // Build a function name -> intrinsic name mapping. 81c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer std::map<std::string, unsigned> IntMapping; 829b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) 83c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer IntMapping[Ints[i].Name] = i; 849b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner 859b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner OS << "// Function name -> enum value recognizer code.\n"; 869b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; 879b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner OS << " switch (Name[5]) {\n"; 883b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner OS << " default:\n"; 899b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner // Emit the intrinsics in sorted order. 909b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner char LastChar = 0; 91c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(), 929b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner E = IntMapping.end(); I != E; ++I) { 939b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner if (I->first[5] != LastChar) { 949b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner LastChar = I->first[5]; 953b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner OS << " break;\n"; 969b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner OS << " case '" << LastChar << "':\n"; 979b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner } 989b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner 99c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer // For overloaded intrinsics, only the prefix needs to match 100c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer if (Ints[I->second].isOverloaded) 1016994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << " if (Len > " << I->first.size() 1026994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth << " && !memcmp(Name, \"" << I->first << ".\", " 10349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::" 1046994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth << Ints[I->second].EnumName << ";\n"; 105c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer else 106c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer OS << " if (Len == " << I->first.size() 1076994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth << " && !memcmp(Name, \"" << I->first << "\", " 10849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::" 109c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer << Ints[I->second].EnumName << ";\n"; 1109b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner } 1119b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner OS << " }\n"; 112f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << "#endif\n\n"; 113f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner} 114f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner 115fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattnervoid IntrinsicEmitter:: 116fda6affb95e9f68278cb5cf75dc3fd3406978255Chris LattnerEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, 117fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner std::ostream &OS) { 118fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner OS << "// Intrinsic ID to name table\n"; 119fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n"; 120fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner OS << " // Note that entry #0 is the invalid intrinsic!\n"; 121f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng for (unsigned i = 0, e = Ints.size(); i != e; ++i) 122f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng OS << " \"" << Ints[i].Name << "\",\n"; 123fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner OS << "#endif\n\n"; 124fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner} 125fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner 1260d52ff1f7b993750a74a5d4432273092de9af069Mon P Wangvoid IntrinsicEmitter:: 1270d52ff1f7b993750a74a5d4432273092de9af069Mon P WangEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, 1280d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang std::ostream &OS) { 1290d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << "// Intrinsic ID to overload table\n"; 1300d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; 1310d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << " // Note that entry #0 is the invalid intrinsic!\n"; 1320d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 1330d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << " "; 1340d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang if (Ints[i].isOverloaded) 1350d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << "true"; 1360d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang else 1370d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << "false"; 1380d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << ",\n"; 1390d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang } 1400d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang OS << "#endif\n\n"; 1410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang} 1420d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang 14383ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sandsstatic void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) { 14483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands if (MVT(VT).isInteger()) { 14583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands unsigned BitWidth = MVT(VT).getSizeInBits(); 1466994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "IntegerType::get(" << BitWidth << ")"; 1476994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else if (VT == MVT::Other) { 1486994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth // MVT::OtherVT is used to mean the empty struct type here. 1496994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "StructType::get(std::vector<const Type *>())"; 1506994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else if (VT == MVT::f32) { 1516994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "Type::FloatTy"; 1526994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else if (VT == MVT::f64) { 1536994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "Type::DoubleTy"; 154317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen } else if (VT == MVT::f80) { 155317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen OS << "Type::X86_FP80Ty"; 156317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen } else if (VT == MVT::f128) { 157317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen OS << "Type::FP128Ty"; 158317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen } else if (VT == MVT::ppcf128) { 159317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen OS << "Type::PPC_FP128Ty"; 1606994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else if (VT == MVT::isVoid) { 1616994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "Type::VoidTy"; 1626994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else { 1636994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth assert(false && "Unsupported ValueType!"); 16418faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner } 16518faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner} 16618faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner 167cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendlingstatic void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, 168cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling unsigned &ArgNo); 169cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 170cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendlingstatic void EmitTypeGenerate(std::ostream &OS, 171cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> &ArgTypes, 172cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling unsigned &ArgNo) { 173cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if (ArgTypes.size() == 1) { 174cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); 175cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling return; 176cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling } 177cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 178cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling OS << "StructType::get("; 179cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 180cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (std::vector<Record*>::const_iterator 18120072af3b0b22d90afbce769409f4ed822520366Bill Wendling I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) { 182cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling EmitTypeGenerate(OS, *I, ArgNo); 18320072af3b0b22d90afbce769409f4ed822520366Bill Wendling OS << ", "; 18420072af3b0b22d90afbce769409f4ed822520366Bill Wendling } 185cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 18620072af3b0b22d90afbce769409f4ed822520366Bill Wendling OS << " NULL)"; 187cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling} 188cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 189cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendlingstatic void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, 19084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer unsigned &ArgNo) { 19183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 1926994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth 1936994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth if (ArgType->isSubClassOf("LLVMMatchType")) { 1946994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth unsigned Number = ArgType->getValueAsInt("Number"); 1956994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth assert(Number < ArgNo && "Invalid matching number!"); 196bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 197bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "VectorType::getExtendedElementVectorType" 198bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; 199bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 200bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "VectorType::getTruncatedElementVectorType" 201bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; 202bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson else 203bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "Tys[" << Number << "]"; 2040fee3ff93ea0bf1ce6466fec1d8496514d76e289Dan Gohman } else if (VT == MVT::iAny || VT == MVT::fAny) { 20584c614d1ac671b1a5524169f20028f51c30be728Reid Spencer // NOTE: The ArgNo variable here is not the absolute argument number, it is 20684c614d1ac671b1a5524169f20028f51c30be728Reid Spencer // the index of the "arbitrary" type in the Tys array passed to the 20784c614d1ac671b1a5524169f20028f51c30be728Reid Spencer // Intrinsic::getDeclaration function. Consequently, we only want to 2086994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth // increment it when we actually hit an overloaded type. Getting this wrong 2096994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth // leads to very subtle bugs! 2106994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "Tys[" << ArgNo++ << "]"; 21183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands } else if (MVT(VT).isVector()) { 21283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands MVT VVT = VT; 2139d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer OS << "VectorType::get("; 21483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT()); 21583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands OS << ", " << VVT.getVectorNumElements() << ")"; 2166994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else if (VT == MVT::iPTR) { 21743ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb OS << "PointerType::getUnqual("; 218c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); 21995af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << ")"; 220e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang } else if (VT == MVT::iPTRAny) { 221e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang // Make sure the user has passed us an argument type to overload. If not, 222e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang // treat it as an ordinary (not overloaded) intrinsic. 223e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo 224e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang << "] : PointerType::getUnqual("; 225e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); 226e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang OS << ")"; 227e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang ++ArgNo; 2286994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else if (VT == MVT::isVoid) { 2296994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth if (ArgNo == 0) 2306994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "Type::VoidTy"; 2316994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth else 2326994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth // MVT::isVoid is used to mean varargs here. 2336994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << "..."; 23495af592a631f403e1458ec1155f89fc31011572cJim Laskey } else { 2356994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth EmitTypeForValueType(OS, VT); 23695af592a631f403e1458ec1155f89fc31011572cJim Laskey } 23795af592a631f403e1458ec1155f89fc31011572cJim Laskey} 23895af592a631f403e1458ec1155f89fc31011572cJim Laskey 239da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of 240c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records. 241c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace { 242cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair; 243c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner struct RecordListComparator { 244cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling bool operator()(const RecPair &LHS, 245cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const RecPair &RHS) const { 246c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner unsigned i = 0; 247cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> *LHSVec = &LHS.first; 248cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> *RHSVec = &RHS.first; 249cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling unsigned RHSSize = RHSVec->size(); 250cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling unsigned LHSSize = LHSVec->size(); 251cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 252c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner do { 253cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if (i == RHSSize) return false; // RHS is shorter than LHS. 254cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if ((*LHSVec)[i] != (*RHSVec)[i]) 255cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); 256cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling } while (++i != LHSSize); 257cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 258023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling if (i != RHSSize) return true; 259cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 260cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling i = 0; 261cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling LHSVec = &LHS.second; 262cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling RHSVec = &RHS.second; 263cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling RHSSize = RHSVec->size(); 264cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling LHSSize = LHSVec->size(); 265cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 266cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (i = 0; i != LHSSize; ++i) { 267cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if (i == RHSSize) return false; // RHS is shorter than LHS. 268cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if ((*LHSVec)[i] != (*RHSVec)[i]) 269cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); 270cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling } 271cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 272cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling return i != RHSSize; 273c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner } 274c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner }; 275c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner} 276c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner 277f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, 278f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner std::ostream &OS) { 279f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << "// Verifier::visitIntrinsicFunctionCall code.\n"; 280f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << "#ifdef GET_INTRINSIC_VERIFIER\n"; 281f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << " switch (ID) {\n"; 282f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; 283c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner 284c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner // This checking can emit a lot of very common code. To reduce the amount of 285c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner // code that we emit, batch up cases that have identical types. This avoids 286c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner // problems where GCC can run out of memory compiling Verifier.cpp. 287cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; 288c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner MapTy UniqueArgInfos; 289c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner 290c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner // Compute the unique argument type info. 291c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) 292cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, 293cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling Ints[i].IS.ParamTypeDefs)].push_back(i); 294c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner 295c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner // Loop through the array, emitting one comparison for each batch. 296c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner for (MapTy::iterator I = UniqueArgInfos.begin(), 297c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner E = UniqueArgInfos.end(); I != E; ++I) { 298cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (unsigned i = 0, e = I->second.size(); i != e; ++i) 299c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// " 300c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner << Ints[I->second[i]].Name << "\n"; 301f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner 302cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const RecPair &ArgTypes = I->first; 303cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> &RetTys = ArgTypes.first; 304cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> &ParamTys = ArgTypes.second; 305cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 306cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", " 307cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling << ParamTys.size(); 308cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 309cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling // Emit return types. 310cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (unsigned j = 0, je = RetTys.size(); j != je; ++j) { 311cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling Record *ArgType = RetTys[j]; 312cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling OS << ", "; 313cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 3146994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth if (ArgType->isSubClassOf("LLVMMatchType")) { 3156994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth unsigned Number = ArgType->getValueAsInt("Number"); 3166994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth assert(Number < j && "Invalid matching number!"); 317bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 318bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "~(ExtendedElementVectorType | " << Number << ")"; 319bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 320bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "~(TruncatedElementVectorType | " << Number << ")"; 321bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson else 322bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "~" << Number; 3236994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth } else { 32483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 3256994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << getEnumName(VT); 326cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 327cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if (VT == MVT::isVoid && j != 0 && j != je - 1) 328cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling throw "Var arg type not last argument"; 329cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling } 330cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling } 331cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 332cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling // Emit the parameter types. 333cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) { 334cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling Record *ArgType = ParamTys[j]; 335cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling OS << ", "; 336cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 337cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if (ArgType->isSubClassOf("LLVMMatchType")) { 338cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling unsigned Number = ArgType->getValueAsInt("Number"); 339cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling assert(Number < j + RetTys.size() && "Invalid matching number!"); 340bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 341bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "~(ExtendedElementVectorType | " << Number << ")"; 342bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 343bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "~(TruncatedElementVectorType | " << Number << ")"; 344bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson else 345bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson OS << "~" << Number; 346cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling } else { 347cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 348cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling OS << getEnumName(VT); 349cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 350cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling if (VT == MVT::isVoid && j != 0 && j != je - 1) 35195d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey throw "Var arg type not last argument"; 35295d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey } 35395d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey } 35495d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey 3556994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth OS << ");\n"; 356f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << " break;\n"; 357f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner } 358f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << " }\n"; 359f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner OS << "#endif\n\n"; 3609b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner} 3619b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner 36295af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 36395af592a631f403e1458ec1155f89fc31011572cJim Laskey std::ostream &OS) { 36495af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << "// Code for generating Intrinsic function declarations.\n"; 36595af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << "#ifdef GET_INTRINSIC_GENERATOR\n"; 36695af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " switch (id) {\n"; 36795af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; 36895af592a631f403e1458ec1155f89fc31011572cJim Laskey 36995af592a631f403e1458ec1155f89fc31011572cJim Laskey // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical 37095af592a631f403e1458ec1155f89fc31011572cJim Laskey // types. 371cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; 37295af592a631f403e1458ec1155f89fc31011572cJim Laskey MapTy UniqueArgInfos; 37395af592a631f403e1458ec1155f89fc31011572cJim Laskey 37495af592a631f403e1458ec1155f89fc31011572cJim Laskey // Compute the unique argument type info. 37595af592a631f403e1458ec1155f89fc31011572cJim Laskey for (unsigned i = 0, e = Ints.size(); i != e; ++i) 376cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, 377cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling Ints[i].IS.ParamTypeDefs)].push_back(i); 37895af592a631f403e1458ec1155f89fc31011572cJim Laskey 37995af592a631f403e1458ec1155f89fc31011572cJim Laskey // Loop through the array, emitting one generator for each batch. 38049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen std::string IntrinsicStr = TargetPrefix + "Intrinsic::"; 38149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen 38295af592a631f403e1458ec1155f89fc31011572cJim Laskey for (MapTy::iterator I = UniqueArgInfos.begin(), 38395af592a631f403e1458ec1155f89fc31011572cJim Laskey E = UniqueArgInfos.end(); I != E; ++I) { 384cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (unsigned i = 0, e = I->second.size(); i != e; ++i) 38549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName 38649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << ":\t\t// " << Ints[I->second[i]].Name << "\n"; 38795af592a631f403e1458ec1155f89fc31011572cJim Laskey 388cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const RecPair &ArgTypes = I->first; 389cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> &RetTys = ArgTypes.first; 390cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling const std::vector<Record*> &ParamTys = ArgTypes.second; 391cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 392cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling unsigned N = ParamTys.size(); 39395af592a631f403e1458ec1155f89fc31011572cJim Laskey 3946994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth if (N > 1 && 395cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) { 39695af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " IsVarArg = true;\n"; 39795af592a631f403e1458ec1155f89fc31011572cJim Laskey --N; 39895af592a631f403e1458ec1155f89fc31011572cJim Laskey } 399cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 40084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer unsigned ArgNo = 0; 40195af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " ResultTy = "; 402cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling EmitTypeGenerate(OS, RetTys, ArgNo); 40395af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << ";\n"; 40495af592a631f403e1458ec1155f89fc31011572cJim Laskey 405cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling for (unsigned j = 0; j != N; ++j) { 40695af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " ArgTys.push_back("; 407cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling EmitTypeGenerate(OS, ParamTys[j], ArgNo); 40895af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << ");\n"; 40995af592a631f403e1458ec1155f89fc31011572cJim Laskey } 410cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 41195af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " break;\n"; 41295af592a631f403e1458ec1155f89fc31011572cJim Laskey } 413cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling 41495af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << " }\n"; 41595af592a631f403e1458ec1155f89fc31011572cJim Laskey OS << "#endif\n\n"; 41695af592a631f403e1458ec1155f89fc31011572cJim Laskey} 41795af592a631f403e1458ec1155f89fc31011572cJim Laskey 418048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method. 4194e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter:: 420a3355ffb3d30d19d226bbb75707991c60f236e37Duncan SandsEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) { 421a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands OS << "// Add parameter attributes that are not common to all intrinsics.\n"; 422a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; 42349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen if (TargetOnly) 42449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "static AttrListPtr getAttributes(" << TargetPrefix 42549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << "Intrinsic::ID id) {"; 42649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen else 42749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "AttrListPtr Intrinsic::getAttributes(ID id) {"; 428048ffb239c282277959463c61200b86e2380cb84Chris Lattner OS << " // No intrinsic can throw exceptions.\n"; 429048ffb239c282277959463c61200b86e2380cb84Chris Lattner OS << " Attributes Attr = Attribute::NoUnwind;\n"; 430a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands OS << " switch (id) {\n"; 4317056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner OS << " default: break;\n"; 43210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner unsigned MaxArgAttrs = 0; 4337056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 43410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner MaxArgAttrs = 43510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size())); 4367056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner switch (Ints[i].ModRef) { 4377056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner default: break; 4387056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner case CodeGenIntrinsic::NoMem: 43949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 44049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << ":\n"; 4417056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner break; 4427056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner } 4437056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner } 4440598866c052147c31b808391f58434ce3dbfb838Devang Patel OS << " Attr |= Attribute::ReadNone; // These do not access memory.\n"; 445a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands OS << " break;\n"; 4464e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 4474e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner switch (Ints[i].ModRef) { 448022f64fbbc4669623e79b805379266fed519017dChris Lattner default: break; 449022f64fbbc4669623e79b805379266fed519017dChris Lattner case CodeGenIntrinsic::ReadArgMem: 450022f64fbbc4669623e79b805379266fed519017dChris Lattner case CodeGenIntrinsic::ReadMem: 45149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 45249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << ":\n"; 453022f64fbbc4669623e79b805379266fed519017dChris Lattner break; 4544e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner } 4554e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner } 4560598866c052147c31b808391f58434ce3dbfb838Devang Patel OS << " Attr |= Attribute::ReadOnly; // These do not write memory.\n"; 457a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands OS << " break;\n"; 4584e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner OS << " }\n"; 45910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner OS << " AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n"; 460d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << " unsigned NumAttrs = 0;\n"; 46110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner OS << " switch (id) {\n"; 46210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner OS << " default: break;\n"; 46310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 46410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner // Add argument attributes for any intrinsics that have them. 46510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 46610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner if (Ints[i].ArgumentAttributes.empty()) continue; 46710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 46849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 46949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << ":\n"; 47010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 47110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs = 47210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner Ints[i].ArgumentAttributes; 47310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner // Sort by argument index. 47410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner std::sort(ArgAttrs.begin(), ArgAttrs.end()); 47510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 47610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner unsigned NumArgsWithAttrs = 0; 47710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 478d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner while (!ArgAttrs.empty()) { 479d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner unsigned ArgNo = ArgAttrs[0].first; 480d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner 481d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << " AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get(" 482d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner << ArgNo+1 << ", 0"; 483d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner 484d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) { 485d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner switch (ArgAttrs[0].second) { 486d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner default: assert(0 && "Unknown arg attribute"); 487d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner case CodeGenIntrinsic::NoCapture: 488d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << "|Attribute::NoCapture"; 489d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner break; 490d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner } 491d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner ArgAttrs.erase(ArgAttrs.begin()); 492d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner } 493d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << ");\n"; 494d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner } 49510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 496d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << " NumAttrs = " << NumArgsWithAttrs << ";\n"; 49710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner OS << " break;\n"; 49810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner } 49910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner 50010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner OS << " }\n"; 501d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << " AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n"; 502d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << " return AttrListPtr::get(AWI, NumAttrs+1);\n"; 503048ffb239c282277959463c61200b86e2380cb84Chris Lattner OS << "}\n"; 504d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; 5054e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner} 506022f64fbbc4669623e79b805379266fed519017dChris Lattner 507d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. 508d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter:: 509d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan SandsEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){ 510d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"; 511d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"; 512d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "switch (id) {\n"; 513d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "default:\n return UnknownModRefBehavior;\n"; 514d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 515d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands if (Ints[i].ModRef == CodeGenIntrinsic::WriteMem) 516d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands continue; 517d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 518d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands << ":\n"; 519d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands switch (Ints[i].ModRef) { 520d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands default: 521d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands assert(false && "Unknown Mod/Ref type!"); 522d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands case CodeGenIntrinsic::NoMem: 523d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << " return DoesNotAccessMemory;\n"; 524d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands break; 525d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands case CodeGenIntrinsic::ReadArgMem: 526d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands case CodeGenIntrinsic::ReadMem: 527d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << " return OnlyReadsMemory;\n"; 528d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands break; 529d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands case CodeGenIntrinsic::WriteArgMem: 530d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << " return AccessesArguments;\n"; 531d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands break; 532d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands } 533d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands } 534d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "}\n"; 535d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; 536d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands} 537d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands 538022f64fbbc4669623e79b805379266fed519017dChris Lattnervoid IntrinsicEmitter:: 539022f64fbbc4669623e79b805379266fed519017dChris LattnerEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){ 540022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n"; 541022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << "#ifdef GET_GCC_BUILTIN_NAME\n"; 542022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << " switch (F->getIntrinsicID()) {\n"; 543022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << " default: BuiltinName = \"\"; break;\n"; 544022f64fbbc4669623e79b805379266fed519017dChris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 545022f64fbbc4669623e79b805379266fed519017dChris Lattner if (!Ints[i].GCCBuiltinName.empty()) { 546022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << " case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \"" 547022f64fbbc4669623e79b805379266fed519017dChris Lattner << Ints[i].GCCBuiltinName << "\"; break;\n"; 548022f64fbbc4669623e79b805379266fed519017dChris Lattner } 549022f64fbbc4669623e79b805379266fed519017dChris Lattner } 550022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << " }\n"; 551022f64fbbc4669623e79b805379266fed519017dChris Lattner OS << "#endif\n\n"; 552767a25b8788b5e313c99c16b4d359478432901f5Reid Spencer} 5533f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner 554331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified 555331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// sorted range of builtin names is equal to the current builtin. This breaks 556331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// it down into a simple tree. 557331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// 558331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// At this point, we know that all the builtins in the range have the same name 559331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// for the first 'CharStart' characters. Only the end of the name needs to be 560331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// discriminated. 561331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnertypedef std::map<std::string, std::string>::const_iterator StrMapIterator; 562331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, 563331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner unsigned CharStart, unsigned Indent, 56449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen std::string TargetPrefix, std::ostream &OS) { 565331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (Start == End) return; // empty range. 566331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 567331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Determine what, if anything, is the same about all these strings. 568331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner std::string CommonString = Start->first; 569331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner unsigned NumInRange = 0; 570331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) { 571331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Find the first character that doesn't match. 572331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner const std::string &ThisStr = I->first; 573331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner unsigned NonMatchChar = CharStart; 574331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner while (NonMatchChar < CommonString.size() && 575331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner NonMatchChar < ThisStr.size() && 576331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner CommonString[NonMatchChar] == ThisStr[NonMatchChar]) 577331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner ++NonMatchChar; 578331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Truncate off pieces that don't match. 579331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner CommonString.resize(NonMatchChar); 580331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 581331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 582331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Just compare the rest of the string. 583331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (NumInRange == 1) { 584331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (CharStart != CommonString.size()) { 585331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; 586331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (CharStart) OS << "+" << CharStart; 587331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; 588331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << CommonString.size() - CharStart << "))\n"; 589331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner ++Indent; 590331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 59149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix 59249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << "Intrinsic::"; 593331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << Start->second << ";\n"; 594331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner return; 595331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 596331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 597331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // At this point, we potentially have a common prefix for these builtins, emit 598331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // a check for this common prefix. 599331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (CommonString.size() != CharStart) { 600331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; 601331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (CharStart) OS << "+" << CharStart; 602331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; 603331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << CommonString.size()-CharStart << ")) {\n"; 604331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 60549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, 60649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen TargetPrefix, OS); 607331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << "}\n"; 608331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner return; 609331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 610331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 611331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Output a switch on the character that differs across the set. 612331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart 613331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner << "]) {"; 614331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (CharStart) 615331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << " // \"" << std::string(Start->first.begin(), 616331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner Start->first.begin()+CharStart) << "\""; 617331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << "\n"; 618331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 619331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner for (StrMapIterator I = Start; I != End; ) { 620331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner char ThisChar = I->first[CharStart]; 621331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n"; 622331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Figure out the range that has this common character. 623331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner StrMapIterator NextChar = I; 624331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar; 625331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner ++NextChar) 626331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner /*empty*/; 62749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS); 628331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << " break;\n"; 629331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner I = NextChar; 630331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 631331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << std::string(Indent*2, ' ') << "}\n"; 632331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner} 633331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 634331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the 635331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it. 636331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, 63749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen const std::string &TargetPrefix, 638331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner std::ostream &OS) { 639331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Rearrange the builtins by length. 640331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner std::vector<std::map<std::string, std::string> > BuiltinsByLen; 641331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner BuiltinsByLen.reserve(100); 642331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 643331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) { 644331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (I->first.size() >= BuiltinsByLen.size()) 645331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner BuiltinsByLen.resize(I->first.size()+1); 646331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner BuiltinsByLen[I->first.size()].insert(*I); 647331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 648331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 649331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner // Now that we have all the builtins by their length, emit a switch stmt. 650331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << " switch (strlen(BuiltinName)) {\n"; 651331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << " default: break;\n"; 652331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) { 653331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner if (BuiltinsByLen[i].empty()) continue; 654331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << " case " << i << ":\n"; 655331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(), 65649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen 0, 3, TargetPrefix, OS); 657331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << " break;\n"; 658331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner } 659331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner OS << " }\n"; 660331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner} 661331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 662331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 6633f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter:: 6643f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, 6653f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner std::ostream &OS) { 666fa0fba1c546091c485e5513eadeef181dda370abChris Lattner typedef std::map<std::string, std::map<std::string, std::string> > BIMTy; 6673f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner BIMTy BuiltinMap; 6683f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 6693f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner if (!Ints[i].GCCBuiltinName.empty()) { 670fa0fba1c546091c485e5513eadeef181dda370abChris Lattner // Get the map for this target prefix. 671fa0fba1c546091c485e5513eadeef181dda370abChris Lattner std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix]; 672fa0fba1c546091c485e5513eadeef181dda370abChris Lattner 673fa0fba1c546091c485e5513eadeef181dda370abChris Lattner if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName, 674fa0fba1c546091c485e5513eadeef181dda370abChris Lattner Ints[i].EnumName)).second) 6753f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner throw "Intrinsic '" + Ints[i].TheDef->getName() + 6763f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner "': duplicate GCC builtin name!"; 6773f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner } 6783f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner } 6793f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner 6803f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n"; 6813f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner OS << "// This is used by the C front-end. The GCC builtin name is passed\n"; 6823f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n"; 6833f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n"; 6843f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n"; 68549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen 68649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen if (TargetOnly) { 68749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "static " << TargetPrefix << "Intrinsic::ID " 68849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << "getIntrinsicForGCCBuiltin(const char " 68949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << "*TargetPrefix, const char *BuiltinName) {\n"; 69049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = "; 69149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen } else { 69249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " 69349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen << "*TargetPrefix, const char *BuiltinName) {\n"; 69449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " Intrinsic::ID IntrinsicID = "; 69549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen } 69649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen 69749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen if (TargetOnly) 69849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "(" << TargetPrefix<< "Intrinsic::ID)"; 69949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen 70049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "Intrinsic::not_intrinsic;\n"; 701331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner 7023f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner // Note: this could emit significantly better code if we cared. 7033f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ 704fa0fba1c546091c485e5513eadeef181dda370abChris Lattner OS << " "; 705fa0fba1c546091c485e5513eadeef181dda370abChris Lattner if (!I->first.empty()) 706fa0fba1c546091c485e5513eadeef181dda370abChris Lattner OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) "; 707fa0fba1c546091c485e5513eadeef181dda370abChris Lattner else 708fa0fba1c546091c485e5513eadeef181dda370abChris Lattner OS << "/* Target Independent Builtins */ "; 709fa0fba1c546091c485e5513eadeef181dda370abChris Lattner OS << "{\n"; 710fa0fba1c546091c485e5513eadeef181dda370abChris Lattner 711fa0fba1c546091c485e5513eadeef181dda370abChris Lattner // Emit the comparisons for this target prefix. 71249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen EmitTargetBuiltins(I->second, TargetPrefix, OS); 713fa0fba1c546091c485e5513eadeef181dda370abChris Lattner OS << " }\n"; 7143f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner } 71549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << " return IntrinsicID;\n"; 71649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen OS << "}\n"; 7173f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner OS << "#endif\n\n"; 7183f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner} 719