diff options
Diffstat (limited to 'utils')
26 files changed, 479 insertions, 333 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index e76fa57066..ee83311c58 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -689,18 +689,18 @@ parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) { // Split via the '='. std::pair<StringRef, StringRef> Ops = S.split('='); if (Ops.second == "") - throw TGError(Loc, "missing '=' in two-operand alias constraint"); + PrintFatalError(Loc, "missing '=' in two-operand alias constraint"); // Trim whitespace and the leading '$' on the operand names. size_t start = Ops.first.find_first_of('$'); if (start == std::string::npos) - throw TGError(Loc, "expected '$' prefix on asm operand name"); + PrintFatalError(Loc, "expected '$' prefix on asm operand name"); Ops.first = Ops.first.slice(start + 1, std::string::npos); size_t end = Ops.first.find_last_of(" \t"); Ops.first = Ops.first.slice(0, end); // Now the second operand. start = Ops.second.find_first_of('$'); if (start == std::string::npos) - throw TGError(Loc, "expected '$' prefix on asm operand name"); + PrintFatalError(Loc, "expected '$' prefix on asm operand name"); Ops.second = Ops.second.slice(start + 1, std::string::npos); end = Ops.second.find_last_of(" \t"); Ops.first = Ops.first.slice(0, end); @@ -716,11 +716,11 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { int SrcAsmOperand = findAsmOperandNamed(Ops.first); int DstAsmOperand = findAsmOperandNamed(Ops.second); if (SrcAsmOperand == -1) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "unknown source two-operand alias operand '" + Ops.first.str() + "'."); if (DstAsmOperand == -1) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "unknown destination two-operand alias operand '" + Ops.second.str() + "'."); @@ -852,15 +852,15 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { // The first token of the instruction is the mnemonic, which must be a // simple string, not a $foo variable or a singleton register. if (AsmOperands.empty()) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "Instruction '" + TheDef->getName() + "' has no tokens"); Mnemonic = AsmOperands[0].Token; if (Mnemonic.empty()) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "Missing instruction mnemonic"); // FIXME : Check and raise an error if it is a register. if (Mnemonic[0] == '$') - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); // Remove the first operand, it is tracked in the mnemonic field. @@ -870,12 +870,12 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { // Reject matchables with no .s string. if (AsmString.empty()) - throw TGError(TheDef->getLoc(), "instruction with empty asm string"); + PrintFatalError(TheDef->getLoc(), "instruction with empty asm string"); // Reject any matchables with a newline in them, they should be marked // isCodeGenOnly if they are pseudo instructions. if (AsmString.find('\n') != std::string::npos) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "multiline instruction is not valid for the asmparser, " "mark it isCodeGenOnly"); @@ -883,7 +883,7 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { // has one line. if (!CommentDelimiter.empty() && StringRef(AsmString).find(CommentDelimiter) != StringRef::npos) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "asmstring for instruction has comment character in it, " "mark it isCodeGenOnly"); @@ -897,7 +897,7 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { StringRef Tok = AsmOperands[i].Token; if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "matchable with operand modifier '" + Tok.str() + "' not supported by asm matcher. Mark isCodeGenOnly!"); @@ -905,7 +905,7 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { // We reject aliases and ignore instructions for now. if (Tok[0] == '$' && !OperandNames.insert(Tok).second) { if (!Hack) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "ERROR: matchable with tied operand '" + Tok.str() + "' can never be matched!"); // FIXME: Should reject these. The ARM backend hits this with $lane in a @@ -1004,8 +1004,8 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { // use it, else just fall back to the underlying register class. const RecordVal *R = Rec->getValue("ParserMatchClass"); if (R == 0 || R->getValue() == 0) - throw "Record `" + Rec->getName() + - "' does not have a ParserMatchClass!\n"; + PrintFatalError("Record `" + Rec->getName() + + "' does not have a ParserMatchClass!\n"); if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) { Record *MatchClass = DI->getDef(); @@ -1016,28 +1016,28 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { // No custom match class. Just use the register class. Record *ClassRec = Rec->getValueAsDef("RegClass"); if (!ClassRec) - throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() + + PrintFatalError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() + "' has no associated register class!\n"); if (ClassInfo *CI = RegisterClassClasses[ClassRec]) return CI; - throw TGError(Rec->getLoc(), "register class has no class info!"); + PrintFatalError(Rec->getLoc(), "register class has no class info!"); } if (Rec->isSubClassOf("RegisterClass")) { if (ClassInfo *CI = RegisterClassClasses[Rec]) return CI; - throw TGError(Rec->getLoc(), "register class has no class info!"); + PrintFatalError(Rec->getLoc(), "register class has no class info!"); } if (!Rec->isSubClassOf("Operand")) - throw TGError(Rec->getLoc(), "Operand `" + Rec->getName() + + PrintFatalError(Rec->getLoc(), "Operand `" + Rec->getName() + "' does not derive from class Operand!\n"); Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); if (ClassInfo *CI = AsmOperandClasses[MatchClass]) return CI; - throw TGError(Rec->getLoc(), "operand has no match class!"); + PrintFatalError(Rec->getLoc(), "operand has no match class!"); } void AsmMatcherInfo:: @@ -1287,7 +1287,7 @@ void AsmMatcherInfo::buildInfo() { continue; if (Pred->getName().empty()) - throw TGError(Pred->getLoc(), "Predicate has no name!"); + PrintFatalError(Pred->getLoc(), "Predicate has no name!"); unsigned FeatureNo = SubtargetFeatures.size(); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); @@ -1468,7 +1468,7 @@ void AsmMatcherInfo::buildInfo() { ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); if (FromClass == ToClass) - throw TGError(Rec->getLoc(), + PrintFatalError(Rec->getLoc(), "error: Destination value identical to source value."); FromClass->SuperClasses.push_back(ToClass); } @@ -1490,7 +1490,7 @@ buildInstructionOperandReference(MatchableInfo *II, // Map this token to an operand. unsigned Idx; if (!Operands.hasOperandNamed(OperandName, Idx)) - throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + + PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" + OperandName.str() + "'"); // If the instruction operand has multiple suboperands, but the parser @@ -1561,7 +1561,7 @@ void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II, return; } - throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + + PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" + OperandName.str() + "'"); } @@ -1583,7 +1583,7 @@ void MatchableInfo::buildInstructionResultOperands() { // Find out what operand from the asmparser this MCInst operand comes from. int SrcOperand = findAsmOperandNamed(OpInfo.Name); if (OpInfo.Name.empty() || SrcOperand == -1) - throw TGError(TheDef->getLoc(), "Instruction '" + + PrintFatalError(TheDef->getLoc(), "Instruction '" + TheDef->getName() + "' has operand '" + OpInfo.Name + "' that doesn't appear in asm string!"); @@ -1635,7 +1635,7 @@ void MatchableInfo::buildAliasResultOperands() { StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); int SrcOperand = findAsmOperand(Name, SubIdx); if (SrcOperand == -1) - throw TGError(TheDef->getLoc(), "Instruction '" + + PrintFatalError(TheDef->getLoc(), "Instruction '" + TheDef->getName() + "' has operand '" + OpName + "' that doesn't appear in asm string!"); unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1); @@ -2270,7 +2270,7 @@ static std::string GetAliasRequiredFeatures(Record *R, SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); if (F == 0) - throw TGError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + + PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + "' is not marked as an AssemblerPredicate!"); if (NumFeatures) @@ -2333,14 +2333,14 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) { // We can't have two aliases from the same mnemonic with no predicate. PrintError(ToVec[AliasWithNoPredicate]->getLoc(), "two MnemonicAliases with the same 'from' mnemonic!"); - throw TGError(R->getLoc(), "this is the other MnemonicAlias."); + PrintFatalError(R->getLoc(), "this is the other MnemonicAlias."); } AliasWithNoPredicate = i; continue; } if (R->getValueAsString("ToMnemonic") == I->first) - throw TGError(R->getLoc(), "MnemonicAlias to the same string"); + PrintFatalError(R->getLoc(), "MnemonicAlias to the same string"); if (!MatchCode.empty()) MatchCode += "else "; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 9e453e0f6d..a4114d9815 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -566,9 +566,9 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, std::vector<std::string> AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames"); if (AltNames.size() <= Idx) - throw TGError(Reg.TheDef->getLoc(), - (Twine("Register definition missing alt name for '") + - AltName + "'.").str()); + PrintFatalError(Reg.TheDef->getLoc(), + (Twine("Register definition missing alt name for '") + + AltName + "'.").str()); AsmName = AltNames[Idx]; } } diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 350a2ccfcc..fe1f756361 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -14,6 +14,7 @@ #include "AsmWriterInst.h" #include "CodeGenTarget.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" using namespace llvm; @@ -123,8 +124,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, != std::string::npos) { AddLiteralString(std::string(1, AsmString[DollarPos+1])); } else { - throw "Non-supported escaped character found in instruction '" + - CGI.TheDef->getName() + "'!"; + PrintFatalError("Non-supported escaped character found in instruction '" + + CGI.TheDef->getName() + "'!"); } LastEmitted = DollarPos+2; continue; @@ -162,15 +163,15 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, // brace. if (hasCurlyBraces) { if (VarEnd >= AsmString.size()) - throw "Reached end of string before terminating curly brace in '" - + CGI.TheDef->getName() + "'"; + PrintFatalError("Reached end of string before terminating curly brace in '" + + CGI.TheDef->getName() + "'"); // Look for a modifier string. if (AsmString[VarEnd] == ':') { ++VarEnd; if (VarEnd >= AsmString.size()) - throw "Reached end of string before terminating curly brace in '" - + CGI.TheDef->getName() + "'"; + PrintFatalError("Reached end of string before terminating curly brace in '" + + CGI.TheDef->getName() + "'"); unsigned ModifierStart = VarEnd; while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) @@ -178,17 +179,17 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, Modifier = std::string(AsmString.begin()+ModifierStart, AsmString.begin()+VarEnd); if (Modifier.empty()) - throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"; + PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"); } if (AsmString[VarEnd] != '}') - throw "Variable name beginning with '{' did not end with '}' in '" - + CGI.TheDef->getName() + "'"; + PrintFatalError("Variable name beginning with '{' did not end with '}' in '" + + CGI.TheDef->getName() + "'"); ++VarEnd; } if (VarName.empty() && Modifier.empty()) - throw "Stray '$' in '" + CGI.TheDef->getName() + - "' asm string, maybe you want $$?"; + PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() + + "' asm string, maybe you want $$?"); if (VarName.empty()) { // Just a modifier, pass this into PrintSpecial. diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 116fa57522..d0416c9081 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -1,4 +1,3 @@ -set(LLVM_REQUIRES_EH 1) set(LLVM_LINK_COMPONENTS Support) add_tablegen(llvm-tblgen LLVM diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index dff97f4e83..94f3c6518c 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <cassert> @@ -93,7 +94,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << Action->getValueAsString("Predicate"); } else { Action->dump(); - throw "Unknown CCPredicateAction!"; + PrintFatalError("Unknown CCPredicateAction!"); } O << ") {\n"; @@ -131,7 +132,7 @@ void CallingConvEmitter::EmitAction(Record *Action, ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); if (ShadowRegList->getSize() >0 && ShadowRegList->getSize() != RegList->getSize()) - throw "Invalid length of list of shadowed registers"; + PrintFatalError("Invalid length of list of shadowed registers"); if (RegList->getSize() == 1) { O << IndentStr << "if (unsigned Reg = State.AllocateReg("; @@ -221,7 +222,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << IndentStr << "return false;\n"; } else { Action->dump(); - throw "Unknown CCAction!"; + PrintFatalError("Unknown CCAction!"); } } } diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 3b5511c056..d5b581b598 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -79,14 +79,19 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, const std::vector<MVT::SimpleValueType> &LegalTypes = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); + if (TP.hasError()) + return false; + for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) if (Pred == 0 || Pred(LegalTypes[i])) TypeVec.push_back(LegalTypes[i]); // If we have nothing that matches the predicate, bail out. - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, no " + std::string(PredicateName) + " types found"); + return false; + } // No need to sort with one element. if (TypeVec.size() == 1) return true; @@ -146,9 +151,9 @@ std::string EEVT::TypeSet::getName() const { /// MergeInTypeInfo - This merges in type information from the specified /// argument. If 'this' changes, it returns true. If the two types are -/// contradictory (e.g. merge f32 into i32) then this throws an exception. +/// contradictory (e.g. merge f32 into i32) then this flags an error. bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ - if (InVT.isCompletelyUnknown() || *this == InVT) + if (InVT.isCompletelyUnknown() || *this == InVT || TP.hasError()) return false; if (isCompletelyUnknown()) { @@ -224,11 +229,13 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, merging '" + InVT.getName() + "' into '" + InputSet.getName() + "'"); - return true; // unreachable + return false; } /// EnforceInteger - Remove all non-integer types from this set. bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { + if (TP.hasError()) + return false; // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isInteger, "integer"); @@ -242,14 +249,18 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { if (!isInteger(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be integer"); + return false; + } return true; } /// EnforceFloatingPoint - Remove all integer types from this set. bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { + if (TP.hasError()) + return false; // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isFloatingPoint, "floating point"); @@ -264,14 +275,19 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { if (!isFloatingPoint(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be floating point"); + return false; + } return true; } /// EnforceScalar - Remove all vector types from this. bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { + if (TP.hasError()) + return false; + // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isScalar, "scalar"); @@ -286,14 +302,19 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { if (!isScalar(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be scalar"); + return false; + } return true; } /// EnforceVector - Remove all vector types from this. bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { + if (TP.hasError()) + return false; + // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isVector, "vector"); @@ -308,9 +329,11 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { MadeChange = true; } - if (TypeVec.empty()) + if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be a vector"); + return false; + } return MadeChange; } @@ -319,6 +342,9 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update /// this an other based on this information. bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { + if (TP.hasError()) + return false; + // Both operands must be integer or FP, but we don't care which. bool MadeChange = false; @@ -365,19 +391,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { if (hasVectorTypes() && Other.hasVectorTypes()) { if (Type.getSizeInBits() >= OtherType.getSizeInBits()) if (Type.getVectorElementType().getSizeInBits() - >= OtherType.getVectorElementType().getSizeInBits()) + >= OtherType.getVectorElementType().getSizeInBits()) { TP.error("Type inference contradiction found, '" + getName() + "' element type not smaller than '" + Other.getName() +"'!"); + return false; + } } else // For scalar types, the bitsize of this type must be larger // than that of the other. - if (Type.getSizeInBits() >= OtherType.getSizeInBits()) + if (Type.getSizeInBits() >= OtherType.getSizeInBits()) { TP.error("Type inference contradiction found, '" + getName() + "' is not smaller than '" + Other.getName() +"'!"); - + return false; + } } @@ -437,9 +466,11 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // If this is the only type in the large set, the constraint can never be // satisfied. if ((Other.hasIntegerTypes() && OtherIntSize == 0) - || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) + || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) { TP.error("Type inference contradiction found, '" + Other.getName() + "' has nothing larger than '" + getName() +"'!"); + return false; + } // Okay, find the largest type in the Other set and remove it from the // current set. @@ -493,9 +524,11 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // If this is the only type in the small set, the constraint can never be // satisfied. if ((hasIntegerTypes() && IntSize == 0) - || (hasFloatingPointTypes() && FPSize == 0)) + || (hasFloatingPointTypes() && FPSize == 0)) { TP.error("Type inference contradiction found, '" + getName() + "' has nothing smaller than '" + Other.getName()+"'!"); + return false; + } return MadeChange; } @@ -504,6 +537,9 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { /// whose element is specified by VTOperand. bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { + if (TP.hasError()) + return false; + // "This" must be a vector and "VTOperand" must be a scalar. bool MadeChange = false; MadeChange |= EnforceVector(TP); @@ -535,9 +571,11 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, } } - if (TypeVec.empty()) // FIXME: Really want an SMLoc here! + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have a vector element"); + return false; + } return MadeChange; } @@ -769,7 +807,7 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { ConstraintType = SDTCisVT; x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); if (x.SDTCisVT_Info.VT == MVT::isVoid) - throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); + PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); } else if (R->isSubClassOf("SDTCisPtrTy")) { ConstraintType = SDTCisPtrTy; @@ -829,11 +867,13 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, /// ApplyTypeConstraint - Given a node in a pattern, apply this type /// constraint to the nodes operands. This returns true if it makes a -/// change, false otherwise. If a type contradiction is found, throw an -/// exception. +/// change, false otherwise. If a type contradiction is found, flag an error. bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const { + if (TP.hasError()) + return false; + unsigned ResNo = 0; // The result number being referenced. TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); @@ -866,8 +906,10 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, if (!NodeToApply->isLeaf() || !isa<DefInit>(NodeToApply->getLeafValue()) || !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef() - ->isSubClassOf("ValueType")) + ->isSubClassOf("ValueType")) { TP.error(N->getOperator()->getName() + " expects a VT operand!"); + return false; + } MVT::SimpleValueType VT = getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()); @@ -1176,7 +1218,11 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { /// fragments, inline them into place, giving us a pattern without any /// PatFrag references. TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { - if (isLeaf()) return this; // nothing to do. + if (TP.hasError()) + return 0; + + if (isLeaf()) + return this; // nothing to do. Record *Op = getOperator(); if (!Op->isSubClassOf("PatFrag")) { @@ -1199,9 +1245,11 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); // Verify that we are passing the right number of operands. - if (Frag->getNumArgs() != Children.size()) + if (Frag->getNumArgs() != Children.size()) { TP.error("'" + Op->getName() + "' fragment requires " + utostr(Frag->getNumArgs()) + " operands!"); + return 0; + } TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); @@ -1375,9 +1423,11 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { /// ApplyTypeConstraints - Apply all of the type constraints relevant to /// this node and its children in the tree. This returns true if it makes a -/// change, false otherwise. If a type contradiction is found, throw an -/// exception. +/// change, false otherwise. If a type contradiction is found, flag an error. bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { + if (TP.hasError()) + return false; + CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); if (isLeaf()) { if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { @@ -1414,7 +1464,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { TP.error("Integer value '" + itostr(II->getValue()) + "' is out of range for type '" + getEnumName(getType(0)) + "'!"); - return MadeChange; + return false; } return false; } @@ -1477,10 +1527,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { for (unsigned i = 0, e = NumRetVTs; i != e; ++i) MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); - if (getNumChildren() != NumParamVTs + 1) + if (getNumChildren() != NumParamVTs + 1) { TP.error("Intrinsic '" + Int->Name + "' expects " + utostr(NumParamVTs) + " operands, not " + utostr(getNumChildren() - 1) + " operands!"); + return false; + } // Apply type info to the intrinsic ID. MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); @@ -1500,9 +1552,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Check that the number of operands is sane. Negative operands -> varargs. if (NI.getNumOperands() >= 0 && - getNumChildren() != (unsigned)NI.getNumOperands()) + getNumChildren() != (unsigned)NI.getNumOperands()) { TP.error(getOperator()->getName() + " node requires exactly " + itostr(NI.getNumOperands()) + " operands!"); + return false; + } bool MadeChange = NI.ApplyTypeConstraints(this, TP); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) @@ -1576,9 +1630,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { continue; // Verify that we didn't run out of provided operands. - if (ChildNo >= getNumChildren()) + if (ChildNo >= getNumChildren()) { TP.error("Instruction |