diff options
32 files changed, 488 insertions, 452 deletions
diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h index 3f7b7f4e8c..2f6b7e625c 100644 --- a/include/llvm/TableGen/Error.h +++ b/include/llvm/TableGen/Error.h @@ -19,26 +19,13 @@ namespace llvm { -class TGError { - SmallVector<SMLoc, 4> Locs; - std::string Message; -public: - TGError(ArrayRef<SMLoc> locs, const std::string &message) - : Locs(locs.begin(), locs.end()), Message(message) {} - - ArrayRef<SMLoc> getLoc() const { return Locs; } - const std::string &getMessage() const { return Message; } -}; - void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg); void PrintWarning(const char *Loc, const Twine &Msg); void PrintWarning(const Twine &Msg); -void PrintWarning(const TGError &Warning); void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg); void PrintError(const char *Loc, const Twine &Msg); void PrintError(const Twine &Msg); -void PrintError(const TGError &Error); LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const std::string &Msg); LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, diff --git a/lib/TableGen/CMakeLists.txt b/lib/TableGen/CMakeLists.txt index 4f64eb4ff2..935d674a36 100644 --- a/lib/TableGen/CMakeLists.txt +++ b/lib/TableGen/CMakeLists.txt @@ -1,5 +1,3 @@ -set(LLVM_REQUIRES_EH 1) - add_llvm_library(LLVMTableGen Error.cpp Main.cpp diff --git a/lib/TableGen/Error.cpp b/lib/TableGen/Error.cpp index ad98fba9ba..0bb86b0686 100644 --- a/lib/TableGen/Error.cpp +++ b/lib/TableGen/Error.cpp @@ -45,10 +45,6 @@ void PrintWarning(const Twine &Msg) { errs() << "warning:" << Msg << "\n"; } -void PrintWarning(const TGError &Warning) { - PrintWarning(Warning.getLoc(), Warning.getMessage()); -} - void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) { PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg); } @@ -61,10 +57,6 @@ void PrintError(const Twine &Msg) { errs() << "error:" << Msg << "\n"; } -void PrintError(const TGError &Error) { - PrintError(Error.getLoc(), Error.getMessage()); -} - void PrintFatalError(const std::string &Msg) { PrintError(Twine(Msg)); std::exit(1); diff --git a/lib/TableGen/Main.cpp b/lib/TableGen/Main.cpp index d87d175502..d0ca756016 100644 --- a/lib/TableGen/Main.cpp +++ b/lib/TableGen/Main.cpp @@ -80,56 +80,46 @@ namespace llvm { int TableGenMain(char *argv0, TableGenMainFn *MainFn) { RecordKeeper Records; - try { - // Parse the input file. - OwningPtr<MemoryBuffer> File; - if (error_code ec = - MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { - errs() << "Could not open input file '" << InputFilename << "': " - << ec.message() <<"\n"; - return 1; - } - MemoryBuffer *F = File.take(); - - // Tell SrcMgr about this buffer, which is what TGParser will pick up. - SrcMgr.AddNewSourceBuffer(F, SMLoc()); - - // Record the location of the include directory so that the lexer can find - // it later. - SrcMgr.setIncludeDirs(IncludeDirs); - - TGParser Parser(SrcMgr, Records); - - if (Parser.ParseFile()) - return 1; - - std::string Error; - tool_output_file Out(OutputFilename.c_str(), Error); - if (!Error.empty()) { - errs() << argv0 << ": error opening " << OutputFilename - << ":" << Error << "\n"; - return 1; - } - if (!DependFilename.empty()) - if (int Ret = createDependencyFile(Parser, argv0)) - return Ret; - - if (MainFn(Out.os(), Records)) - return 1; - - // Declare success. - Out.keep(); - return 0; - - } catch (const TGError &Error) { - PrintError(Error); - } catch (const std::string &Error) { - PrintError(Error); - } catch (const char *Error) { - PrintError(Error); - } catch (...) { - errs() << argv0 << ": Unknown unexpected exception occurred.\n"; + // Parse the input file. + OwningPtr<MemoryBuffer> File; + if (error_code ec = + MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { + errs() << "Could not open input file '" << InputFilename << "': " + << ec.message() <<"\n"; + return 1; } + MemoryBuffer *F = File.take(); + + // Tell SrcMgr about this buffer, which is what TGParser will pick up. + SrcMgr.AddNewSourceBuffer(F, SMLoc()); + + // Record the location of the include directory so that the lexer can find + // it later. + SrcMgr.setIncludeDirs(IncludeDirs); + + TGParser Parser(SrcMgr, Records); + + if (Parser.ParseFile()) + return 1; + + std::string Error; + tool_output_file Out(OutputFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv0 << ": error opening " << OutputFilename + << ":" << Error << "\n"; + return 1; + } + if (!DependFilename.empty()) { + if (int Ret = createDependencyFile(Parser, argv0)) + return Ret; + } + + if (MainFn(Out.os(), Records)) + return 1; + + // Declare success. + Out.keep(); + return 0; return 1; } diff --git a/lib/TableGen/Makefile b/lib/TableGen/Makefile index 732d8a197e..345db3465c 100644 --- a/lib/TableGen/Makefile +++ b/lib/TableGen/Makefile @@ -11,6 +11,4 @@ LEVEL = ../.. LIBRARYNAME = LLVMTableGen BUILD_ARCHIVE = 1 -REQUIRES_EH = 1 - include $(LEVEL)/Makefile.common diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index c7b2de2b0f..11feb43542 100644 --- a/lib/TableGen/Record.cpp +++ b/lib/TableGen/Record.cpp @@ -616,7 +616,8 @@ ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) const { Record *ListInit::getElementAsRecord(unsigned i) const { assert(i < Values.size() && "List element index out of range!"); DefInit *DI = dyn_cast<DefInit>(Values[i]); - if (DI == 0) throw "Expected record in list!"; + if (DI == 0) + PrintFatalError("Expected record in list!"); return DI->getDef(); } @@ -725,7 +726,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) { if (RV->getType() != getType()) - throw "type mismatch in cast"; + PrintFatalError("type mismatch in cast"); return VarInit::get(Name, RV->getType()); } @@ -737,7 +738,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { assert(RV && "Template arg doesn't exist??"); if (RV->getType() != getType()) - throw "type mismatch in cast"; + PrintFatalError("type mismatch in cast"); return VarInit::get(TemplateArgName, RV->getType()); } @@ -751,7 +752,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { assert(RV && "Template arg doesn't exist??"); if (RV->getType() != getType()) - throw "type mismatch in cast"; + PrintFatalError("type mismatch in cast"); return VarInit::get(MCName, RV->getType()); } @@ -760,7 +761,8 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { if (Record *D = (CurRec->getRecords()).getDef(Name)) return DefInit::get(D); - throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n"); + PrintFatalError(CurRec->getLoc(), + "Undefined reference:'" + Name + "'\n"); } } break; @@ -860,7 +862,7 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { DefInit *LOp = dyn_cast<DefInit>(LHSs->getOperator()); DefInit *ROp = dyn_cast<DefInit>(RHSs->getOperator()); if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef()) - throw "Concated Dag operators do not match!"; + PrintFatalError("Concated Dag operators do not match!"); std::vector<Init*> Args; std::vector<std::string> ArgNames; for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) { @@ -1027,14 +1029,13 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, OpInit *RHSo = dyn_cast<OpInit>(RHS); if (!RHSo) { - throw TGError(CurRec->getLoc(), "!foreach requires an operator\n"); + PrintFatalError(CurRec->getLoc(), "!foreach requires an operator\n"); } TypedInit *LHSt = dyn_cast<TypedInit>(LHS); - if (!LHSt) { - throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n"); - } + if (!LHSt) + PrintFatalError(CurRec->getLoc(), "!foreach requires typed variable\n"); if ((MHSd && isa<DagRecTy>(Type)) || (MHSl && isa<ListRecTy>(Type))) { if (MHSd) { @@ -1632,7 +1633,7 @@ void Record::checkName() { assert(TypedName && "Record name is not typed!"); RecTy *Type = TypedName->getType(); if (!isa<StringRecTy>(Type)) - throw TGError(getLoc(), "Record name is not a string!"); + PrintFatalError(getLoc(), "Record name is not a string!"); } DefInit *Record::getDefInit() { @@ -1683,7 +1684,7 @@ void Record::resolveReferencesTo(const RecordVal *RV) { continue; if (Init *V = Values[i].getValue()) if (Values[i].setValue(V->resolveReferences(*this, RV))) - throw TGError(getLoc(), "Invalid value is found when setting '" + PrintFatalError(getLoc(), "Invalid value is found when setting '" + Values[i].getNameInitAsString() + "' after resolving references" + (RV ? " against '" + RV->getNameInitAsString() @@ -1738,68 +1739,68 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { } /// getValueInit - Return the initializer for a value with the specified name, -/// or throw an exception if the field does not exist. +/// or abort if the field does not exist. /// Init *Record::getValueInit(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); return R->getValue(); } /// getValueAsString - This method looks up the specified field and returns its -/// value as a string, throwing an exception if the field does not exist or if +/// value as a string, aborts if the field does not exist or if /// the value is not a string. /// std::string Record::getValueAsString(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (StringInit *SI = dyn_cast<StringInit>(R->getValue())) return SI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a string initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a string initializer!"); } /// getValueAsBitsInit - This method looks up the specified field and returns -/// its value as a BitsInit, throwing an exception if the field does not exist -/// or if the value is not the right type. +/// its value as a BitsInit, aborts if the field does not exist or if +/// the value is not the right type. /// BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (BitsInit *BI = dyn_cast<BitsInit>(R->getValue())) return BI; - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a BitsInit initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a BitsInit initializer!"); } /// getValueAsListInit - This method looks up the specified field and returns -/// its value as a ListInit, throwing an exception if the field does not exist -/// or if the value is not the right type. +/// its value as a ListInit, aborting if the field does not exist or if +/// the value is not the right type. /// ListInit *Record::getValueAsListInit(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (ListInit *LI = dyn_cast<ListInit>(R->getValue())) return LI; - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a list initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a list initializer!"); } /// getValueAsListOfDefs - This method looks up the specified field and returns -/// its value as a vector of records, throwing an exception if the field does -/// not exist or if the value is not the right type. +/// its value as a vector of records, aborting if the field does not exist +/// or if the value is not the right type. /// std::vector<Record*> Record::getValueAsListOfDefs(StringRef FieldName) const { @@ -1809,32 +1810,32 @@ Record::getValueAsListOfDefs(StringRef FieldName) const { if (DefInit *DI = dyn_cast<DefInit>(List->getElement(i))) { Defs.push_back(DI->getDef()); } else { - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' list is not entirely DefInit!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' list is not entirely DefInit!"); } } return Defs; } /// getValueAsInt - This method looks up the specified field and returns its -/// value as an int64_t, throwing an exception if the field does not exist or if -/// the value is not the right type. +/// value as an int64_t, aborting if the field does not exist or if the value +/// is not the right type. /// int64_t Record::getValueAsInt(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (IntInit *II = dyn_cast<IntInit>(R->getValue())) return II->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have an int initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have an int initializer!"); } /// getValueAsListOfInts - This method looks up the specified field and returns -/// its value as a vector of integers, throwing an exception if the field does -/// not exist or if the value is not the right type. +/// its value as a vector of integers, aborting if the field does not exist or +/// if the value is not the right type. /// std::vector<int64_t> Record::getValueAsListOfInts(StringRef FieldName) const { @@ -1844,16 +1845,16 @@ Record::getValueAsListOfInts(StringRef FieldName) const { if (IntInit *II = dyn_cast<IntInit>(List->getElement(i))) { Ints.push_back(II->getValue()); } else { - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a list of ints initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a list of ints initializer!"); } } return Ints; } /// getValueAsListOfStrings - This method looks up the specified field and -/// returns its value as a vector of strings, throwing an exception if the -/// field does not exist or if the value is not the right type. +/// returns its value as a vector of strings, aborting if the field does not +/// exist or if the value is not the right type. /// std::vector<std::string> Record::getValueAsListOfStrings(StringRef FieldName) const { @@ -1863,50 +1864,50 @@ Record::getValueAsListOfStrings(StringRef FieldName) const { if (StringInit *II = dyn_cast<StringInit>(List->getElement(i))) { Strings.push_back(II->getValue()); } else { - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a list of strings initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a list of strings initializer!"); } } return Strings; } /// getValueAsDef - This method looks up the specified field and returns its -/// value as a Record, throwing an exception if the field does not exist or if -/// the value is not the right type. +/// value as a Record, aborting if the field does not exist or if the value +/// is not the right type. /// Record *Record::getValueAsDef(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (DefInit *DI = dyn_cast<DefInit>(R->getValue())) return DI->getDef(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a def initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a def initializer!"); } /// getValueAsBit - This method looks up the specified field and returns its -/// value as a bit, throwing an exception if the field does not exist or if -/// the value is not the right type. +/// value as a bit, aborting if the field does not exist or if the value is +/// not the right type. /// bool Record::getValueAsBit(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (BitInit *BI = dyn_cast<BitInit>(R->getValue())) return BI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a bit initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a bit initializer!"); } bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (R->getValue() == UnsetInit::get()) { Unset = true; @@ -1915,24 +1916,24 @@ bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const { Unset = false; if (BitInit *BI = dyn_cast<BitInit>(R->getValue())) return BI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a bit initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a bit initializer!"); } /// getValueAsDag - This method looks up the specified field and returns its -/// value as an Dag, throwing an exception if the field does not exist or if -/// the value is not the right type. +/// value as an Dag, aborting if the field does not exist or if the value is +/// not the right type. /// DagInit *Record::getValueAsDag(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName.str() + "'!\n"); if (DagInit *DI = dyn_cast<DagInit>(R->getValue())) return DI; - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a dag initializer!"; + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + + FieldName.str() + "' does not have a dag initializer!"); } @@ -1975,7 +1976,7 @@ std::vector<Record*> RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { Record *Class = getClass(ClassName); if (!Class) - throw "ERROR: Couldn't find the `" + ClassName + "' class!\n"; + PrintFatalError("ERROR: Couldn't find the `" + ClassName + "' class!\n"); std::vector<Record*> Defs; for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(), 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..568a40c5c1 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 false; + + 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 false; + } 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 '" + getOperator()->getName() + "' expects more operands than were provided."); + return false; + } MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); @@ -1606,9 +1662,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); } - if (ChildNo != getNumChildren()) + if (ChildNo != getNumChildren()) { TP.error("Instruction '" + getOperator()->getName() + "' was provided too many operands!"); + return false; + } return MadeChange; } @@ -1616,9 +1674,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); // Node transforms always take one operand. - if (getNumChildren() != 1) + if (getNumChildren() != 1) { TP.error("Node transform '" + getOperator()->getName() + "' requires one operand!"); + return false; + } bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters); @@ -1692,27 +1752,30 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, // TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, - CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ - isInputPattern = isInput; + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), + isInputPattern(isInput), HasError(false) { for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) Trees.push_back(ParseTreePattern(RawPat->getElement(i), "")); } TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, - CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ - isInputPattern = isInput; + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), + isInputPattern(isInput), HasError(false) { Trees.push_back(ParseTreePattern(Pat, "")); } TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, - CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ - isInputPattern = isInput; + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), + isInputPattern(isInput), HasError(false) { Trees.push_back(Pat); } -void TreePattern::error(const std::string &Msg) const { +void TreePattern::error(const std::string &Msg) { + if (HasError) + return; dump(); - throw TGError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); + PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); + HasError = true; } void TreePattern::ComputeNamedNodes() { @@ -1901,7 +1964,7 @@ static bool SimplifyTree(TreePatternNode *&N) { /// InferAllTypes - Infer/propagate as many types throughout the expression /// patterns as possible. Return true if all types are inferred, false -/// otherwise. Throw an exception if a type contradiction is found. +/// otherwise. Flags an error if a type contradiction is found. bool TreePattern:: InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { if (NamedNodes.empty()) @@ -2152,14 +2215,8 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. - try { - ThePat->InferAllTypes(); - } catch (...) { - // If this pattern fragment is not supported by this target (no types can - // satisfy its constraints), just ignore it. If the bogus pattern is - // actually used by instructions, the type consistency error will be - // reported there. - } + ThePat->InferAllTypes(); + ThePat->resetError(); // If debugging, print out the pattern fragment result. DEBUG(ThePat->dump()); @@ -2199,8 +2256,8 @@ void CodeGenDAGPatterns::ParseDefaultOperands() { /* Resolve all types */; if (TPN->ContainsUnresolvedType()) { - throw "Value #" + utostr(i) + " of OperandWithDefaultOps '" + - DefaultOps[i]->getName() +"' doesn't have a concrete type!"; + PrintFatalError("Value #" + utostr(i) + " of OperandWithDefaultOps '" + + DefaultOps[i]->getName() +"' doesn't have a concrete type!"); } DefaultOpInfo.DefaultOps.push_back(TPN); } @@ -2746,7 +2803,7 @@ void CodeGenDAGPatterns::ParseInstructions() { Instructions.begin(), E = Instructions.end(); II != E; ++II) { DAGInstruction &TheInst = II->second; - const TreePattern *I = TheInst.getPattern(); + TreePattern *I = TheInst.getPattern(); if (I == 0) continue; // No pattern. // FIXME: Assume only the first tree is the pattern. The others are clobber @@ -2777,7 +2834,7 @@ typedef std::pair<const TreePatternNode*, unsigned> NameRecord; static void FindNames(const TreePatternNode *P, std::map<std::string, NameRecord> &Names, - const TreePattern *PatternTop) { + TreePattern *PatternTop) { if (!P->getName().empty()) { NameRecord &Rec = Names[P->getName()]; // If this is the first instance of the name, remember the node. @@ -2794,7 +2851,7 @@ static void FindNames(const TreePatternNode *P, } } -void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, +void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM) { // Do some sanity checking on the pattern we're about to match. std::string Reason; @@ -2895,7 +2952,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() { } if (Errors) - throw "pattern conflicts"; + PrintFatalError("pattern conflicts"); // Revisit instructions with undefined flags and no pattern. if (Target.guessInstructionProperties()) { @@ -2992,7 +3049,7 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() { } } if (Errors) - throw "Errors in DAG patterns"; + PrintFatalError("Errors in DAG patterns"); } /// Given a pattern result with an unresolved type, see if we can find one diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 66f77eae1a..9be763f2ff 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -105,7 +105,7 @@ namespace EEVT { /// 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 MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP); bool MergeInTypeInfo(MVT::SimpleValueType InVT, TreePattern &TP) { @@ -187,8 +187,8 @@ struct SDTypeConstraint { /// 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, an error + /// is flagged. bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const; }; @@ -232,7 +232,7 @@ public: /// ApplyTypeConstraints - Given a node in a pattern, apply the type /// constraints for this node to the operands of the node. This returns /// true if it makes a change, false otherwise. If a type contradiction is - /// found, throw an exception. + /// found, an error is flagged. bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const { bool MadeChange = false; for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) @@ -446,13 +446,12 @@ public: // Higher level manipulation routines. /// 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 ApplyTypeConstraints(TreePattern &TP, bool NotRegisters); /// UpdateNodeType - Set the node type of N to VT if VT contains - /// information. If N already contains a conflicting type, then throw an - /// exception. This returns true if any information was updated. + /// information. If N already contains a conflicting type, then flag an + /// error. This returns true if any information was updated. /// bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy, TreePattern &TP) { @@ -514,6 +513,10 @@ class TreePattern { /// isInputPattern - True if this is an input pattern, something to match. /// False if this is an output pattern, something to emit. bool isInputPattern; + + /// hasError - True if the currently processed nodes have unresolvable types + /// or other non-fatal errors + bool HasError; public: /// TreePattern constructor - Parse the specified DagInits into the @@ -565,13 +568,19 @@ public: /// InferAllTypes - Infer/propagate as many types throughout the expression /// patterns as possible. Return true if all types are inferred, false - /// otherwise. Throw an exception if a type contradiction is found. + /// otherwise. Bail out if a type contradiction is found. bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *NamedTypes=0); - /// error - Throw an exception, prefixing it with information about this - /// pattern. - void error(const std::string &Msg) const; + /// error - If this is the first error in the current resolution step, + /// print it and set the error flag. Otherwise, continue silently. + void error(const std::string &Msg); + bool hasError() const { + return HasError; + } + void resetError() { + HasError = false; + } void print(raw_ostream &OS) const; void dump() const; @@ -602,7 +611,7 @@ public: : Pattern(TP), Results(results), Operands(operands), ImpResults(impresults), ResultPattern(0) {} - const TreePattern *getPattern() const { return Pattern; } + TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return Results.size(); } unsigned getNumOperands() const { return Operands.size(); } unsigned getNumImpResults() const { return ImpResults.size(); } @@ -794,7 +803,7 @@ private: void GenerateVariants(); void VerifyInstructionFlags(); - void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM); + void AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, std::map<std::string, TreePatternNode*> &InstInputs, diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index fd38672bfc..0a8684d3da 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -34,18 +34,18 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) { if (Init->getDef()->getName() != "outs") - throw R->getName() + ": invalid def name for output list: use 'outs'"; + PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'"); } else - throw R->getName() + ": invalid output list: use 'outs'"; + PrintFatalError(R->getName() + ": invalid output list: use 'outs'"); NumDefs = OutDI->getNumArgs(); DagInit *InDI = R->getValueAsDag("InOperandList"); if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) { if (Init->getDef()->getName() != "ins") - throw R->getName() + ": invalid def name for input list: use 'ins'"; + PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'"); } else - throw R->getName() + ": invalid input list: use 'ins'"; + PrintFatalError(R->getName() + ": invalid input list: use 'ins'"); unsigned MIOperandNo = 0; std::set<std::string> OperandNames; @@ -62,7 +62,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { DefInit *Arg = dyn_cast<DefInit>(ArgInit); if (!Arg) - throw "Illegal operand for the '" + R->getName() + "' instruction!"; + PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!"); Record *Rec = Arg->getDef(); std::string PrintMethod = "printOperand"; @@ -82,8 +82,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { // Verify that MIOpInfo has an 'ops' root value. if (!isa<DefInit>(MIOpInfo->getOperator()) || cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops") - throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + - "'\n"; + PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() + + "'\n"); // If we have MIOpInfo, then we have #operands equal to number of entries // in MIOperandInfo. @@ -101,16 +101,16 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { OperandType = "OPERAND_REGISTER"; } else if (!Rec->isSubClassOf("PointerLikeRegClass") && !Rec->isSubClassOf("unknown_class")) - throw "Unknown operand class '" + Rec->getName() + - "' in '" + R->getName() + "' instruction!"; + PrintFatalError("Unknown operand class '" + Rec->getName() + + "' in '" + R->getName() + "' instruction!"); // Check that the operand has a name and that it's unique. if (ArgName.empty()) - throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has no name!"; + PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) + + " has no name!"); if (!OperandNames.insert(ArgName).second) - throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has the same name as a previous operand!"; + PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) + + " has the same name as a previous operand!"); OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, OperandType, MIOperandNo, NumOps, @@ -128,13 +128,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the -/// specified name, throw an exception. +/// specified name, abort. /// unsigned CGIOperandList::getOperandNamed(StringRef Name) const { unsigned OpIdx; if (hasOperandNamed(Name, OpIdx)) return OpIdx; - throw "'" + TheDef->getName() + "' does not have an operand named '$" + - Name.str() + "'!"; + PrintFatalError("'" + TheDef->getName() + "' does not have an operand named '$" + + Name.str() + "'!"); } /// hasOperandNamed - Query whether the instruction has an operand of the @@ -153,7 +153,7 @@ bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { std::pair<unsigned,unsigned> CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (Op.empty() || Op[0] != '$') - throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; + PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'"); std::string OpName = Op.substr(1); std::string SubOpName; @@ -163,7 +163,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (DotIdx != std::string::npos) { SubOpName = OpName.substr(DotIdx+1); if (SubOpName.empty()) - throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"; + PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"); OpName = OpName.substr(0, DotIdx); } @@ -173,8 +173,8 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // If one was needed, throw. if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && SubOpName.empty()) - throw TheDef->getName() + ": Illegal to refer to" - " whole operand part of complex operand '" + Op + "'"; + PrintFatalError(TheDef->getName() + ": Illegal to refer to" + " whole operand part of complex operand '" + Op + "'"); // Otherwise, return the operand. return std::make_pair(OpIdx, 0U); @@ -183,7 +183,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // Find the suboperand number involved. DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; if (MIOpInfo == 0) - throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; + PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); // Find the operand with the right name. for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) @@ -191,7 +191,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { return std::make_pair(OpIdx, i); // Otherwise, didn't find it! - throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; + PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); } static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { @@ -203,13 +203,13 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { std::string Name = CStr.substr(wpos+1); wpos = Name.find_first_not_of(" \t"); if (wpos == std::string::npos) - throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; + PrintFatalError("Illegal format for @earlyclobber constraint: '" + CStr + "'"); Name = Name.substr(wpos); std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false); // Build the string for the operand if (!Ops[Op.first].Constraints[Op.second].isNone()) - throw "Operand '" + Name + "' cannot have multiple constraints!"; + PrintFatalError("Operand '" + Name + "' cannot have multiple constraints!"); Ops[Op.first].Constraints[Op.second] = CGIOperandList::ConstraintInfo::getEarlyClobber(); return; @@ -224,14 +224,14 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { // TIED_TO: $src1 = $dst wpos = Name.find_first_of(" \t"); if (wpos == std::string::npos) - throw "Illegal format for tied-to constraint: '" + CStr + "'"; + PrintFatalError("Illegal format for tied-to constraint: '" + CStr + "'"); std::string DestOpName = Name.substr(0, wpos); std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false); Name = CStr.substr(pos+1); wpos = Name.find_first_not_of(" \t"); if (wpos == std::string::npos) - throw "Illegal format for tied-to constraint: '" + CStr + "'"; + PrintFatalError("Illegal format for tied-to constraint: '" + CStr + "'"); std::string SrcOpName = Name.substr(wpos); std::pair<unsigned,unsigned> SrcOp = Ops.ParseOperandName(SrcOpName, false); @@ -243,7 +243,8 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp); if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) - throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; + PrintFatalError("Operand '" + DestOpName + + "' cannot have multiple constraints!"); Ops[DestOp.first].Constraints[DestOp.second] = CGIOperandList::ConstraintInfo::getTied(FlatOpNo); } @@ -328,7 +329,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) ImplicitUses = R->getValueAsListOfDefs("Uses"); if (neverHasSideEffects + hasSideEffects > 1) - throw R->getName() + ": multiple conflicting side-effect flags set!"; + PrintFatalError(R->getName() + ": multiple conflicting side-effect flags set!"); // Parse Constraints. ParseConstraints(R->getValueAsString("Constraints"), Operands); @@ -422,7 +423,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, // If the operand is a record, it must have a name, and the record type // must match up with the instruction's argument type. if (Result->getArgName(AliasOpNo).empty()) - throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) + " must have a name!"); ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); return true; @@ -457,13 +458,13 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, if (!T.getRegisterClass(InstOpRec) .contains(T.getRegBank().getReg(ADI->getDef()))) - throw TGError(Loc, "fixed register " + ADI->getDef()->getName() + - " is not a member of the " + InstOpRec->getName() + - " register class!"); + PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() + + " is not a member of the " + InstOpRec->getName() + + " register class!"); if (!Result->getArgName(AliasOpNo).empty()) - throw TGError(Loc, "result fixed register argument must " - "not have a name!"); + PrintFatalError(Loc, "result fixed register argument must " + "not have a name!"); ResOp = ResultOperand(ADI->getDef()); return true; @@ -491,8 +492,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return false; // Integer arguments can't have names. if (!Result->getArgName(AliasOpNo).empty()) - throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + - " must not have a name!"); + PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) + + " must not have a name!"); ResOp = ResultOperand(II->getValue()); return true; } @@ -520,7 +521,8 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { // Verify that the root of the result is an instruction. DefInit *DI = dyn_cast<DefInit>(Result->getOperator()); if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) - throw TGError(R->getLoc(), "result of inst alias should be an instruction"); + PrintFatalError(R->getLoc(), + "result of inst alias should be an instruction"); ResultInst = &T.getInstruction(DI->getDef()); @@ -536,9 +538,9 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { // same type. Record *&Entry = NameClass[Result->getArgName(i)]; if (Entry && Entry != ADI->getDef()) - throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) + - " is both " + Entry->getName() + " and " + - ADI->getDef()->getName() + "!"); + PrintFatalError(R->getLoc(), "result value $" + Result->getArgName(i) + + " is both " + Entry->getName() + " and " + + ADI->getDef()->getName() + "!"); Entry = ADI->getDef(); } @@ -554,7 +556,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { continue; if (AliasOpNo >= Result->getNumArgs()) - throw TGError(R->getLoc(), "not enough arguments for instruction!"); + PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); Record *InstOpRec = ResultInst->Operands[i].Rec; unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; @@ -595,7 +597,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { if (AliasOpNo >= Result->getNumArgs()) - throw TGError(R->getLoc(), "not enough arguments for instruction!"); + PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef(); if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, R->getLoc(), T, ResOp)) { @@ -603,18 +605,18 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); ++AliasOpNo; } else { - throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + " does not match instruction operand class " + (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); } } continue; } - throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + - " does not match instruction operand class " + - InstOpRec->getName()); + PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + InstOpRec->getName()); } if (AliasOpNo != Result->getNumArgs()) - throw TGError(R->getLoc(), "too many operands for instruction!"); + PrintFatalError(R->getLoc(), "too many operands for instruction!"); } diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index f601a8318f..55d44399df 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -152,7 +152,7 @@ namespace llvm { /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the - /// specified name, throw an exception. + /// specified name, abort. unsigned getOperandNamed(StringRef Name) const; /// hasOperandNamed - Query whether the instruction has an operand of the @@ -162,9 +162,8 @@ namespace llvm { /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", /// where $foo is a whole operand and $foo.bar refers to a suboperand. - /// This throws an exception if the name is invalid. If AllowWholeOp is - /// true, references to operands with suboperands are allowed, otherwise - /// not. + /// This aborts if the name is invalid. If AllowWholeOp is true, references + /// to operands with suboperands are allowed, otherwise not. std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op, bool AllowWholeOp = true); diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp index 4bfd1ba798..1653d67da9 100644 --- a/utils/TableGen/CodeGenMapTable.cpp +++ b/utils/TableGen/CodeGenMapTable.cpp @@ -78,6 +78,7 @@ #include "CodeGenTarget.h" #include "llvm/Support/Format.h" +#include "llvm/TableGen/Error.h" using namespace llvm; typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy; @@ -128,20 +129,19 @@ public: // Each instruction map must specify at least one column for it to be valid. if (ColValList->getSize() == 0) - throw "InstrMapping record `" + MapRec->getName() + "' has empty " + - "`ValueCols' field!"; + PrintFatalError(MapRec->getLoc(), "InstrMapping record `" + + MapRec->getName() + "' has empty " + "`ValueCols' field!"); for (unsigned i = 0, e = ColValList->getSize(); i < e; i++) { ListInit *ColI = dyn_cast<ListInit>(ColValList->getElement(i)); // Make sure that all the sub-lists in 'ValueCols' have same number of // elements as the fields in 'ColFields'. - if (ColI->getSize() == ColFields->getSize()) - ValueCols.push_back(ColI); - else { - throw "Record `" + MapRec->getName() + "', field `" + "ValueCols" + - "' entries don't match with the entries in 'ColFields'!"; - } + if (ColI->getSize() != ColFields->getSize()) + PrintFatalError(MapRec->getLoc(), "Record `" + MapRec->getName() + + "', field `ValueCols' entries don't match with " + + " the entries in 'ColFields'!"); + ValueCols.push_back(ColI); } } @@ -344,10 +344,9 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, if (MatchFound) { if (MatchInstr) // Already had a match // Error if multiple matches are found for a column. - throw "Multiple matches found for `" + KeyInstr->getName() + - "', for the relation `" + InstrMapDesc.getName(); - else - MatchInstr = CurInstr; + PrintFatalError("Multiple matches found for `" + KeyInstr->getName() + + "', for the relation `" + InstrMapDesc.getName()); + MatchInstr = CurInstr; } } return MatchInstr; @@ -516,10 +515,9 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { for (unsigned j = 0; j < ListSize; j++) { ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j)); - if (ListJ->getSize() != ColFields->getSize()) { - throw "Record `" + CurMap->getName() + "', field `" + "ValueCols" + - "' entries don't match with the entries in 'ColFields' !"; - } + if (ListJ->getSize() != ColFields->getSize()) + PrintFatalError("Record `" + CurMap->getName() + "', field " + "`ValueCols' entries don't match with the entries in 'ColFields' !"); ValueCols.push_back(ListJ); } diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 10064fdd16..580e319f24 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -54,19 +54,20 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf"); if (!Comps.empty()) { if (Comps.size() != 2) - throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries"); + PrintFatalError(TheDef->getLoc(), + "ComposedOf must have exactly two entries"); CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); CodeGenSubRegIndex *X = A->addComposite(B, this); if (X) - throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); + PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); } std::vector<Record*> Parts = TheDef->getValueAsListOfDefs("CoveringSubRegIndices"); if (!Parts.empty()) { if (Parts.size() < 2) - throw TGError(TheDef->getLoc(), + PrintFatalError(TheDef->getLoc(), "CoveredBySubRegs must have two or more entries"); SmallVector<CodeGenSubRegIndex*, 8> IdxParts; for (unsigned i = 0, e = Parts.size(); i != e; ++i) @@ -112,8 +113,8 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) { std::vector<Record*> SRs = TheDef->getValueAsListOfDefs("SubRegs"); if (SRIs.size() != SRs.size()) - throw TGError(TheDef->getLoc(), - "SubRegs and SubRegIndices must have the same size"); + PrintFatalError(TheDef->getLoc(), + "SubRegs and SubRegIndices must have the same size"); for (unsigned i = 0, e = SRIs.size(); i != e; ++i) { ExplicitSubRegIndices.push_back(RegBank.getSubRegIdx(SRIs[i])); @@ -224,8 +225,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { CodeGenRegister *SR = ExplicitSubRegs[i]; CodeGenSubRegIndex *Idx = ExplicitSubRegIndices[i]; if (!SubRegs.insert(std::make_pair(Idx, SR)).second) - throw TGError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() + - " appears twice in Register " + getName()); + PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() + + " appears twice in Register " + getName()); // Map explicit sub-registers first, so the names take precedence. // The inherited sub-registers are mapped below. SubReg2Idx.insert(std::make_pair(SR, Idx)); @@ -308,8 +309,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { ArrayRef<SMLoc> Loc; if (TheDef) Loc = TheDef->getLoc(); - throw TGError(Loc, "Register " + getName() + - " has itself as a sub-register"); + PrintFatalError(Loc, "Register " + getName() + + " has itself as a sub-register"); } // Ensure that every sub-register has a unique name. DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*>::iterator Ins = @@ -320,7 +321,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { ArrayRef<SMLoc> Loc; if (TheDef) Loc = TheDef->getLoc(); - throw TGError(Loc, "Sub-register can't have two names: " + + PrintFatalError(Loc, "Sub-register can't have two names: " + SI->second->getName() + " available as " + SI->first->getName() + " and " + Ins->second->getName()); } @@ -467,8 +468,8 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) { CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second); if (!SubIdx) - throw TGError(TheDef->getLoc(), "No SubRegIndex for " + - SI->second->getName() + " in " + getName()); + PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " + + SI->second->getName() + " in " + getName()); NewIdx->addComposite(SI->first, SubIdx); } } @@ -592,9 +593,10 @@ struct TupleExpander : SetTheory::Expander { unsigned Dim = Indices.size(); ListInit *SubRegs = Def->getValueAsListInit("SubRegs"); if (Dim != SubRegs->getSize()) - throw TGError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch"); + PrintFatalError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch"); if (Dim < 2) - throw TGError(Def->getLoc(), "Tuples must have at least 2 sub-registers"); + PrintFatalError(Def->getLoc(), + "Tuples must have at least 2 sub-registers"); // Evaluate the sub-register lists to be zipped. unsigned Length = ~0u; @@ -706,8 +708,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { Record *Type = TypeList[i]; if (!Type->isSubClassOf("ValueType")) - throw "RegTypes list member '" + Type->getName() + - "' does not derive from the ValueType class!"; + PrintFatalError("RegTypes list member '" + Type->getName() + + "' does not derive from the ValueType class!"); VTs.push_back(getValueType(Type)); } assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); @@ -735,7 +737,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) CodeGenRegister *Reg = RegBank.getReg(Order.back()); Order.pop_back(); if (!contains(Reg)) - throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() + + PrintFatalError(R->getLoc(), " AltOrder register " + Reg->getName() + " is not a class member"); } } @@ -1021,7 +1023,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { // Read in register class definitions. std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); if (RCs.empty()) - throw std::string("No 'RegisterClass' subclasses defined!"); + PrintFatalError(std::string("No 'RegisterClass' subclasses defined!")); // Allocate user-defined register classes. RegClasses.reserve(RCs.size()); @@ -1098,7 +1100,7 @@ CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { if (CodeGenRegisterClass *RC = Def2RC[Def]) return RC; - throw TGError(Def->getLoc(), "Not a known RegisterClass!"); + PrintFatalError(Def->getLoc(), "Not a known RegisterClass!"); } CodeGenSubRegIndex* diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 1cca3e3f85..a8c9392be7 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -63,7 +63,7 @@ struct InstRegexOp : public SetTheory::Operator { AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) { StringInit *SI = dyn_cast<StringInit>(*AI); if (!SI) - throw TGError(Loc, "instregex requires pattern string: " + PrintFatalError(Loc, "instregex requires pattern string: " + Expr->getAsString()); std::string pat = SI->getValue(); // Implement a python-style prefix match. @@ -268,13 +268,13 @@ void CodeGenSchedModels::collectSchedRW() { Record *AliasDef = (*AI)->getValueAsDef("AliasRW"); if (MatchDef->isSubClassOf("SchedWrite")) { if (!AliasDef->isSubClassOf("SchedWrite")) - throw TGError((*AI)->getLoc(), "SchedWrite Alias must be SchedWrite"); + PrintFatalError((*AI)->getLoc(), "SchedWrite Alias must be SchedWrite"); scanSchedRW(AliasDef, SWDefs, RWSet); } else { assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite"); if (!AliasDef->isSubClassOf("SchedRead")) - throw TGError((*AI)->getLoc(), "SchedRead Alias must be SchedRead"); + PrintFatalError((*AI)->getLoc(), "SchedRead Alias must be SchedRead"); scanSchedRW(AliasDef, SRDefs, RWSet); } } @@ -305,7 +305,7 @@ void CodeGenSchedModels::collectSchedRW() { Record *MatchDef = (*AI)->getValueAsDef("MatchRW"); CodeGenSchedRW &RW = getSchedRW(MatchDef); if (RW.IsAlias) - throw TGError((*AI)->getLoc(), "Cannot Alias an Alias"); + PrintFatalError((*AI)->getLoc(), "Cannot Alias an Alias"); RW.Aliases.push_back(*AI); } DEBUG( @@ -437,9 +437,9 @@ void CodeGenSchedModels::expandRWSeqForProc( continue; } if (AliasDef) - throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases " - "defined for processor " + ProcModel.ModelName + - " Ensure only one SchedAlias exists per RW."); + PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases " + "defined for processor " + ProcModel.ModelName + + " Ensure only one SchedAlias exists per RW."); AliasDef = AliasRW.TheDef; } if (AliasDef) { @@ -706,7 +706,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { // Sort Instrs into sets. const RecVec *InstDefs = Sets.expand(InstRWDef); if (InstDefs->empty()) - throw TGError(InstRWDef->getLoc(), "No matching instruction opcodes"); + PrintFatalError(InstRWDef->getLoc(), "No matching instruction opcodes"); for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) { unsigned SCIdx = 0; @@ -766,7 +766,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(), RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) { if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) { - throw TGError(InstRWDef->getLoc(), "Overlapping InstRW def " + + PrintFatalError(InstRWDef->getLoc(), "Overlapping InstRW def " + (*II)->getName() + " also matches " + (*RI)->getValue("Instrs")->getValue()->getAsString()); } @@ -825,11 +825,11 @@ void CodeGenSchedModels::collectProcItinRW() { std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord()); for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) { if (!(*II)->getValueInit("SchedModel")->isComplete()) - throw TGError((*II)->getLoc(), "SchedModel is undefined"); + PrintFatalError((*II)->getLoc(), "SchedModel is undefined"); Record *ModelDef = (*II)->getValueAsDef("SchedModel"); ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef); if (I == ProcModelMap.end()) { - throw TGError((*II)->getLoc(), "Undefined SchedMachineModel " + PrintFatalError((*II)->getLoc(), "Undefined SchedMachineModel " + ModelDef->getName()); } ProcModels[I->second].ItinRWDefs.push_back(*II); @@ -867,7 +867,7 @@ void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef, if (!std::count(Matched.begin(), Matched.end(), ItinClassDef)) continue; if (HasMatch) - throw TGError((*II)->getLoc(), "Duplicate itinerary class " + PrintFatalError((*II)->getLoc(), "Duplicate itinerary class " + ItinClassDef->getName() + " in ItinResources for " + PM.ModelName); HasMatch = true; @@ -1095,9 +1095,10 @@ void PredTransitions::getIntersectingVariants( if (Cnt > 1) { const CodeGenProcModel &PM = *(SchedModels.procModelBegin() + Variant.ProcIdx); - throw TGError(Variant.VarOrSeqDef->getLoc(), - "Multiple variants defined for processor " + PM.ModelName + - " Ensure only one SchedAlias exists per RW."); + PrintFatalError(Variant.VarOrSeqDef->getLoc(), + "Multiple variants defined for processor " + + PM.ModelName + + " Ensure only one SchedAlias exists per RW."); } } if (Variant.VarOrSeqDef->isSubClassOf("SchedVar")) { @@ -1215,8 +1216,9 @@ void PredTransitions::substituteVariantOperand( std::vector<TransVariant> IntersectingVariants; getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants); if (IntersectingVariants.empty()) - throw TGError(SchedRW.TheDef->getLoc(), "No variant of this type has a " - "matching predicate on any processor "); + PrintFatalError(SchedRW.TheDef->getLoc(), + "No variant of this type has " + "a matching predicate on any processor"); // Now expand each variant on top of its copy of the transition. for (std::vector<TransVariant>::const_iterator IVI = IntersectingVariants.begin(), @@ -1440,9 +1442,9 @@ void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) { if (!std::count(Matched.begin(), Matched.end(), ItinClassDef)) continue; if (HasMatch) - throw TGError((*II)->getLoc(), "Duplicate itinerary class " - + ItinClassDef->getName() - + " in ItinResources for " + PM.ModelName); + PrintFatalError((*II)->getLoc(), "Duplicate itinerary class " + + ItinClassDef->getName() + + " in ItinResources for " + PM.ModelName); HasMatch = true; IdxVec Writes, Reads; findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); @@ -1519,17 +1521,17 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind, if ((*RI)->getValueAsDef("Kind") == ProcResKind && (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) { if (ProcUnitDef) { - throw TGError((*RI)->getLoc(), - "Multiple ProcessorResourceUnits associated with " - + ProcResKind->getName()); + PrintFatalError((*RI)->getLoc(), + "Multiple ProcessorResourceUnits associated with " + + ProcResKind->getName()); } ProcUnitDef = *RI; } } if (!ProcUnitDef) { - throw TGError(ProcResKind->getLoc(), - "No ProcessorResources associated with " - + ProcResKind->getName()); + PrintFatalError(ProcResKind->getLoc(), + "No ProcessorResources associated with " + + ProcResKind->getName()); } return ProcUnitDef; } @@ -1586,8 +1588,8 @@ unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const { RecIter PRPos = std::find(ProcResourceDefs.begin(), ProcResourceDefs.end(), PRDef); if (PRPos == ProcResourceDefs.end()) - throw TGError(PRDef->getLoc(), "ProcResource def is not included in " - "the ProcResources list for " + ModelName); + PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in " + "the ProcResources list for " + ModelName); // Idx=0 is reserved for invalid. return 1 + PRPos - ProcResourceDefs.begin(); } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 3a3b0aa380..c9992eb392 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -10,13 +10,14 @@ // This class wraps target description classes used by the various code // generation TableGen backends. This makes it easier to access the data and // provides a single place that needs to check it for validity. All of these -// classes throw exceptions on error conditions. +// classes abort on error conditions. // //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" #include "CodeGenSchedule.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" @@ -124,9 +125,9 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records) : Records(records), RegBank(0), SchedModels(0) { std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) - throw std::string("ERROR: No 'Target' subclasses defined!"); + PrintFatalError("ERROR: No 'Target' subclasses defined!"); if (Targets.size() != 1) - throw std::string("ERROR: Multiple subclasses of Target defined!"); + PrintFatalError("ERROR: Multiple subclasses of Target defined!"); TargetRec = Targets[0]; } @@ -160,7 +161,7 @@ Record *CodeGenTarget::getInstructionSet() const { Record *CodeGenTarget::getAsmParser() const { std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); if (AsmParserNum >= LI.size()) - throw "Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"; + PrintFatalError("Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"); return LI[AsmParserNum]; } @@ -171,7 +172,7 @@ Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); if (i >= LI.size()) - throw "Target does not have an AsmParserVariant #" + utostr(i) + "!"; + PrintFatalError("Target does not have an AsmParserVariant #" + utostr(i) + "!"); return LI[i]; } @@ -189,7 +190,7 @@ unsigned CodeGenTarget::getAsmParserVariantCount() const { Record *CodeGenTarget::getAsmWriter() const { std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); if (AsmWriterNum >= LI.size()) - throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"; + PrintFatalError("Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"); return LI[AsmWriterNum]; } @@ -256,7 +257,7 @@ CodeGenSchedModels &CodeGenTarget::getSchedModels() const { void CodeGenTarget::ReadInstructions() const { std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); if (Insts.size() <= 2) - throw std::string("No 'Instruction' subclasses defined!"); + PrintFatalError("No 'Instruction' subclasses defined!"); // Parse the instructions defined in the .td file. for (unsigned i = 0, e = Insts.size(); i != e; ++i) @@ -272,7 +273,7 @@ GetInstByName(const char *Name, DenseMap<const Record*, CodeGenInstruction*>::const_iterator I = Insts.find(Rec); if (Rec == 0 || I == Insts.end()) - throw std::string("Could not find '") + Name + "' instruction!"; + PrintFatalError(std::string("Could not find '") + Name + "' instruction!"); return I->second; } @@ -419,7 +420,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") - throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; + PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!"); EnumName = std::string(DefName.begin()+4, DefName.end()); @@ -439,7 +440,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // Verify it starts with "llvm.". if (Name.size() <= 5 || std::string(Name.begin(), Name.begin() + 5) != "llvm.") - throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; + PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"); } // If TargetPrefix is specified, make sure that Name starts with @@ -448,8 +449,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { 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." + - TargetPrefix + ".'!"; + PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." + + TargetPrefix + ".'!"); } // Parse the list of return types. @@ -481,7 +482,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // Reject invalid types. if (VT == MVT::isVoid) - throw "Intrinsic '" + DefName + " has void in result type list!"; + PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); @@ -515,7 +516,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // Reject invalid types. if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) - throw "Intrinsic '" + DefName + " has void in result type list!"; + PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 672b1406a5..ddeecee36f 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -9,8 +9,8 @@ // // This file defines wrappers for the Target class and related global // functionality. This makes it easier to access the data and provides a single -// place that needs to check it for validity. All of these classes throw -// exceptions on error conditions. +// place that needs to check it for validity. All of these classes abort +// on error conditions. // //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 70c6fe6000..573f55875e 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -10,6 +10,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "CodeGenRegisters.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" @@ -172,15 +173,10 @@ void MatcherGen::InferPossibleTypes() { // diagnostics, which we know are impossible at this point. TreePattern &TP = *CGP.pf_begin()->second; - try { - bool MadeChange = true; - while (MadeChange) - MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP, - true/*Ignore reg constraints*/); - } catch (...) { - errs() << "Type constraint application shouldn't fail!"; - abort(); - } + bool MadeChange = true; + while (MadeChange) + MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP, + true/*Ignore reg constraints*/); } @@ -876,7 +872,7 @@ void MatcherGen::EmitResultOperand(const TreePatternNode *N, if (OpRec->isSubClassOf("SDNodeXForm")) return EmitResultSDNodeXFormAsOperand(N, ResultOps); errs() << "Unknown result node to emit code for: " << *N << '\n'; - throw std::string("Unknown node in result pattern!"); + PrintFatalError("Unknown node in result pattern!"); } void MatcherGen::EmitResultCode() { diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 826465a516..2d11d2480d 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -117,11 +117,9 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i) RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i); - // FIXME: As long as we are using exceptions, might as well drop this to the - // actual conflict site. if (Tables.hasConflicts()) - throw TGError(Target.getTargetRecord()->getLoc(), - "Primary decode conflict"); + PrintFatalError(Target.getTargetRecord()->getLoc(), + "Primary decode conflict"); Tables.emit(OS); return; diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index b687df7f67..ea2545050b 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <string> @@ -777,7 +778,7 @@ static void ARMPopulateOperands( errs() << "Operand type: " << rec.getName() << '\n'; errs() << "Operand name: " << operandInfo.Name << '\n'; errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; - throw("Unhandled type in EDEmitter"); + PrintFatalError("Unhandled type in EDEmitter"); } } } diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 03e918fa4b..8b1e7f9256 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -549,7 +549,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { }; if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) - throw TGError(Pattern.getSrcRecord()->getLoc(), + PrintFatalError(Pattern.getSrcRecord()->getLoc(), "Duplicate record in FastISel table!"); SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index c53776b9ff..5cabcadabd 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -15,6 +15,7 @@ #define DEBUG_TYPE "decoder-emitter" #include "CodeGenTarget.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" @@ -741,7 +742,7 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, switch (*I) { default: - throw "invalid decode table opcode"; + PrintFatalError("invalid decode table opcode"); case MCD::OPC_ExtractField: { ++I; unsigned Start = *I++; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 8e670e3cbc..48d41d7b96 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -19,6 +19,7 @@ #include "TableGenBackends.h" #include "SequenceToOffsetTable.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <algorithm> @@ -343,13 +344,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); - if (!TSF) throw "no TSFlags?"; + if (!TSF) + PrintFatalError("no TSFlags?"); uint64_t Value = 0; for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(i))) Value |= uint64_t(Bit->getValue()) << i; else - throw "Invalid TSFlags bit in " + Inst.TheDef->getName(); + PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName()); } OS << ", 0x"; OS.write_hex(Value); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index e830a66a33..e1910784a6 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -15,6 +15,7 @@ #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/TableGenBackend.h" @@ -249,7 +250,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, if (EVT(VT).isInteger()) { unsigned BitWidth = EVT(VT).getSizeInBits(); switch (BitWidth) { - default: throw "unhandled integer type width in intrinsic!"; + default: PrintFatalError("unhandled integer type width in intrinsic!"); case 1: return Sig.push_back(IIT_I1); case 8: return Sig.push_back(IIT_I8); case 16: return Sig.push_back(IIT_I16); @@ -259,7 +260,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, } switch (VT) { - default: throw "unhandled MVT in intrinsic!"; + default: PrintFatalError("unhandled MVT in intrinsic!"); case MVT::f32: return Sig.push_back(IIT_F32); case MVT::f64: return Sig.push_back(IIT_F64); case MVT::Metadata: return Sig.push_back(IIT_METADATA); @@ -328,7 +329,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, if (EVT(VT).isVector()) { EVT VVT = VT; switch (VVT.getVectorNumElements()) { - default: throw "unhandled vector type width in intrinsic!"; + default: PrintFatalError("unhandled vector type width in intrinsic!"); case 2: Sig.push_back(IIT_V2); break; case 4: Sig.push_back(IIT_V4); break; case 8: Sig.push_back(IIT_V8); break; @@ -692,8 +693,8 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName, Ints[i].EnumName)).second) - throw "Intrinsic '" + Ints[i].TheDef->getName() + - "': duplicate GCC builtin name!"; + PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() + + "': duplicate GCC builtin name!"); } } diff --git a/utils/TableGen/Makefile b/utils/TableGen/Makefile index bdf0ba01fb..9bfd94b757 100644 --- a/utils/TableGen/Makefile +++ b/utils/TableGen/Makefile @@ -10,7 +10,6 @@ LEVEL = ../.. TOOLNAME = llvm-tblgen USEDLIBS = LLVMTableGen.a LLVMSupport.a -REQUIRES_EH := 1 # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index b0241c7c27..64aaee756b 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -90,7 +90,7 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) - throw TGError(Rec->getLoc(), + PrintFatalError(Rec->getLoc(), "Pseudo operand type '" + DI->getDef()->getName() + "' does not match expansion operand type '" + Insn.Operands[BaseIdx + i].Rec->getName() + "'"); @@ -129,22 +129,22 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); if (!OpDef) - throw TGError(Rec->getLoc(), Rec->getName() + + PrintFatalError(Rec->getLoc(), Rec->getName() + " has unexpected operator type!"); Record *Operator = OpDef->getDef(); if (!Operator->isSubClassOf("Instruction")) - throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + - "' is not an instruction!"); + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' is not an instruction!"); CodeGenInstruction Insn(Operator); if (Insn.isCodeGenOnly || Insn.isPseudo) - throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + - "' cannot be another pseudo instruction!"); + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' cannot be another pseudo instruction!"); if (Insn.Operands.size() != Dag->getNumArgs()) - throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + - "' operand count mismatch"); + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' operand count mismatch"); unsigned NumMIOperands = 0; for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) @@ -179,9 +179,9 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { StringMap<unsigned>::iterator SourceOp = SourceOperands.find(Dag->getArgName(i)); if (SourceOp == SourceOperands.end()) - throw TGError(Rec->getLoc(), - "Pseudo output operand '" + Dag->getArgName(i) + - "' has no matching source operand."); + PrintFatalError(Rec->getLoc(), + "Pseudo output operand '" + Dag->getArgName(i) + + "' has no matching source operand."); // Map the source operand to the destination operand index for each // MachineInstr operand. for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index ad1dab4ac0..273cac0c01 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -1092,7 +1092,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, else if (RegisterClasses.size() < UINT16_MAX) OS << " static const uint16_t Table["; else - throw "Too many register classes."; + PrintFatalError("Too many register classes."); OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { const CodeGenRegisterClass &RC = *RegisterClasses[rci]; diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp index 33a8f0e337..0dd9853843 100644 --- a/utils/TableGen/SetTheory.cpp +++ b/utils/TableGen/SetTheory.cpp @@ -36,7 +36,7 @@ struct AddOp : public SetTheory::Operator { struct SubOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { if (Expr->arg_size() < 2) - throw TGError(Loc, "Set difference needs at least two arguments: " + + PrintFatalError(Loc, "Set difference needs at least two arguments: " + Expr->getAsString()); RecSet Add, Sub; ST.evaluate(*Expr->arg_begin(), Add, Loc); @@ -51,7 +51,7 @@ struct SubOp : public SetTheory::Operator { struct AndOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { if (Expr->arg_size() != 2) - throw TGError(Loc, "Set intersection requires two arguments: " + + PrintFatalError(Loc, "Set intersection requires two arguments: " + Expr->getAsString()); RecSet S1, S2; ST.evaluate(Expr->arg_begin()[0], S1, Loc); @@ -70,13 +70,13 @@ struct SetIntBinOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { if (Expr->arg_size() != 2) - throw TGError(Loc, "Operator requires (Op Set, Int) arguments: " + + PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " + Expr->getAsString()); RecSet Set; ST.evaluate(Expr->arg_begin()[0], Set, Loc); IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]); if (!II) - throw TGError(Loc, "Second argument must be an integer: " + + PrintFatalError(Loc, "Second argument must be an integer: " + Expr->getAsString()); apply2(ST, Expr, Set, II->getValue(), Elts, Loc); } @@ -88,7 +88,7 @@ struct ShlOp : public SetIntBinOp { RecSet &Set, int64_t N, RecSet &Elts, ArrayRef<SMLoc> Loc) { if (N < 0) - throw TGError(Loc, "Positive shift required: " + + PrintFatalError(Loc, "Positive shift required: " + Expr->getAsString()); if (unsigned(N) < Set.size()) Elts.insert(Set.begin() + N, Set.end()); @@ -101,7 +101,7 @@ struct TruncOp : public SetIntBinOp { RecSet &Set, int64_t N, RecSet &Elts, ArrayRef<SMLoc> Loc) { if (N < 0) - throw TGError(Loc, "Positive length required: " + + PrintFatalError(Loc, "Positive length required: " + Expr->getAsString()); if (unsigned(N) > Set.size()) N = Set.size(); @@ -138,7 +138,7 @@ struct DecimateOp : public SetIntBinOp { RecSet &Set, int64_t N, RecSet &Elts, ArrayRef<SMLoc> Loc) { if (N <= 0) - throw TGError(Loc, "Positive stride required: " + + PrintFatalError(Loc, "Positive stride required: " + Expr->getAsString()); for (unsigned I = 0; I < Set.size(); I += N) Elts.insert(Set[I]); @@ -168,35 +168,36 @@ struct SequenceOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { int Step = 1; if (Expr->arg_size() > 4) - throw TGError(Loc, "Bad args to (sequence \"Format\", From, To): " + + PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " + Expr->getAsString()); else if (Expr->arg_size() == 4) { if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) { Step = II->getValue(); } else - throw TGError(Loc, "Stride must be an integer: " + Expr->getAsString()); + PrintFatalError(Loc, "Stride must be an integer: " + + Expr->getAsString()); } std::string Format; if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0])) Format = SI->getValue(); else - throw TGError(Loc, "Format must be a string: " + Expr->getAsString()); + PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString()); int64_t From, To; if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1])) From = II->getValue(); else - throw TGError(Loc, "From must be an integer: " + Expr->getAsString()); + PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); if (From < 0 || From >= (1 << 30)) - throw TGError(Loc, "From out of range"); + PrintFatalError(Loc, "From out of range"); if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[2])) To = II->getValue(); else - throw TGError(Loc, "From must be an integer: " + Expr->getAsString()); + PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); if (To < 0 || To >= (1 << 30)) - throw TGError(Loc, "To out of range"); + PrintFatalError(Loc, "To out of range"); RecordKeeper &Records = cast<DefInit>(Expr->getOperator())->getDef()->getRecords(); @@ -212,7 +213,7 @@ struct SequenceOp : public SetTheory::Operator { OS << format(Format.c_str(), unsigned(From)); Record *Rec = Records.getDef(OS.str()); if (!Rec) - throw TGError(Loc, "No def named '" + Name + "': " + + PrintFatalError(Loc, "No def named '" + Name + "': " + Expr->getAsString()); // Try to reevaluate Rec in case it is a set. if (const RecVec *Result = ST.expand(Rec)) @@ -282,13 +283,13 @@ void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { // Anything else must be a DAG. DagInit *DagExpr = dyn_cast<DagInit>(Expr); if (!DagExpr) - throw TGError(Loc, "Invalid set element: " + Expr->getAsString()); + PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString()); DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator()); if (!OpInit) - throw TGError(Loc, "Bad set expression: " + Expr->getAsString()); + PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString()); Operator *Op = Operators.lookup(OpInit->getDef()->getName()); if (!Op) - throw TGError(Loc, "Unknown set operator: " + Expr->getAsString()); + PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString()); Op->apply(*this, DagExpr, Elts, Loc); } diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index ac833a54a7..806bda1cbc 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -675,7 +675,7 @@ Record *SubtargetEmitter::FindWriteResources( continue; } if (AliasDef) - throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases " + PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases " "defined for processor " + ProcModel.ModelName + " Ensure only one SchedAlias exists per RW."); AliasDef = AliasRW.TheDef; @@ -692,7 +692,7 @@ Record *SubtargetEmitter::FindWriteResources( if (AliasDef == (*WRI)->getValueAsDef("WriteType") || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) { if (ResDef) { - throw TGError((*WRI)->getLoc(), "Resources are defined for both " + PrintFatalError((*WRI)->getLoc(), "Resources are defined for both " "SchedWrite and its alias on processor " + ProcModel.ModelName); } @@ -702,7 +702,7 @@ Record *SubtargetEmitter::FindWriteResources( // TODO: If ProcModel has a base model (previous generation processor), // then call FindWriteResources recursively with that model here. if (!ResDef) { - throw TGError(ProcModel.ModelDef->getLoc(), + PrintFatalError(ProcModel.ModelDef->getLoc(), std::string("Processor does not define resources for ") + SchedWrite.TheDef->getName()); } @@ -729,7 +729,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, continue; } if (AliasDef) - throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases " + PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases " "defined for processor " + ProcModel.ModelName + " Ensure only one SchedAlias exists per RW."); AliasDef = AliasRW.TheDef; @@ -746,7 +746,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, if (AliasDef == (*RAI)->getValueAsDef("ReadType") || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) { if (ResDef) { - throw TGError((*RAI)->getLoc(), "Resources are defined for both " + PrintFatalError((*RAI)->getLoc(), "Resources are defined for both " "SchedRead and its alias on processor " + ProcModel.ModelName); } @@ -756,7 +756,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, // TODO: If ProcModel has a base model (previous generation processor), // then call FindReadAdvance recursively with that model here. if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") { - throw TGError(ProcModel.ModelDef->getLoc(), + PrintFatalError(ProcModel.ModelDef->getLoc(), std::string("Processor does not define resources for ") + SchedRead.TheDef->getName()); } @@ -1098,7 +1098,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { if (PI->hasInstrSchedModel()) EmitProcessorResources(*PI, OS); else if(!PI->ProcResourceDefs.empty()) - throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines " + PrintFatalError(PI->ModelDef->getLoc(), "SchedMachineModel defines " "ProcResources without defining WriteRes SchedWriteRes"); // Begin processor itinerary properties |