X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FIntrinsicEmitter.cpp;h=8800a778164d1d7c80a55a1713cc4f5c2ad7cc02;hb=0d52ff1f7b993750a74a5d4432273092de9af069;hp=eda55e1430f3805b48b67a47d4f5a63b4d89fde5;hpb=4d452de1506344bf1d28bb4a8c4ddb78c51a28c8;p=oota-llvm.git diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index eda55e1430f..8800a778164 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -25,14 +25,20 @@ using namespace llvm; void IntrinsicEmitter::run(std::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; // 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,6 +51,9 @@ 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); @@ -91,12 +100,12 @@ EmitFnNameRecognizer(const std::vector &Ints, if (Ints[I->second].isOverloaded) OS << " if (Len > " << I->first.size() << " && !memcmp(Name, \"" << I->first << ".\", " - << (I->first.size() + 1) << ")) return Intrinsic::" + << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::" << Ints[I->second].EnumName << ";\n"; else OS << " if (Len == " << I->first.size() << " && !memcmp(Name, \"" << I->first << "\", " - << I->first.size() << ")) return Intrinsic::" + << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::" << Ints[I->second].EnumName << ";\n"; } OS << " }\n"; @@ -114,6 +123,23 @@ EmitIntrinsicToNameTable(const std::vector &Ints, OS << "#endif\n\n"; } +void IntrinsicEmitter:: +EmitIntrinsicToOverloadTable(const std::vector &Ints, + std::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(std::ostream &OS, MVT::SimpleValueType VT) { if (MVT(VT).isInteger()) { unsigned BitWidth = MVT(VT).getSizeInBits(); @@ -351,11 +377,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; @@ -392,7 +420,11 @@ void IntrinsicEmitter:: EmitAttributes(const std::vector &Ints, std::ostream &OS) { OS << "// Add parameter attributes that are not common to all intrinsics.\n"; OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; - OS << "AttrListPtr Intrinsic::getAttributes(ID id) {"; + 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"; @@ -404,7 +436,8 @@ EmitAttributes(const std::vector &Ints, std::ostream &OS) { 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; } } @@ -415,7 +448,8 @@ 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; } } @@ -431,7 +465,8 @@ EmitAttributes(const std::vector &Ints, std::ostream &OS) { for (unsigned i = 0, e = Ints.size(); i != e; ++i) { if (Ints[i].ArgumentAttributes.empty()) continue; - OS << " case Intrinsic::" << Ints[i].EnumName << ":\n"; + OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName + << ":\n"; std::vector > ArgAttrs = Ints[i].ArgumentAttributes; @@ -469,6 +504,37 @@ EmitAttributes(const std::vector &Ints, std::ostream &OS) { OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } +/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. +void IntrinsicEmitter:: +EmitModRefBehavior(const std::vector &Ints, std::ostream &OS){ + OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"; + OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"; + OS << "switch (id) {\n"; + OS << "default:\n return UnknownModRefBehavior;\n"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + if (Ints[i].ModRef == CodeGenIntrinsic::WriteMem) + 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: + case CodeGenIntrinsic::ReadMem: + OS << " return OnlyReadsMemory;\n"; + break; + case CodeGenIntrinsic::WriteArgMem: + OS << " return AccessesArguments;\n"; + break; + } + } + OS << "}\n"; + OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; +} + void IntrinsicEmitter:: EmitGCCBuiltinList(const std::vector &Ints, std::ostream &OS){ OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n"; @@ -495,7 +561,7 @@ EmitGCCBuiltinList(const std::vector &Ints, std::ostream &OS){ typedef std::map::const_iterator StrMapIterator; static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, unsigned CharStart, unsigned Indent, - std::ostream &OS) { + std::string TargetPrefix, std::ostream &OS) { if (Start == End) return; // empty range. // Determine what, if anything, is the same about all these strings. @@ -522,7 +588,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, OS << CommonString.size() - CharStart << "))\n"; ++Indent; } - OS << std::string(Indent*2, ' ') << "IntrinsicID = Intrinsic::"; + OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix + << "Intrinsic::"; OS << Start->second << ";\n"; return; } @@ -535,7 +602,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; OS << CommonString.size()-CharStart << ")) {\n"; - EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, OS); + EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, + TargetPrefix, OS); OS << std::string(Indent*2, ' ') << "}\n"; return; } @@ -556,7 +624,7 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar; ++NextChar) /*empty*/; - EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, OS); + EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS); OS << std::string(Indent*2, ' ') << " break;\n"; I = NextChar; } @@ -566,6 +634,7 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, /// 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, + const std::string &TargetPrefix, std::ostream &OS) { // Rearrange the builtins by length. std::vector > BuiltinsByLen; @@ -584,7 +653,7 @@ static void EmitTargetBuiltins(const std::map &BIM, if (BuiltinsByLen[i].empty()) continue; OS << " case " << i << ":\n"; EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(), - 0, 3, OS); + 0, 3, TargetPrefix, OS); OS << " break;\n"; } OS << " }\n"; @@ -613,7 +682,22 @@ 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 " + << "*TargetPrefix, const char *BuiltinName) {\n"; + OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = "; + } else { + OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " + << "*TargetPrefix, const char *BuiltinName) {\n"; + OS << " Intrinsic::ID IntrinsicID = "; + } + + if (TargetOnly) + OS << "(" << TargetPrefix<< "Intrinsic::ID)"; + + OS << "Intrinsic::not_intrinsic;\n"; // Note: this could emit significantly better code if we cared. for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ @@ -625,8 +709,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector &Ints, OS << "{\n"; // Emit the comparisons for this target prefix. - EmitTargetBuiltins(I->second, OS); + EmitTargetBuiltins(I->second, TargetPrefix, OS); OS << " }\n"; } + OS << " return IntrinsicID;\n"; + OS << "}\n"; OS << "#endif\n\n"; }