X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FIntrinsicEmitter.cpp;h=8f0c3a66ab49c6d868a2be4393c1a02f32aeda97;hb=867fe8570f299a058f155f98646d85cabc27155b;hp=86e83e591116a3b46727ac21d47ea8980d383a4e;hpb=bc03979536a1ecb220f1330719f3e3973a81ab0b;p=oota-llvm.git diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 86e83e59111..8f0c3a66ab4 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -14,6 +14,7 @@ #include "CodeGenTarget.h" #include "IntrinsicEmitter.h" #include "Record.h" +#include "StringMatcher.h" #include "llvm/ADT/StringExtras.h" #include using namespace llvm; @@ -22,17 +23,25 @@ using namespace llvm; // IntrinsicEmitter Implementation //===----------------------------------------------------------------------===// -void IntrinsicEmitter::run(std::ostream &OS) { +void IntrinsicEmitter::run(raw_ostream &OS) { EmitSourceFileHeader("Intrinsic Function Source Fragment", OS); - std::vector Ints = LoadIntrinsics(Records); + std::vector Ints = LoadIntrinsics(Records, TargetOnly); + + if (TargetOnly && !Ints.empty()) + TargetPrefix = Ints[0].TargetPrefix; + + EmitPrefix(OS); // Emit the enum information. EmitEnumInfo(Ints, OS); // Emit the intrinsic ID -> name table. EmitIntrinsicToNameTable(Ints, OS); - + + // Emit the intrinsic ID -> overload table. + EmitIntrinsicToOverloadTable(Ints, OS); + // Emit the function name recognizer. EmitFnNameRecognizer(Ints, OS); @@ -45,15 +54,38 @@ void IntrinsicEmitter::run(std::ostream &OS) { // Emit the intrinsic parameter attributes. EmitAttributes(Ints, OS); + // Emit intrinsic alias analysis mod/ref behavior. + EmitModRefBehavior(Ints, OS); + // Emit a list of intrinsics with corresponding GCC builtins. EmitGCCBuiltinList(Ints, OS); // Emit code to translate GCC builtins into LLVM intrinsics. EmitIntrinsicToGCCBuiltinMap(Ints, OS); + + EmitSuffix(OS); +} + +void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) { + OS << "// VisualStudio defines setjmp as _setjmp\n" + "#if defined(_MSC_VER) && defined(setjmp) && \\\n" + " !defined(setjmp_undefined_for_msvc)\n" + "# pragma push_macro(\"setjmp\")\n" + "# undef setjmp\n" + "# define setjmp_undefined_for_msvc\n" + "#endif\n\n"; +} + +void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) { + OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n" + "// let's return it to _setjmp state\n" + "# pragma pop_macro(\"setjmp\")\n" + "# undef setjmp_undefined_for_msvc\n" + "#endif\n\n"; } void IntrinsicEmitter::EmitEnumInfo(const std::vector &Ints, - std::ostream &OS) { + raw_ostream &OS) { OS << "// Enum values for Intrinsics.h\n"; OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { @@ -67,45 +99,56 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector &Ints, void IntrinsicEmitter:: EmitFnNameRecognizer(const std::vector &Ints, - std::ostream &OS) { - // Build a function name -> intrinsic name mapping. - std::map IntMapping; + raw_ostream &OS) { + // Build a 'first character of function name' -> intrinsic # mapping. + std::map > IntMapping; for (unsigned i = 0, e = Ints.size(); i != e; ++i) - IntMapping[Ints[i].Name] = i; - + IntMapping[Ints[i].Name[5]].push_back(i); + OS << "// Function name -> enum value recognizer code.\n"; OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; - OS << " switch (Name[5]) {\n"; - OS << " default:\n"; - // Emit the intrinsics in sorted order. - char LastChar = 0; - for (std::map::iterator I = IntMapping.begin(), + OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n"; + OS << " switch (Name[5]) { // Dispatch on first letter.\n"; + OS << " default: break;\n"; + // Emit the intrinsic matching stuff by first letter. + for (std::map >::iterator I = IntMapping.begin(), E = IntMapping.end(); I != E; ++I) { - if (I->first[5] != LastChar) { - LastChar = I->first[5]; - OS << " break;\n"; - OS << " case '" << LastChar << "':\n"; + OS << " case '" << I->first << "':\n"; + std::vector &IntList = I->second; + + // Emit all the overloaded intrinsics first, build a table of the + // non-overloaded ones. + std::vector MatchTable; + + for (unsigned i = 0, e = IntList.size(); i != e; ++i) { + unsigned IntNo = IntList[i]; + std::string Result = "return " + TargetPrefix + "Intrinsic::" + + Ints[IntNo].EnumName + ";"; + + if (!Ints[IntNo].isOverloaded) { + MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result)); + continue; + } + + // For overloaded intrinsics, only the prefix needs to match + std::string TheStr = Ints[IntNo].Name.substr(6); + TheStr += '.'; // Require "bswap." instead of bswap. + OS << " if (NameR.startswith(\"" << TheStr << "\")) " + << Result << '\n'; } - // For overloaded intrinsics, only the prefix needs to match - if (Ints[I->second].isOverloaded) - OS << " if (Len > " << I->first.size() - << " && !memcmp(Name, \"" << I->first << ".\", " - << (I->first.size() + 1) << ")) return Intrinsic::" - << Ints[I->second].EnumName << ";\n"; - else - OS << " if (Len == " << I->first.size() - << " && !memcmp(Name, \"" << I->first << "\", " - << I->first.size() << ")) return Intrinsic::" - << Ints[I->second].EnumName << ";\n"; + // Emit the matcher logic for the fixed length strings. + StringMatcher("NameR", MatchTable, OS).Emit(1); + OS << " break; // end of '" << I->first << "' case.\n"; } + OS << " }\n"; OS << "#endif\n\n"; } void IntrinsicEmitter:: EmitIntrinsicToNameTable(const std::vector &Ints, - std::ostream &OS) { + raw_ostream &OS) { OS << "// Intrinsic ID to name table\n"; OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n"; OS << " // Note that entry #0 is the invalid intrinsic!\n"; @@ -114,42 +157,64 @@ EmitIntrinsicToNameTable(const std::vector &Ints, OS << "#endif\n\n"; } -static void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) { - if (MVT(VT).isInteger()) { - unsigned BitWidth = MVT(VT).getSizeInBits(); - OS << "IntegerType::get(" << BitWidth << ")"; +void IntrinsicEmitter:: +EmitIntrinsicToOverloadTable(const std::vector &Ints, + raw_ostream &OS) { + OS << "// Intrinsic ID to overload table\n"; + OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; + OS << " // Note that entry #0 is the invalid intrinsic!\n"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + OS << " "; + if (Ints[i].isOverloaded) + OS << "true"; + else + OS << "false"; + OS << ",\n"; + } + OS << "#endif\n\n"; +} + +static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) { + if (EVT(VT).isInteger()) { + unsigned BitWidth = EVT(VT).getSizeInBits(); + OS << "IntegerType::get(Context, " << BitWidth << ")"; } else if (VT == MVT::Other) { // MVT::OtherVT is used to mean the empty struct type here. - OS << "StructType::get(std::vector())"; + OS << "StructType::get(Context)"; } else if (VT == MVT::f32) { - OS << "Type::FloatTy"; + OS << "Type::getFloatTy(Context)"; } else if (VT == MVT::f64) { - OS << "Type::DoubleTy"; + OS << "Type::getDoubleTy(Context)"; } else if (VT == MVT::f80) { - OS << "Type::X86_FP80Ty"; + OS << "Type::getX86_FP80Ty(Context)"; } else if (VT == MVT::f128) { - OS << "Type::FP128Ty"; + OS << "Type::getFP128Ty(Context)"; } else if (VT == MVT::ppcf128) { - OS << "Type::PPC_FP128Ty"; + OS << "Type::getPPC_FP128Ty(Context)"; } else if (VT == MVT::isVoid) { - OS << "Type::VoidTy"; + OS << "Type::getVoidTy(Context)"; + } else if (VT == MVT::Metadata) { + OS << "Type::getMetadataTy(Context)"; + } else if (VT == MVT::x86mmx) { + OS << "Type::getX86_MMXTy(Context)"; } else { assert(false && "Unsupported ValueType!"); } } -static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, +static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, unsigned &ArgNo); -static void EmitTypeGenerate(std::ostream &OS, +static void EmitTypeGenerate(raw_ostream &OS, const std::vector &ArgTypes, unsigned &ArgNo) { - if (ArgTypes.size() == 1) { - EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); - return; - } + if (ArgTypes.empty()) + return EmitTypeForValueType(OS, MVT::isVoid); + + if (ArgTypes.size() == 1) + return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); - OS << "StructType::get("; + OS << "StructType::get(Context, "; for (std::vector::const_iterator I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) { @@ -160,7 +225,7 @@ static void EmitTypeGenerate(std::ostream &OS, OS << " NULL)"; } -static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, +static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, unsigned &ArgNo) { MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); @@ -175,17 +240,17 @@ static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, << "(dyn_cast(Tys[" << Number << "]))"; else OS << "Tys[" << Number << "]"; - } else if (VT == MVT::iAny || VT == MVT::fAny) { + } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) { // NOTE: The ArgNo variable here is not the absolute argument number, it is // the index of the "arbitrary" type in the Tys array passed to the // Intrinsic::getDeclaration function. Consequently, we only want to // increment it when we actually hit an overloaded type. Getting this wrong // leads to very subtle bugs! OS << "Tys[" << ArgNo++ << "]"; - } else if (MVT(VT).isVector()) { - MVT VVT = VT; + } else if (EVT(VT).isVector()) { + EVT VVT = VT; OS << "VectorType::get("; - EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT()); + EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy); OS << ", " << VVT.getVectorNumElements() << ")"; } else if (VT == MVT::iPTR) { OS << "PointerType::getUnqual("; @@ -201,7 +266,7 @@ static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, ++ArgNo; } else if (VT == MVT::isVoid) { if (ArgNo == 0) - OS << "Type::VoidTy"; + OS << "Type::getVoidTy(Context)"; else // MVT::isVoid is used to mean varargs here. OS << "..."; @@ -210,7 +275,7 @@ static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, } } -/// RecordListComparator - Provide a determinstic comparator for lists of +/// RecordListComparator - Provide a deterministic comparator for lists of /// records. namespace { typedef std::pair, std::vector > RecPair; @@ -223,11 +288,11 @@ namespace { unsigned RHSSize = RHSVec->size(); unsigned LHSSize = LHSVec->size(); - do { + for (; i != LHSSize; ++i) { if (i == RHSSize) return false; // RHS is shorter than LHS. if ((*LHSVec)[i] != (*RHSVec)[i]) return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); - } while (++i != LHSSize); + } if (i != RHSSize) return true; @@ -249,7 +314,7 @@ namespace { } void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, - std::ostream &OS) { + raw_ostream &OS) { OS << "// Verifier::visitIntrinsicFunctionCall code.\n"; OS << "#ifdef GET_INTRINSIC_VERIFIER\n"; OS << " switch (ID) {\n"; @@ -276,6 +341,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, const RecPair &ArgTypes = I->first; const std::vector &RetTys = ArgTypes.first; const std::vector &ParamTys = ArgTypes.second; + std::vector OverloadedTypeIndices; OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", " << ParamTys.size(); @@ -287,7 +353,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, if (ArgType->isSubClassOf("LLVMMatchType")) { unsigned Number = ArgType->getValueAsInt("Number"); - assert(Number < j && "Invalid matching number!"); + assert(Number < OverloadedTypeIndices.size() && + "Invalid matching number!"); + Number = OverloadedTypeIndices[Number]; if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) OS << "~(ExtendedElementVectorType | " << Number << ")"; else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) @@ -298,6 +366,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); OS << getEnumName(VT); + if (EVT(VT).isOverloaded()) + OverloadedTypeIndices.push_back(j); + if (VT == MVT::isVoid && j != 0 && j != je - 1) throw "Var arg type not last argument"; } @@ -310,7 +381,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, if (ArgType->isSubClassOf("LLVMMatchType")) { unsigned Number = ArgType->getValueAsInt("Number"); - assert(Number < j + RetTys.size() && "Invalid matching number!"); + assert(Number < OverloadedTypeIndices.size() && + "Invalid matching number!"); + Number = OverloadedTypeIndices[Number]; if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) OS << "~(ExtendedElementVectorType | " << Number << ")"; else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) @@ -321,6 +394,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); OS << getEnumName(VT); + if (EVT(VT).isOverloaded()) + OverloadedTypeIndices.push_back(j + RetTys.size()); + if (VT == MVT::isVoid && j != 0 && j != je - 1) throw "Var arg type not last argument"; } @@ -334,7 +410,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, } void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, - std::ostream &OS) { + raw_ostream &OS) { OS << "// Code for generating Intrinsic function declarations.\n"; OS << "#ifdef GET_INTRINSIC_GENERATOR\n"; OS << " switch (id) {\n"; @@ -351,11 +427,13 @@ void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, Ints[i].IS.ParamTypeDefs)].push_back(i); // Loop through the array, emitting one generator for each batch. + std::string IntrinsicStr = TargetPrefix + "Intrinsic::"; + for (MapTy::iterator I = UniqueArgInfos.begin(), E = UniqueArgInfos.end(); I != E; ++I) { for (unsigned i = 0, e = I->second.size(); i != e; ++i) - OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// " - << Ints[I->second[i]].Name << "\n"; + OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName + << ":\t\t// " << Ints[I->second[i]].Name << "\n"; const RecPair &ArgTypes = I->first; const std::vector &RetTys = ArgTypes.first; @@ -387,17 +465,29 @@ void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, OS << "#endif\n\n"; } +/// EmitAttributes - This emits the Intrinsic::getAttributes method. void IntrinsicEmitter:: -EmitAttributes(const std::vector &Ints, std::ostream &OS) { +EmitAttributes(const std::vector &Ints, raw_ostream &OS) { OS << "// Add parameter attributes that are not common to all intrinsics.\n"; OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; + if (TargetOnly) + OS << "static AttrListPtr getAttributes(" << TargetPrefix + << "Intrinsic::ID id) {"; + else + OS << "AttrListPtr Intrinsic::getAttributes(ID id) {"; + OS << " // No intrinsic can throw exceptions.\n"; + OS << " Attributes Attr = Attribute::NoUnwind;\n"; OS << " switch (id) {\n"; OS << " default: break;\n"; + unsigned MaxArgAttrs = 0; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + MaxArgAttrs = + std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size())); switch (Ints[i].ModRef) { default: break; case CodeGenIntrinsic::NoMem: - OS << " case Intrinsic::" << Ints[i].EnumName << ":\n"; + OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName + << ":\n"; break; } } @@ -408,18 +498,97 @@ EmitAttributes(const std::vector &Ints, std::ostream &OS) { default: break; case CodeGenIntrinsic::ReadArgMem: case CodeGenIntrinsic::ReadMem: - OS << " case Intrinsic::" << Ints[i].EnumName << ":\n"; + OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName + << ":\n"; break; } } OS << " Attr |= Attribute::ReadOnly; // These do not write memory.\n"; OS << " break;\n"; OS << " }\n"; - OS << "#endif\n\n"; + OS << " AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n"; + OS << " unsigned NumAttrs = 0;\n"; + OS << " switch (id) {\n"; + OS << " default: break;\n"; + + // Add argument attributes for any intrinsics that have them. + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + if (Ints[i].ArgumentAttributes.empty()) continue; + + OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName + << ":\n"; + + std::vector > ArgAttrs = + Ints[i].ArgumentAttributes; + // Sort by argument index. + std::sort(ArgAttrs.begin(), ArgAttrs.end()); + + unsigned NumArgsWithAttrs = 0; + + while (!ArgAttrs.empty()) { + unsigned ArgNo = ArgAttrs[0].first; + + OS << " AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get(" + << ArgNo+1 << ", 0"; + + while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) { + switch (ArgAttrs[0].second) { + default: assert(0 && "Unknown arg attribute"); + case CodeGenIntrinsic::NoCapture: + OS << "|Attribute::NoCapture"; + break; + } + ArgAttrs.erase(ArgAttrs.begin()); + } + OS << ");\n"; + } + + OS << " NumAttrs = " << NumArgsWithAttrs << ";\n"; + OS << " break;\n"; + } + + OS << " }\n"; + OS << " AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n"; + OS << " return AttrListPtr::get(AWI, NumAttrs+1);\n"; + OS << "}\n"; + OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } +/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. void IntrinsicEmitter:: -EmitGCCBuiltinList(const std::vector &Ints, std::ostream &OS){ +EmitModRefBehavior(const std::vector &Ints, raw_ostream &OS){ + OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"; + OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"; + OS << "switch (iid) {\n"; + OS << "default:\n return UnknownModRefBehavior;\n"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem) + continue; + OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName + << ":\n"; + switch (Ints[i].ModRef) { + default: + assert(false && "Unknown Mod/Ref type!"); + case CodeGenIntrinsic::NoMem: + OS << " return DoesNotAccessMemory;\n"; + break; + case CodeGenIntrinsic::ReadArgMem: + OS << " return AccessesArgumentsReadonly;\n"; + break; + case CodeGenIntrinsic::ReadMem: + OS << " return OnlyReadsMemory;\n"; + break; + case CodeGenIntrinsic::ReadWriteArgMem: + OS << " return AccessesArguments;\n"; + break; + } + } + OS << "}\n"; + OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; +} + +void IntrinsicEmitter:: +EmitGCCBuiltinList(const std::vector &Ints, raw_ostream &OS){ OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n"; OS << "#ifdef GET_GCC_BUILTIN_NAME\n"; OS << " switch (F->getIntrinsicID()) {\n"; @@ -434,115 +603,28 @@ EmitGCCBuiltinList(const std::vector &Ints, std::ostream &OS){ OS << "#endif\n\n"; } -/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified -/// sorted range of builtin names is equal to the current builtin. This breaks -/// it down into a simple tree. -/// -/// At this point, we know that all the builtins in the range have the same name -/// for the first 'CharStart' characters. Only the end of the name needs to be -/// discriminated. -typedef std::map::const_iterator StrMapIterator; -static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, - unsigned CharStart, unsigned Indent, - std::ostream &OS) { - if (Start == End) return; // empty range. - - // Determine what, if anything, is the same about all these strings. - std::string CommonString = Start->first; - unsigned NumInRange = 0; - for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) { - // Find the first character that doesn't match. - const std::string &ThisStr = I->first; - unsigned NonMatchChar = CharStart; - while (NonMatchChar < CommonString.size() && - NonMatchChar < ThisStr.size() && - CommonString[NonMatchChar] == ThisStr[NonMatchChar]) - ++NonMatchChar; - // Truncate off pieces that don't match. - CommonString.resize(NonMatchChar); - } - - // Just compare the rest of the string. - if (NumInRange == 1) { - if (CharStart != CommonString.size()) { - OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; - if (CharStart) OS << "+" << CharStart; - OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; - OS << CommonString.size() - CharStart << "))\n"; - ++Indent; - } - OS << std::string(Indent*2, ' ') << "IntrinsicID = Intrinsic::"; - OS << Start->second << ";\n"; - return; - } - - // At this point, we potentially have a common prefix for these builtins, emit - // a check for this common prefix. - if (CommonString.size() != CharStart) { - OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; - if (CharStart) OS << "+" << CharStart; - OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; - OS << CommonString.size()-CharStart << ")) {\n"; - - EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, OS); - OS << std::string(Indent*2, ' ') << "}\n"; - return; - } - - // Output a switch on the character that differs across the set. - OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart - << "]) {"; - if (CharStart) - OS << " // \"" << std::string(Start->first.begin(), - Start->first.begin()+CharStart) << "\""; - OS << "\n"; - - for (StrMapIterator I = Start; I != End; ) { - char ThisChar = I->first[CharStart]; - OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n"; - // Figure out the range that has this common character. - StrMapIterator NextChar = I; - for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar; - ++NextChar) - /*empty*/; - EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, OS); - OS << std::string(Indent*2, ' ') << " break;\n"; - I = NextChar; - } - OS << std::string(Indent*2, ' ') << "}\n"; -} - /// EmitTargetBuiltins - All of the builtins in the specified map are for the /// same target, and we already checked it. static void EmitTargetBuiltins(const std::map &BIM, - std::ostream &OS) { - // Rearrange the builtins by length. - std::vector > BuiltinsByLen; - BuiltinsByLen.reserve(100); + const std::string &TargetPrefix, + raw_ostream &OS) { - for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) { - if (I->first.size() >= BuiltinsByLen.size()) - BuiltinsByLen.resize(I->first.size()+1); - BuiltinsByLen[I->first.size()].insert(*I); - } + std::vector Results; - // Now that we have all the builtins by their length, emit a switch stmt. - OS << " switch (strlen(BuiltinName)) {\n"; - OS << " default: break;\n"; - for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) { - if (BuiltinsByLen[i].empty()) continue; - OS << " case " << i << ":\n"; - EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(), - 0, 3, OS); - OS << " break;\n"; + for (std::map::const_iterator I = BIM.begin(), + E = BIM.end(); I != E; ++I) { + std::string ResultCode = + "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; + Results.push_back(StringMatcher::StringPair(I->first, ResultCode)); } - OS << " }\n"; + + StringMatcher("BuiltinName", Results, OS).Emit(); } void IntrinsicEmitter:: EmitIntrinsicToGCCBuiltinMap(const std::vector &Ints, - std::ostream &OS) { + raw_ostream &OS) { typedef std::map > BIMTy; BIMTy BuiltinMap; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { @@ -562,20 +644,36 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector &Ints, OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n"; OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n"; OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n"; - OS << " IntrinsicID = Intrinsic::not_intrinsic;\n"; + + if (TargetOnly) { + OS << "static " << TargetPrefix << "Intrinsic::ID " + << "getIntrinsicForGCCBuiltin(const char " + << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; + } else { + OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " + << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; + } + + OS << " StringRef BuiltinName(BuiltinNameStr);\n"; + OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n"; // Note: this could emit significantly better code if we cared. for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ OS << " "; if (!I->first.empty()) - OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) "; + OS << "if (TargetPrefix == \"" << I->first << "\") "; else OS << "/* Target Independent Builtins */ "; OS << "{\n"; // Emit the comparisons for this target prefix. - EmitTargetBuiltins(I->second, OS); + EmitTargetBuiltins(I->second, TargetPrefix, OS); OS << " }\n"; } + OS << " return "; + if (!TargetPrefix.empty()) + OS << "(" << TargetPrefix << "Intrinsic::ID)"; + OS << "Intrinsic::not_intrinsic;\n"; + OS << "}\n"; OS << "#endif\n\n"; }