diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 21 | ||||
-rw-r--r-- | utils/TableGen/CodeGenIntrinsics.h | 36 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 45 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 134 |
4 files changed, 170 insertions, 66 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index e987c2bc82..859a8ccac8 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -471,7 +471,8 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs, } if (getExtTypeNum(0) == MVT::iPTR || getExtTypeNum(0) == MVT::iPTRAny) { - if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny || ExtVTs[0] == EMVT::isInt) + if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny || + ExtVTs[0] == EMVT::isInt) return false; if (EMVT::isExtIntegerInVTs(ExtVTs)) { std::vector<unsigned char> FVTs = FilterEVTs(ExtVTs, isInteger); @@ -885,18 +886,22 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool MadeChange = false; // Apply the result type to the node. - MadeChange = UpdateNodeType(Int->ArgVTs[0], TP); + unsigned NumRetVTs = Int->IS.RetVTs.size(); + unsigned NumParamVTs = Int->IS.ParamVTs.size(); - if (getNumChildren() != Int->ArgVTs.size()) + for (unsigned i = 0, e = NumRetVTs; i != e; ++i) + MadeChange |= UpdateNodeType(Int->IS.RetVTs[i], TP); + + if (getNumChildren() != NumParamVTs + NumRetVTs) TP.error("Intrinsic '" + Int->Name + "' expects " + - utostr(Int->ArgVTs.size()-1) + " operands, not " + - utostr(getNumChildren()-1) + " operands!"); + utostr(NumParamVTs + NumRetVTs - 1) + " operands, not " + + utostr(getNumChildren() - 1) + " operands!"); // Apply type info to the intrinsic ID. MadeChange |= getChild(0)->UpdateNodeType(MVT::iPTR, TP); - for (unsigned i = 1, e = getNumChildren(); i != e; ++i) { - MVT::SimpleValueType OpVT = Int->ArgVTs[i]; + for (unsigned i = NumRetVTs, e = getNumChildren(); i != e; ++i) { + MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i - NumRetVTs]; MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP); MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); } @@ -1232,7 +1237,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { // If this intrinsic returns void, it must have side-effects and thus a // chain. - if (Int.ArgVTs[0] == MVT::isVoid) { + if (Int.IS.RetVTs[0] == MVT::isVoid) { Operator = getDAGPatterns().get_intrinsic_void_sdnode(); } else if (Int.ModRef != CodeGenIntrinsic::NoMem) { // Has side-effects, requires chain. diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 4de93864a8..1170da0f35 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -30,16 +30,34 @@ namespace llvm { std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "". std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics. - /// ArgVTs - The MVT::SimpleValueType for each argument type. Note that - /// this list is only populated when in the context of a target .td file. - /// When building Intrinsics.td, this isn't available, because we don't know - /// the target pointer size. - std::vector<MVT::SimpleValueType> ArgVTs; + /// IntrinsicSignature - This structure holds the return values and + /// parameter values of an intrinsic. If the number of return values is > 1, + /// then the intrinsic implicitly returns a first-class aggregate. The + /// numbering of the types starts at 0 with the first return value and + /// continues from there throug the parameter list. This is useful for + /// "matching" types. + struct IntrinsicSignature { + /// RetVTs - The MVT::SimpleValueType for each return type. Note that this + /// list is only populated when in the context of a target .td file. When + /// building Intrinsics.td, this isn't available, because we don't know + /// the target pointer size. + std::vector<MVT::SimpleValueType> RetVTs; + + /// RetTypeDefs - The records for each return type. + std::vector<Record*> RetTypeDefs; + + /// ParamVTs - The MVT::SimpleValueType for each parameter type. Note that + /// this list is only populated when in the context of a target .td file. + /// When building Intrinsics.td, this isn't available, because we don't + /// know the target pointer size. + std::vector<MVT::SimpleValueType> ParamVTs; + + /// ParamTypeDefs - The records for each parameter type. + std::vector<Record*> ParamTypeDefs; + }; + + IntrinsicSignature IS; - /// ArgTypeDefs - The records for each argument type. - /// - std::vector<Record*> ArgTypeDefs; - // Memory mod/ref behavior of this intrinsic. enum { NoMem, ReadArgMem, ReadMem, WriteArgMem, WriteMem diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 4e7a10c1d8..2ff1b19542 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -438,25 +438,27 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isCommutative = false; if (DefName.size() <= 4 || - std::string(DefName.begin(), DefName.begin()+4) != "int_") + std::string(DefName.begin(), DefName.begin() + 4) != "int_") throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; + EnumName = std::string(DefName.begin()+4, DefName.end()); + if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); - TargetPrefix = R->getValueAsString("TargetPrefix"); + + TargetPrefix = R->getValueAsString("TargetPrefix"); Name = R->getValueAsString("LLVMName"); + if (Name == "") { // If an explicit name isn't specified, derive one from the DefName. Name = "llvm."; + for (unsigned i = 0, e = EnumName.size(); i != e; ++i) - if (EnumName[i] == '_') - Name += '.'; - else - Name += EnumName[i]; + Name += (EnumName[i] == '_') ? '.' : EnumName[i]; } else { // Verify it starts with "llvm.". if (Name.size() <= 5 || - std::string(Name.begin(), Name.begin()+5) != "llvm.") + std::string(Name.begin(), Name.begin() + 5) != "llvm.") throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; } @@ -464,26 +466,37 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // "llvm.<targetprefix>.". if (!TargetPrefix.empty()) { if (Name.size() < 6+TargetPrefix.size() || - std::string(Name.begin()+5, Name.begin()+6+TargetPrefix.size()) - != (TargetPrefix+".")) - throw "Intrinsic '" + DefName + "' does not start with 'llvm." + + std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) + != (TargetPrefix + ".")) + throw "Intrinsic '" + DefName + "' does not start with 'llvm." + TargetPrefix + ".'!"; } - // Parse the list of argument types. - ListInit *TypeList = R->getValueAsListInit("Types"); + // Parse the list of return types. + ListInit *TypeList = R->getValueAsListInit("RetTypes"); for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT")); isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny; - ArgVTs.push_back(VT); - ArgTypeDefs.push_back(TyEl); + IS.RetVTs.push_back(VT); + IS.RetTypeDefs.push_back(TyEl); } - if (ArgVTs.size() == 0) + + if (IS.RetVTs.size() == 0) throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!"; - + // Parse the list of parameter types. + TypeList = R->getValueAsListInit("ParamTypes"); + for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { + Record *TyEl = TypeList->getElementAsRecord(i); + assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); + MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT")); + isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny; + IS.ParamVTs.push_back(VT); + IS.ParamTypeDefs.push_back(TyEl); + } + // Parse the intrinsic properties. ListInit *PropList = R->getValueAsListInit("Properties"); for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) { diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index ade1c8c664..9247a85d22 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -138,7 +138,27 @@ static void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) { } } -static void EmitTypeGenerate(std::ostream &OS, Record *ArgType, +static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, + unsigned &ArgNo); + +static void EmitTypeGenerate(std::ostream &OS, + const std::vector<Record*> &ArgTypes, + unsigned &ArgNo) { + if (ArgTypes.size() == 1) { + EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); + return; + } + + OS << "StructType::get("; + + for (std::vector<Record*>::const_iterator + I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) + EmitTypeGenerate(OS, *I, ArgNo); + + OS << ", NULL)"; +} + +static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, unsigned &ArgNo) { MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); @@ -184,17 +204,37 @@ static void EmitTypeGenerate(std::ostream &OS, Record *ArgType, /// RecordListComparator - Provide a determinstic comparator for lists of /// records. namespace { + typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair; struct RecordListComparator { - bool operator()(const std::vector<Record*> &LHS, - const std::vector<Record*> &RHS) const { + bool operator()(const RecPair &LHS, + const RecPair &RHS) const { unsigned i = 0; + const std::vector<Record*> *LHSVec = &LHS.first; + const std::vector<Record*> *RHSVec = &RHS.first; + unsigned RHSSize = RHSVec->size(); + unsigned LHSSize = LHSVec->size(); + do { - if (i == RHS.size()) return false; // RHS is shorter than LHS. - if (LHS[i] != RHS[i]) - return LHS[i]->getName() < RHS[i]->getName(); - } while (++i != LHS.size()); - - return i != RHS.size(); + 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 false; + + i = 0; + LHSVec = &LHS.second; + RHSVec = &RHS.second; + RHSSize = RHSVec->size(); + LHSSize = LHSVec->size(); + + for (i = 0; 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(); + } + + return i != RHSSize; } }; } @@ -209,26 +249,33 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, // This checking can emit a lot of very common code. To reduce the amount of // code that we emit, batch up cases that have identical types. This avoids // problems where GCC can run out of memory compiling Verifier.cpp. - typedef std::map<std::vector<Record*>, std::vector<unsigned>, - RecordListComparator> MapTy; + typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; MapTy UniqueArgInfos; // Compute the unique argument type info. for (unsigned i = 0, e = Ints.size(); i != e; ++i) - UniqueArgInfos[Ints[i].ArgTypeDefs].push_back(i); + UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, + Ints[i].IS.ParamTypeDefs)].push_back(i); // Loop through the array, emitting one comparison for each batch. for (MapTy::iterator I = UniqueArgInfos.begin(), E = UniqueArgInfos.end(); I != E; ++I) { - for (unsigned i = 0, e = I->second.size(); 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"; - } - const std::vector<Record*> &ArgTypes = I->first; - OS << " VerifyIntrinsicPrototype(ID, IF, " << ArgTypes.size() << ", "; - for (unsigned j = 0; j != ArgTypes.size(); ++j) { - Record *ArgType = ArgTypes[j]; + const RecPair &ArgTypes = I->first; + const std::vector<Record*> &RetTys = ArgTypes.first; + const std::vector<Record*> &ParamTys = ArgTypes.second; + + OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", " + << ParamTys.size(); + + // Emit return types. + for (unsigned j = 0, je = RetTys.size(); j != je; ++j) { + Record *ArgType = RetTys[j]; + OS << ", "; + if (ArgType->isSubClassOf("LLVMMatchType")) { unsigned Number = ArgType->getValueAsInt("Number"); assert(Number < j && "Invalid matching number!"); @@ -236,11 +283,28 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, } else { MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); OS << getEnumName(VT); - if (VT == MVT::isVoid && j != 0 && j != ArgTypes.size()-1) + + if (VT == MVT::isVoid && j != 0 && j != je - 1) + throw "Var arg type not last argument"; + } + } + + // Emit the parameter types. + for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) { + Record *ArgType = ParamTys[j]; + OS << ", "; + + if (ArgType->isSubClassOf("LLVMMatchType")) { + unsigned Number = ArgType->getValueAsInt("Number"); + assert(Number < j + RetTys.size() && "Invalid matching number!"); + OS << "~" << Number; + } else { + MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); + OS << getEnumName(VT); + + if (VT == MVT::isVoid && j != 0 && j != je - 1) throw "Var arg type not last argument"; } - if (j != ArgTypes.size()-1) - OS << ", "; } OS << ");\n"; @@ -259,43 +323,47 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical // types. - typedef std::map<std::vector<Record*>, std::vector<unsigned>, - RecordListComparator> MapTy; + typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; MapTy UniqueArgInfos; // Compute the unique argument type info. for (unsigned i = 0, e = Ints.size(); i != e; ++i) - UniqueArgInfos[Ints[i].ArgTypeDefs].push_back(i); + UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, + Ints[i].IS.ParamTypeDefs)].push_back(i); // Loop through the array, emitting one generator for each batch. for (MapTy::iterator I = UniqueArgInfos.begin(), E = UniqueArgInfos.end(); I != E; ++I) { - for (unsigned i = 0, e = I->second.size(); 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"; - } - const std::vector<Record*> &ArgTypes = I->first; - unsigned N = ArgTypes.size(); + const RecPair &ArgTypes = I->first; + const std::vector<Record*> &RetTys = ArgTypes.first; + const std::vector<Record*> &ParamTys = ArgTypes.second; + + unsigned N = ParamTys.size(); if (N > 1 && - getValueType(ArgTypes[N-1]->getValueAsDef("VT")) == MVT::isVoid) { + getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) { OS << " IsVarArg = true;\n"; --N; } - + unsigned ArgNo = 0; OS << " ResultTy = "; - EmitTypeGenerate(OS, ArgTypes[0], ArgNo); + EmitTypeGenerate(OS, RetTys, ArgNo); OS << ";\n"; - for (unsigned j = 1; j != N; ++j) { + for (unsigned j = 0; j != N; ++j) { OS << " ArgTys.push_back("; - EmitTypeGenerate(OS, ArgTypes[j], ArgNo); + EmitTypeGenerate(OS, ParamTys[j], ArgNo); OS << ");\n"; } + OS << " break;\n"; } + OS << " }\n"; OS << "#endif\n\n"; } |