Remove exception handling usage from tblgen.

Most places can use PrintFatalError as the unwinding mechanism was not
used for anything other than printing the error. The single exception
was CodeGenDAGPatterns.cpp, where intermediate errors during type
resolution were ignored to simplify incremental platform development.
This use is replaced by an error flag in TreePattern and bailout earlier
in various places if it is set. 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166712 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Joerg Sonnenberger 2012-10-25 20:33:17 +00:00
parent e5a7a68dfa
commit 61131ab15f
32 changed files with 488 additions and 452 deletions

View File

@ -19,26 +19,13 @@
namespace llvm { 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(ArrayRef<SMLoc> WarningLoc, const Twine &Msg);
void PrintWarning(const char *Loc, const Twine &Msg); void PrintWarning(const char *Loc, const Twine &Msg);
void PrintWarning(const Twine &Msg); void PrintWarning(const Twine &Msg);
void PrintWarning(const TGError &Warning);
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg); void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
void PrintError(const char *Loc, const Twine &Msg); void PrintError(const char *Loc, const Twine &Msg);
void PrintError(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(const std::string &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc,

View File

@ -1,5 +1,3 @@
set(LLVM_REQUIRES_EH 1)
add_llvm_library(LLVMTableGen add_llvm_library(LLVMTableGen
Error.cpp Error.cpp
Main.cpp Main.cpp

View File

@ -45,10 +45,6 @@ void PrintWarning(const Twine &Msg) {
errs() << "warning:" << Msg << "\n"; errs() << "warning:" << Msg << "\n";
} }
void PrintWarning(const TGError &Warning) {
PrintWarning(Warning.getLoc(), Warning.getMessage());
}
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) { void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg); PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
} }
@ -61,10 +57,6 @@ void PrintError(const Twine &Msg) {
errs() << "error:" << Msg << "\n"; errs() << "error:" << Msg << "\n";
} }
void PrintError(const TGError &Error) {
PrintError(Error.getLoc(), Error.getMessage());
}
void PrintFatalError(const std::string &Msg) { void PrintFatalError(const std::string &Msg) {
PrintError(Twine(Msg)); PrintError(Twine(Msg));
std::exit(1); std::exit(1);

View File

@ -80,7 +80,6 @@ namespace llvm {
int TableGenMain(char *argv0, TableGenMainFn *MainFn) { int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
RecordKeeper Records; RecordKeeper Records;
try {
// Parse the input file. // Parse the input file.
OwningPtr<MemoryBuffer> File; OwningPtr<MemoryBuffer> File;
if (error_code ec = if (error_code ec =
@ -110,9 +109,10 @@ int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
<< ":" << Error << "\n"; << ":" << Error << "\n";
return 1; return 1;
} }
if (!DependFilename.empty()) if (!DependFilename.empty()) {
if (int Ret = createDependencyFile(Parser, argv0)) if (int Ret = createDependencyFile(Parser, argv0))
return Ret; return Ret;
}
if (MainFn(Out.os(), Records)) if (MainFn(Out.os(), Records))
return 1; return 1;
@ -121,16 +121,6 @@ int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
Out.keep(); Out.keep();
return 0; 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";
}
return 1; return 1;
} }

View File

@ -11,6 +11,4 @@ LEVEL = ../..
LIBRARYNAME = LLVMTableGen LIBRARYNAME = LLVMTableGen
BUILD_ARCHIVE = 1 BUILD_ARCHIVE = 1
REQUIRES_EH = 1
include $(LEVEL)/Makefile.common include $(LEVEL)/Makefile.common

View File

@ -616,7 +616,8 @@ ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) const {
Record *ListInit::getElementAsRecord(unsigned i) const { Record *ListInit::getElementAsRecord(unsigned i) const {
assert(i < Values.size() && "List element index out of range!"); assert(i < Values.size() && "List element index out of range!");
DefInit *DI = dyn_cast<DefInit>(Values[i]); 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(); return DI->getDef();
} }
@ -725,7 +726,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
if (CurRec) { if (CurRec) {
if (const RecordVal *RV = CurRec->getValue(Name)) { if (const RecordVal *RV = CurRec->getValue(Name)) {
if (RV->getType() != getType()) if (RV->getType() != getType())
throw "type mismatch in cast"; PrintFatalError("type mismatch in cast");
return VarInit::get(Name, RV->getType()); 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??"); assert(RV && "Template arg doesn't exist??");
if (RV->getType() != getType()) if (RV->getType() != getType())
throw "type mismatch in cast"; PrintFatalError("type mismatch in cast");
return VarInit::get(TemplateArgName, RV->getType()); 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??"); assert(RV && "Template arg doesn't exist??");
if (RV->getType() != getType()) if (RV->getType() != getType())
throw "type mismatch in cast"; PrintFatalError("type mismatch in cast");
return VarInit::get(MCName, RV->getType()); 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)) if (Record *D = (CurRec->getRecords()).getDef(Name))
return DefInit::get(D); return DefInit::get(D);
throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n"); PrintFatalError(CurRec->getLoc(),
"Undefined reference:'" + Name + "'\n");
} }
} }
break; break;
@ -860,7 +862,7 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
DefInit *LOp = dyn_cast<DefInit>(LHSs->getOperator()); DefInit *LOp = dyn_cast<DefInit>(LHSs->getOperator());
DefInit *ROp = dyn_cast<DefInit>(RHSs->getOperator()); DefInit *ROp = dyn_cast<DefInit>(RHSs->getOperator());
if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef()) 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<Init*> Args;
std::vector<std::string> ArgNames; std::vector<std::string> ArgNames;
for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) { 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); OpInit *RHSo = dyn_cast<OpInit>(RHS);
if (!RHSo) { 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); TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
if (!LHSt) { if (!LHSt)
throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n"); PrintFatalError(CurRec->getLoc(), "!foreach requires typed variable\n");
}
if ((MHSd && isa<DagRecTy>(Type)) || (MHSl && isa<ListRecTy>(Type))) { if ((MHSd && isa<DagRecTy>(Type)) || (MHSl && isa<ListRecTy>(Type))) {
if (MHSd) { if (MHSd) {
@ -1632,7 +1633,7 @@ void Record::checkName() {
assert(TypedName && "Record name is not typed!"); assert(TypedName && "Record name is not typed!");
RecTy *Type = TypedName->getType(); RecTy *Type = TypedName->getType();
if (!isa<StringRecTy>(Type)) if (!isa<StringRecTy>(Type))
throw TGError(getLoc(), "Record name is not a string!"); PrintFatalError(getLoc(), "Record name is not a string!");
} }
DefInit *Record::getDefInit() { DefInit *Record::getDefInit() {
@ -1683,7 +1684,7 @@ void Record::resolveReferencesTo(const RecordVal *RV) {
continue; continue;
if (Init *V = Values[i].getValue()) if (Init *V = Values[i].getValue())
if (Values[i].setValue(V->resolveReferences(*this, RV))) 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() + Values[i].getNameInitAsString()
+ "' after resolving references" + "' after resolving references"
+ (RV ? " against '" + RV->getNameInitAsString() + (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, /// 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 { Init *Record::getValueInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
return R->getValue(); return R->getValue();
} }
/// getValueAsString - This method looks up the specified field and returns its /// 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. /// the value is not a string.
/// ///
std::string Record::getValueAsString(StringRef FieldName) const { std::string Record::getValueAsString(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (StringInit *SI = dyn_cast<StringInit>(R->getValue())) if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
return SI->getValue(); return SI->getValue();
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a string initializer!"; FieldName.str() + "' does not have a string initializer!");
} }
/// getValueAsBitsInit - This method looks up the specified field and returns /// getValueAsBitsInit - This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist /// its value as a BitsInit, aborts if the field does not exist or if
/// or if the value is not the right type. /// the value is not the right type.
/// ///
BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (BitsInit *BI = dyn_cast<BitsInit>(R->getValue())) if (BitsInit *BI = dyn_cast<BitsInit>(R->getValue()))
return BI; return BI;
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a BitsInit initializer!"; FieldName.str() + "' does not have a BitsInit initializer!");
} }
/// getValueAsListInit - This method looks up the specified field and returns /// getValueAsListInit - This method looks up the specified field and returns
/// its value as a ListInit, throwing an exception if the field does not exist /// its value as a ListInit, aborting if the field does not exist or if
/// or if the value is not the right type. /// the value is not the right type.
/// ///
ListInit *Record::getValueAsListInit(StringRef FieldName) const { ListInit *Record::getValueAsListInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (ListInit *LI = dyn_cast<ListInit>(R->getValue())) if (ListInit *LI = dyn_cast<ListInit>(R->getValue()))
return LI; return LI;
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a list initializer!"; FieldName.str() + "' does not have a list initializer!");
} }
/// getValueAsListOfDefs - This method looks up the specified field and returns /// getValueAsListOfDefs - This method looks up the specified field and returns
/// its value as a vector of records, throwing an exception if the field does /// its value as a vector of records, aborting if the field does not exist
/// not exist or if the value is not the right type. /// or if the value is not the right type.
/// ///
std::vector<Record*> std::vector<Record*>
Record::getValueAsListOfDefs(StringRef FieldName) const { Record::getValueAsListOfDefs(StringRef FieldName) const {
@ -1809,32 +1810,32 @@ Record::getValueAsListOfDefs(StringRef FieldName) const {
if (DefInit *DI = dyn_cast<DefInit>(List->getElement(i))) { if (DefInit *DI = dyn_cast<DefInit>(List->getElement(i))) {
Defs.push_back(DI->getDef()); Defs.push_back(DI->getDef());
} else { } else {
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' list is not entirely DefInit!"; FieldName.str() + "' list is not entirely DefInit!");
} }
} }
return Defs; return Defs;
} }
/// getValueAsInt - This method looks up the specified field and returns its /// 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 /// value as an int64_t, aborting if the field does not exist or if the value
/// the value is not the right type. /// is not the right type.
/// ///
int64_t Record::getValueAsInt(StringRef FieldName) const { int64_t Record::getValueAsInt(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (IntInit *II = dyn_cast<IntInit>(R->getValue())) if (IntInit *II = dyn_cast<IntInit>(R->getValue()))
return II->getValue(); return II->getValue();
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have an int initializer!"; FieldName.str() + "' does not have an int initializer!");
} }
/// getValueAsListOfInts - This method looks up the specified field and returns /// getValueAsListOfInts - This method looks up the specified field and returns
/// its value as a vector of integers, throwing an exception if the field does /// its value as a vector of integers, aborting if the field does not exist or
/// not exist or if the value is not the right type. /// if the value is not the right type.
/// ///
std::vector<int64_t> std::vector<int64_t>
Record::getValueAsListOfInts(StringRef FieldName) const { Record::getValueAsListOfInts(StringRef FieldName) const {
@ -1844,16 +1845,16 @@ Record::getValueAsListOfInts(StringRef FieldName) const {
if (IntInit *II = dyn_cast<IntInit>(List->getElement(i))) { if (IntInit *II = dyn_cast<IntInit>(List->getElement(i))) {
Ints.push_back(II->getValue()); Ints.push_back(II->getValue());
} else { } else {
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a list of ints initializer!"; FieldName.str() + "' does not have a list of ints initializer!");
} }
} }
return Ints; return Ints;
} }
/// getValueAsListOfStrings - This method looks up the specified field and /// getValueAsListOfStrings - This method looks up the specified field and
/// returns its value as a vector of strings, throwing an exception if the /// returns its value as a vector of strings, aborting if the field does not
/// field does not exist or if the value is not the right type. /// exist or if the value is not the right type.
/// ///
std::vector<std::string> std::vector<std::string>
Record::getValueAsListOfStrings(StringRef FieldName) const { Record::getValueAsListOfStrings(StringRef FieldName) const {
@ -1863,50 +1864,50 @@ Record::getValueAsListOfStrings(StringRef FieldName) const {
if (StringInit *II = dyn_cast<StringInit>(List->getElement(i))) { if (StringInit *II = dyn_cast<StringInit>(List->getElement(i))) {
Strings.push_back(II->getValue()); Strings.push_back(II->getValue());
} else { } else {
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a list of strings initializer!"; FieldName.str() + "' does not have a list of strings initializer!");
} }
} }
return Strings; return Strings;
} }
/// getValueAsDef - This method looks up the specified field and returns its /// 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 /// value as a Record, aborting if the field does not exist or if the value
/// the value is not the right type. /// is not the right type.
/// ///
Record *Record::getValueAsDef(StringRef FieldName) const { Record *Record::getValueAsDef(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (DefInit *DI = dyn_cast<DefInit>(R->getValue())) if (DefInit *DI = dyn_cast<DefInit>(R->getValue()))
return DI->getDef(); return DI->getDef();
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a def initializer!"; FieldName.str() + "' does not have a def initializer!");
} }
/// getValueAsBit - This method looks up the specified field and returns its /// 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 /// value as a bit, aborting if the field does not exist or if the value is
/// the value is not the right type. /// not the right type.
/// ///
bool Record::getValueAsBit(StringRef FieldName) const { bool Record::getValueAsBit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (BitInit *BI = dyn_cast<BitInit>(R->getValue())) if (BitInit *BI = dyn_cast<BitInit>(R->getValue()))
return BI->getValue(); return BI->getValue();
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a bit initializer!"; FieldName.str() + "' does not have a bit initializer!");
} }
bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const { bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (R->getValue() == UnsetInit::get()) { if (R->getValue() == UnsetInit::get()) {
Unset = true; Unset = true;
@ -1915,24 +1916,24 @@ bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const {
Unset = false; Unset = false;
if (BitInit *BI = dyn_cast<BitInit>(R->getValue())) if (BitInit *BI = dyn_cast<BitInit>(R->getValue()))
return BI->getValue(); return BI->getValue();
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a bit initializer!"; FieldName.str() + "' does not have a bit initializer!");
} }
/// getValueAsDag - This method looks up the specified field and returns its /// 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 /// value as an Dag, aborting if the field does not exist or if the value is
/// the value is not the right type. /// not the right type.
/// ///
DagInit *Record::getValueAsDag(StringRef FieldName) const { DagInit *Record::getValueAsDag(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName); const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" + PrintFatalError(getLoc(), "Record `" + getName() +
FieldName.str() + "'!\n"; "' does not have a field named `" + FieldName.str() + "'!\n");
if (DagInit *DI = dyn_cast<DagInit>(R->getValue())) if (DagInit *DI = dyn_cast<DagInit>(R->getValue()))
return DI; return DI;
throw "Record `" + getName() + "', field `" + FieldName.str() + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
"' does not have a dag initializer!"; FieldName.str() + "' does not have a dag initializer!");
} }
@ -1975,7 +1976,7 @@ std::vector<Record*>
RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
Record *Class = getClass(ClassName); Record *Class = getClass(ClassName);
if (!Class) if (!Class)
throw "ERROR: Couldn't find the `" + ClassName + "' class!\n"; PrintFatalError("ERROR: Couldn't find the `" + ClassName + "' class!\n");
std::vector<Record*> Defs; std::vector<Record*> Defs;
for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(), for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),

View File

@ -689,18 +689,18 @@ parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) {
// Split via the '='. // Split via the '='.
std::pair<StringRef, StringRef> Ops = S.split('='); std::pair<StringRef, StringRef> Ops = S.split('=');
if (Ops.second == "") 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. // Trim whitespace and the leading '$' on the operand names.
size_t start = Ops.first.find_first_of('$'); size_t start = Ops.first.find_first_of('$');
if (start == std::string::npos) 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); Ops.first = Ops.first.slice(start + 1, std::string::npos);
size_t end = Ops.first.find_last_of(" \t"); size_t end = Ops.first.find_last_of(" \t");
Ops.first = Ops.first.slice(0, end); Ops.first = Ops.first.slice(0, end);
// Now the second operand. // Now the second operand.
start = Ops.second.find_first_of('$'); start = Ops.second.find_first_of('$');
if (start == std::string::npos) 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); Ops.second = Ops.second.slice(start + 1, std::string::npos);
end = Ops.second.find_last_of(" \t"); end = Ops.second.find_last_of(" \t");
Ops.first = Ops.first.slice(0, end); Ops.first = Ops.first.slice(0, end);
@ -716,11 +716,11 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
int SrcAsmOperand = findAsmOperandNamed(Ops.first); int SrcAsmOperand = findAsmOperandNamed(Ops.first);
int DstAsmOperand = findAsmOperandNamed(Ops.second); int DstAsmOperand = findAsmOperandNamed(Ops.second);
if (SrcAsmOperand == -1) if (SrcAsmOperand == -1)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"unknown source two-operand alias operand '" + "unknown source two-operand alias operand '" +
Ops.first.str() + "'."); Ops.first.str() + "'.");
if (DstAsmOperand == -1) if (DstAsmOperand == -1)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"unknown destination two-operand alias operand '" + "unknown destination two-operand alias operand '" +
Ops.second.str() + "'."); 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 // The first token of the instruction is the mnemonic, which must be a
// simple string, not a $foo variable or a singleton register. // simple string, not a $foo variable or a singleton register.
if (AsmOperands.empty()) if (AsmOperands.empty())
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"Instruction '" + TheDef->getName() + "' has no tokens"); "Instruction '" + TheDef->getName() + "' has no tokens");
Mnemonic = AsmOperands[0].Token; Mnemonic = AsmOperands[0].Token;
if (Mnemonic.empty()) if (Mnemonic.empty())
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"Missing instruction mnemonic"); "Missing instruction mnemonic");
// FIXME : Check and raise an error if it is a register. // FIXME : Check and raise an error if it is a register.
if (Mnemonic[0] == '$') if (Mnemonic[0] == '$')
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); "Invalid instruction mnemonic '" + Mnemonic.str() + "'!");
// Remove the first operand, it is tracked in the mnemonic field. // 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 { bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
// Reject matchables with no .s string. // Reject matchables with no .s string.
if (AsmString.empty()) 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 // Reject any matchables with a newline in them, they should be marked
// isCodeGenOnly if they are pseudo instructions. // isCodeGenOnly if they are pseudo instructions.
if (AsmString.find('\n') != std::string::npos) if (AsmString.find('\n') != std::string::npos)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"multiline instruction is not valid for the asmparser, " "multiline instruction is not valid for the asmparser, "
"mark it isCodeGenOnly"); "mark it isCodeGenOnly");
@ -883,7 +883,7 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
// has one line. // has one line.
if (!CommentDelimiter.empty() && if (!CommentDelimiter.empty() &&
StringRef(AsmString).find(CommentDelimiter) != StringRef::npos) StringRef(AsmString).find(CommentDelimiter) != StringRef::npos)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"asmstring for instruction has comment character in it, " "asmstring for instruction has comment character in it, "
"mark it isCodeGenOnly"); "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) { for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
StringRef Tok = AsmOperands[i].Token; StringRef Tok = AsmOperands[i].Token;
if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) if (Tok[0] == '$' && Tok.find(':') != StringRef::npos)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"matchable with operand modifier '" + Tok.str() + "matchable with operand modifier '" + Tok.str() +
"' not supported by asm matcher. Mark isCodeGenOnly!"); "' 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. // We reject aliases and ignore instructions for now.
if (Tok[0] == '$' && !OperandNames.insert(Tok).second) { if (Tok[0] == '$' && !OperandNames.insert(Tok).second) {
if (!Hack) if (!Hack)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"ERROR: matchable with tied operand '" + Tok.str() + "ERROR: matchable with tied operand '" + Tok.str() +
"' can never be matched!"); "' can never be matched!");
// FIXME: Should reject these. The ARM backend hits this with $lane in a // 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. // use it, else just fall back to the underlying register class.
const RecordVal *R = Rec->getValue("ParserMatchClass"); const RecordVal *R = Rec->getValue("ParserMatchClass");
if (R == 0 || R->getValue() == 0) if (R == 0 || R->getValue() == 0)
throw "Record `" + Rec->getName() + PrintFatalError("Record `" + Rec->getName() +
"' does not have a ParserMatchClass!\n"; "' does not have a ParserMatchClass!\n");
if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) { if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) {
Record *MatchClass = DI->getDef(); Record *MatchClass = DI->getDef();
@ -1016,28 +1016,28 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
// No custom match class. Just use the register class. // No custom match class. Just use the register class.
Record *ClassRec = Rec->getValueAsDef("RegClass"); Record *ClassRec = Rec->getValueAsDef("RegClass");
if (!ClassRec) if (!ClassRec)
throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() + PrintFatalError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() +
"' has no associated register class!\n"); "' has no associated register class!\n");
if (ClassInfo *CI = RegisterClassClasses[ClassRec]) if (ClassInfo *CI = RegisterClassClasses[ClassRec])
return CI; 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 (Rec->isSubClassOf("RegisterClass")) {
if (ClassInfo *CI = RegisterClassClasses[Rec]) if (ClassInfo *CI = RegisterClassClasses[Rec])
return CI; 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")) if (!Rec->isSubClassOf("Operand"))
throw TGError(Rec->getLoc(), "Operand `" + Rec->getName() + PrintFatalError(Rec->getLoc(), "Operand `" + Rec->getName() +
"' does not derive from class Operand!\n"); "' does not derive from class Operand!\n");
Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
if (ClassInfo *CI = AsmOperandClasses[MatchClass]) if (ClassInfo *CI = AsmOperandClasses[MatchClass])
return CI; return CI;
throw TGError(Rec->getLoc(), "operand has no match class!"); PrintFatalError(Rec->getLoc(), "operand has no match class!");
} }
void AsmMatcherInfo:: void AsmMatcherInfo::
@ -1287,7 +1287,7 @@ void AsmMatcherInfo::buildInfo() {
continue; continue;
if (Pred->getName().empty()) if (Pred->getName().empty())
throw TGError(Pred->getLoc(), "Predicate has no name!"); PrintFatalError(Pred->getLoc(), "Predicate has no name!");
unsigned FeatureNo = SubtargetFeatures.size(); unsigned FeatureNo = SubtargetFeatures.size();
SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
@ -1468,7 +1468,7 @@ void AsmMatcherInfo::buildInfo() {
ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));
ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));
if (FromClass == ToClass) if (FromClass == ToClass)
throw TGError(Rec->getLoc(), PrintFatalError(Rec->getLoc(),
"error: Destination value identical to source value."); "error: Destination value identical to source value.");
FromClass->SuperClasses.push_back(ToClass); FromClass->SuperClasses.push_back(ToClass);
} }
@ -1490,7 +1490,7 @@ buildInstructionOperandReference(MatchableInfo *II,
// Map this token to an operand. // Map this token to an operand.
unsigned Idx; unsigned Idx;
if (!Operands.hasOperandNamed(OperandName, 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() + "'"); OperandName.str() + "'");
// If the instruction operand has multiple suboperands, but the parser // If the instruction operand has multiple suboperands, but the parser
@ -1561,7 +1561,7 @@ void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II,
return; return;
} }
throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" +
OperandName.str() + "'"); OperandName.str() + "'");
} }
@ -1583,7 +1583,7 @@ void MatchableInfo::buildInstructionResultOperands() {
// Find out what operand from the asmparser this MCInst operand comes from. // Find out what operand from the asmparser this MCInst operand comes from.
int SrcOperand = findAsmOperandNamed(OpInfo.Name); int SrcOperand = findAsmOperandNamed(OpInfo.Name);
if (OpInfo.Name.empty() || SrcOperand == -1) if (OpInfo.Name.empty() || SrcOperand == -1)
throw TGError(TheDef->getLoc(), "Instruction '" + PrintFatalError(TheDef->getLoc(), "Instruction '" +
TheDef->getName() + "' has operand '" + OpInfo.Name + TheDef->getName() + "' has operand '" + OpInfo.Name +
"' that doesn't appear in asm string!"); "' that doesn't appear in asm string!");
@ -1635,7 +1635,7 @@ void MatchableInfo::buildAliasResultOperands() {
StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
int SrcOperand = findAsmOperand(Name, SubIdx); int SrcOperand = findAsmOperand(Name, SubIdx);
if (SrcOperand == -1) if (SrcOperand == -1)
throw TGError(TheDef->getLoc(), "Instruction '" + PrintFatalError(TheDef->getLoc(), "Instruction '" +
TheDef->getName() + "' has operand '" + OpName + TheDef->getName() + "' has operand '" + OpName +
"' that doesn't appear in asm string!"); "' that doesn't appear in asm string!");
unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1); unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
@ -2270,7 +2270,7 @@ static std::string GetAliasRequiredFeatures(Record *R,
SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
if (F == 0) if (F == 0)
throw TGError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
"' is not marked as an AssemblerPredicate!"); "' is not marked as an AssemblerPredicate!");
if (NumFeatures) 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. // We can't have two aliases from the same mnemonic with no predicate.
PrintError(ToVec[AliasWithNoPredicate]->getLoc(), PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
"two MnemonicAliases with the same 'from' mnemonic!"); "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; AliasWithNoPredicate = i;
continue; continue;
} }
if (R->getValueAsString("ToMnemonic") == I->first) 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()) if (!MatchCode.empty())
MatchCode += "else "; MatchCode += "else ";

View File

@ -566,7 +566,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
std::vector<std::string> AltNames = std::vector<std::string> AltNames =
Reg.TheDef->getValueAsListOfStrings("AltNames"); Reg.TheDef->getValueAsListOfStrings("AltNames");
if (AltNames.size() <= Idx) if (AltNames.size() <= Idx)
throw TGError(Reg.TheDef->getLoc(), PrintFatalError(Reg.TheDef->getLoc(),
(Twine("Register definition missing alt name for '") + (Twine("Register definition missing alt name for '") +
AltName + "'.").str()); AltName + "'.").str());
AsmName = AltNames[Idx]; AsmName = AltNames[Idx];

View File

@ -14,6 +14,7 @@
#include "AsmWriterInst.h" #include "AsmWriterInst.h"
#include "CodeGenTarget.h" #include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
using namespace llvm; using namespace llvm;
@ -123,8 +124,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
!= std::string::npos) { != std::string::npos) {
AddLiteralString(std::string(1, AsmString[DollarPos+1])); AddLiteralString(std::string(1, AsmString[DollarPos+1]));
} else { } else {
throw "Non-supported escaped character found in instruction '" + PrintFatalError("Non-supported escaped character found in instruction '" +
CGI.TheDef->getName() + "'!"; CGI.TheDef->getName() + "'!");
} }
LastEmitted = DollarPos+2; LastEmitted = DollarPos+2;
continue; continue;
@ -162,15 +163,15 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
// brace. // brace.
if (hasCurlyBraces) { if (hasCurlyBraces) {
if (VarEnd >= AsmString.size()) if (VarEnd >= AsmString.size())
throw "Reached end of string before terminating curly brace in '" PrintFatalError("Reached end of string before terminating curly brace in '"
+ CGI.TheDef->getName() + "'"; + CGI.TheDef->getName() + "'");
// Look for a modifier string. // Look for a modifier string.
if (AsmString[VarEnd] == ':') { if (AsmString[VarEnd] == ':') {
++VarEnd; ++VarEnd;
if (VarEnd >= AsmString.size()) if (VarEnd >= AsmString.size())
throw "Reached end of string before terminating curly brace in '" PrintFatalError("Reached end of string before terminating curly brace in '"
+ CGI.TheDef->getName() + "'"; + CGI.TheDef->getName() + "'");
unsigned ModifierStart = VarEnd; unsigned ModifierStart = VarEnd;
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
@ -178,17 +179,17 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
Modifier = std::string(AsmString.begin()+ModifierStart, Modifier = std::string(AsmString.begin()+ModifierStart,
AsmString.begin()+VarEnd); AsmString.begin()+VarEnd);
if (Modifier.empty()) if (Modifier.empty())
throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"; PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'");
} }
if (AsmString[VarEnd] != '}') if (AsmString[VarEnd] != '}')
throw "Variable name beginning with '{' did not end with '}' in '" PrintFatalError("Variable name beginning with '{' did not end with '}' in '"
+ CGI.TheDef->getName() + "'"; + CGI.TheDef->getName() + "'");
++VarEnd; ++VarEnd;
} }
if (VarName.empty() && Modifier.empty()) if (VarName.empty() && Modifier.empty())
throw "Stray '$' in '" + CGI.TheDef->getName() + PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() +
"' asm string, maybe you want $$?"; "' asm string, maybe you want $$?");
if (VarName.empty()) { if (VarName.empty()) {
// Just a modifier, pass this into PrintSpecial. // Just a modifier, pass this into PrintSpecial.

View File

@ -1,4 +1,3 @@
set(LLVM_REQUIRES_EH 1)
set(LLVM_LINK_COMPONENTS Support) set(LLVM_LINK_COMPONENTS Support)
add_tablegen(llvm-tblgen LLVM add_tablegen(llvm-tblgen LLVM

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "CodeGenTarget.h" #include "CodeGenTarget.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h" #include "llvm/TableGen/TableGenBackend.h"
#include <cassert> #include <cassert>
@ -93,7 +94,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << Action->getValueAsString("Predicate"); O << Action->getValueAsString("Predicate");
} else { } else {
Action->dump(); Action->dump();
throw "Unknown CCPredicateAction!"; PrintFatalError("Unknown CCPredicateAction!");
} }
O << ") {\n"; O << ") {\n";
@ -131,7 +132,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
if (ShadowRegList->getSize() >0 && if (ShadowRegList->getSize() >0 &&
ShadowRegList->getSize() != RegList->getSize()) ShadowRegList->getSize() != RegList->getSize())
throw "Invalid length of list of shadowed registers"; PrintFatalError("Invalid length of list of shadowed registers");
if (RegList->getSize() == 1) { if (RegList->getSize() == 1) {
O << IndentStr << "if (unsigned Reg = State.AllocateReg("; O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
@ -221,7 +222,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << IndentStr << "return false;\n"; O << IndentStr << IndentStr << "return false;\n";
} else { } else {
Action->dump(); Action->dump();
throw "Unknown CCAction!"; PrintFatalError("Unknown CCAction!");
} }
} }
} }

View File

@ -79,14 +79,19 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
const std::vector<MVT::SimpleValueType> &LegalTypes = const std::vector<MVT::SimpleValueType> &LegalTypes =
TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); TP.getDAGPatterns().getTargetInfo().getLegalValueTypes();
if (TP.hasError())
return false;
for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i)
if (Pred == 0 || Pred(LegalTypes[i])) if (Pred == 0 || Pred(LegalTypes[i]))
TypeVec.push_back(LegalTypes[i]); TypeVec.push_back(LegalTypes[i]);
// If we have nothing that matches the predicate, bail out. // If we have nothing that matches the predicate, bail out.
if (TypeVec.empty()) if (TypeVec.empty()) {
TP.error("Type inference contradiction found, no " + TP.error("Type inference contradiction found, no " +
std::string(PredicateName) + " types found"); std::string(PredicateName) + " types found");
return false;
}
// No need to sort with one element. // No need to sort with one element.
if (TypeVec.size() == 1) return true; 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 /// MergeInTypeInfo - This merges in type information from the specified
/// argument. If 'this' changes, it returns true. If the two types are /// 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){ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
if (InVT.isCompletelyUnknown() || *this == InVT) if (InVT.isCompletelyUnknown() || *this == InVT || TP.hasError())
return false; return false;
if (isCompletelyUnknown()) { if (isCompletelyUnknown()) {
@ -224,11 +229,13 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
// FIXME: Really want an SMLoc here! // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, merging '" + TP.error("Type inference contradiction found, merging '" +
InVT.getName() + "' into '" + InputSet.getName() + "'"); InVT.getName() + "' into '" + InputSet.getName() + "'");
return true; // unreachable return false;
} }
/// EnforceInteger - Remove all non-integer types from this set. /// EnforceInteger - Remove all non-integer types from this set.
bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
if (TP.hasError())
return false;
// If we know nothing, then get the full set. // If we know nothing, then get the full set.
if (TypeVec.empty()) if (TypeVec.empty())
return FillWithPossibleTypes(TP, isInteger, "integer"); return FillWithPossibleTypes(TP, isInteger, "integer");
@ -242,14 +249,18 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
if (!isInteger(TypeVec[i])) if (!isInteger(TypeVec[i]))
TypeVec.erase(TypeVec.begin()+i--); TypeVec.erase(TypeVec.begin()+i--);
if (TypeVec.empty()) if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be integer"); InputSet.getName() + "' needs to be integer");
return false;
}
return true; return true;
} }
/// EnforceFloatingPoint - Remove all integer types from this set. /// EnforceFloatingPoint - Remove all integer types from this set.
bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
if (TP.hasError())
return false;
// If we know nothing, then get the full set. // If we know nothing, then get the full set.
if (TypeVec.empty()) if (TypeVec.empty())
return FillWithPossibleTypes(TP, isFloatingPoint, "floating point"); return FillWithPossibleTypes(TP, isFloatingPoint, "floating point");
@ -264,14 +275,19 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
if (!isFloatingPoint(TypeVec[i])) if (!isFloatingPoint(TypeVec[i]))
TypeVec.erase(TypeVec.begin()+i--); TypeVec.erase(TypeVec.begin()+i--);
if (TypeVec.empty()) if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be floating point"); InputSet.getName() + "' needs to be floating point");
return false;
}
return true; return true;
} }
/// EnforceScalar - Remove all vector types from this. /// EnforceScalar - Remove all vector types from this.
bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
if (TP.hasError())
return false;
// If we know nothing, then get the full set. // If we know nothing, then get the full set.
if (TypeVec.empty()) if (TypeVec.empty())
return FillWithPossibleTypes(TP, isScalar, "scalar"); return FillWithPossibleTypes(TP, isScalar, "scalar");
@ -286,14 +302,19 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
if (!isScalar(TypeVec[i])) if (!isScalar(TypeVec[i]))
TypeVec.erase(TypeVec.begin()+i--); TypeVec.erase(TypeVec.begin()+i--);
if (TypeVec.empty()) if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be scalar"); InputSet.getName() + "' needs to be scalar");
return false;
}
return true; return true;
} }
/// EnforceVector - Remove all vector types from this. /// EnforceVector - Remove all vector types from this.
bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
if (TP.hasError())
return false;
// If we know nothing, then get the full set. // If we know nothing, then get the full set.
if (TypeVec.empty()) if (TypeVec.empty())
return FillWithPossibleTypes(TP, isVector, "vector"); return FillWithPossibleTypes(TP, isVector, "vector");
@ -308,9 +329,11 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
MadeChange = true; MadeChange = true;
} }
if (TypeVec.empty()) if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be a vector"); InputSet.getName() + "' needs to be a vector");
return false;
}
return MadeChange; return MadeChange;
} }
@ -319,6 +342,9 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
/// this an other based on this information. /// this an other based on this information.
bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { 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. // Both operands must be integer or FP, but we don't care which.
bool MadeChange = false; bool MadeChange = false;
@ -365,19 +391,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
if (hasVectorTypes() && Other.hasVectorTypes()) { if (hasVectorTypes() && Other.hasVectorTypes()) {
if (Type.getSizeInBits() >= OtherType.getSizeInBits()) if (Type.getSizeInBits() >= OtherType.getSizeInBits())
if (Type.getVectorElementType().getSizeInBits() if (Type.getVectorElementType().getSizeInBits()
>= OtherType.getVectorElementType().getSizeInBits()) >= OtherType.getVectorElementType().getSizeInBits()) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
getName() + "' element type not smaller than '" + getName() + "' element type not smaller than '" +
Other.getName() +"'!"); Other.getName() +"'!");
return false;
}
} }
else else
// For scalar types, the bitsize of this type must be larger // For scalar types, the bitsize of this type must be larger
// than that of the other. // than that of the other.
if (Type.getSizeInBits() >= OtherType.getSizeInBits()) if (Type.getSizeInBits() >= OtherType.getSizeInBits()) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
getName() + "' is not smaller than '" + getName() + "' is not smaller than '" +
Other.getName() +"'!"); 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 // If this is the only type in the large set, the constraint can never be
// satisfied. // satisfied.
if ((Other.hasIntegerTypes() && OtherIntSize == 0) if ((Other.hasIntegerTypes() && OtherIntSize == 0)
|| (Other.hasFloatingPointTypes() && OtherFPSize == 0)) || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
Other.getName() + "' has nothing larger than '" + getName() +"'!"); Other.getName() + "' has nothing larger than '" + getName() +"'!");
return false;
}
// Okay, find the largest type in the Other set and remove it from the // Okay, find the largest type in the Other set and remove it from the
// current set. // 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 // If this is the only type in the small set, the constraint can never be
// satisfied. // satisfied.
if ((hasIntegerTypes() && IntSize == 0) if ((hasIntegerTypes() && IntSize == 0)
|| (hasFloatingPointTypes() && FPSize == 0)) || (hasFloatingPointTypes() && FPSize == 0)) {
TP.error("Type inference contradiction found, '" + TP.error("Type inference contradiction found, '" +
getName() + "' has nothing smaller than '" + Other.getName()+"'!"); getName() + "' has nothing smaller than '" + Other.getName()+"'!");
return false;
}
return MadeChange; return MadeChange;
} }
@ -504,6 +537,9 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
/// whose element is specified by VTOperand. /// whose element is specified by VTOperand.
bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
TreePattern &TP) { TreePattern &TP) {
if (TP.hasError())
return false;
// "This" must be a vector and "VTOperand" must be a scalar. // "This" must be a vector and "VTOperand" must be a scalar.
bool MadeChange = false; bool MadeChange = false;
MadeChange |= EnforceVector(TP); 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 '" + TP.error("Type inference contradiction found, forcing '" +
InputSet.getName() + "' to have a vector element"); InputSet.getName() + "' to have a vector element");
return false;
}
return MadeChange; return MadeChange;
} }
@ -769,7 +807,7 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
ConstraintType = SDTCisVT; ConstraintType = SDTCisVT;
x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
if (x.SDTCisVT_Info.VT == MVT::isVoid) 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")) { } else if (R->isSubClassOf("SDTCisPtrTy")) {
ConstraintType = SDTCisPtrTy; ConstraintType = SDTCisPtrTy;
@ -829,11 +867,13 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N,
/// ApplyTypeConstraint - Given a node in a pattern, apply this type /// ApplyTypeConstraint - Given a node in a pattern, apply this type
/// constraint to the nodes operands. This returns true if it makes a /// constraint to the nodes operands. This returns true if it makes a
/// change, false otherwise. If a type contradiction is found, throw an /// change, false otherwise. If a type contradiction is found, flag an error.
/// exception.
bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
const SDNodeInfo &NodeInfo, const SDNodeInfo &NodeInfo,
TreePattern &TP) const { TreePattern &TP) const {
if (TP.hasError())
return false;
unsigned ResNo = 0; // The result number being referenced. unsigned ResNo = 0; // The result number being referenced.
TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
@ -866,8 +906,10 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
if (!NodeToApply->isLeaf() || if (!NodeToApply->isLeaf() ||
!isa<DefInit>(NodeToApply->getLeafValue()) || !isa<DefInit>(NodeToApply->getLeafValue()) ||
!static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef() !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
->isSubClassOf("ValueType")) ->isSubClassOf("ValueType")) {
TP.error(N->getOperator()->getName() + " expects a VT operand!"); TP.error(N->getOperator()->getName() + " expects a VT operand!");
return false;
}
MVT::SimpleValueType VT = MVT::SimpleValueType VT =
getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()); 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 /// fragments, inline them into place, giving us a pattern without any
/// PatFrag references. /// PatFrag references.
TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { 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(); Record *Op = getOperator();
if (!Op->isSubClassOf("PatFrag")) { if (!Op->isSubClassOf("PatFrag")) {
@ -1199,9 +1245,11 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op);
// Verify that we are passing the right number of operands. // 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 " + TP.error("'" + Op->getName() + "' fragment requires " +
utostr(Frag->getNumArgs()) + " operands!"); utostr(Frag->getNumArgs()) + " operands!");
return false;
}
TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
@ -1375,9 +1423,11 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const {
/// ApplyTypeConstraints - Apply all of the type constraints relevant to /// ApplyTypeConstraints - Apply all of the type constraints relevant to
/// this node and its children in the tree. This returns true if it makes a /// 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 /// change, false otherwise. If a type contradiction is found, flag an error.
/// exception.
bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (TP.hasError())
return false;
CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); CodeGenDAGPatterns &CDP = TP.getDAGPatterns();
if (isLeaf()) { if (isLeaf()) {
if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 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()) + TP.error("Integer value '" + itostr(II->getValue()) +
"' is out of range for type '" + getEnumName(getType(0)) + "'!"); "' is out of range for type '" + getEnumName(getType(0)) + "'!");
return MadeChange; return false;
} }
return false; return false;
} }
@ -1477,10 +1527,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
for (unsigned i = 0, e = NumRetVTs; i != e; ++i) for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP);
if (getNumChildren() != NumParamVTs + 1) if (getNumChildren() != NumParamVTs + 1) {
TP.error("Intrinsic '" + Int->Name + "' expects " + TP.error("Intrinsic '" + Int->Name + "' expects " +
utostr(NumParamVTs) + " operands, not " + utostr(NumParamVTs) + " operands, not " +
utostr(getNumChildren() - 1) + " operands!"); utostr(getNumChildren() - 1) + " operands!");
return false;
}
// Apply type info to the intrinsic ID. // Apply type info to the intrinsic ID.
MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); 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. // Check that the number of operands is sane. Negative operands -> varargs.
if (NI.getNumOperands() >= 0 && if (NI.getNumOperands() >= 0 &&
getNumChildren() != (unsigned)NI.getNumOperands()) getNumChildren() != (unsigned)NI.getNumOperands()) {
TP.error(getOperator()->getName() + " node requires exactly " + TP.error(getOperator()->getName() + " node requires exactly " +
itostr(NI.getNumOperands()) + " operands!"); itostr(NI.getNumOperands()) + " operands!");
return false;
}
bool MadeChange = NI.ApplyTypeConstraints(this, TP); bool MadeChange = NI.ApplyTypeConstraints(this, TP);
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
@ -1576,9 +1630,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
continue; continue;
// Verify that we didn't run out of provided operands. // Verify that we didn't run out of provided operands.
if (ChildNo >= getNumChildren()) if (ChildNo >= getNumChildren()) {
TP.error("Instruction '" + getOperator()->getName() + TP.error("Instruction '" + getOperator()->getName() +
"' expects more operands than were provided."); "' expects more operands than were provided.");
return false;
}
MVT::SimpleValueType VT; MVT::SimpleValueType VT;
TreePatternNode *Child = getChild(ChildNo++); TreePatternNode *Child = getChild(ChildNo++);
@ -1606,9 +1662,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
} }
if (ChildNo != getNumChildren()) if (ChildNo != getNumChildren()) {
TP.error("Instruction '" + getOperator()->getName() + TP.error("Instruction '" + getOperator()->getName() +
"' was provided too many operands!"); "' was provided too many operands!");
return false;
}
return MadeChange; return MadeChange;
} }
@ -1616,9 +1674,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
// Node transforms always take one operand. // Node transforms always take one operand.
if (getNumChildren() != 1) if (getNumChildren() != 1) {
TP.error("Node transform '" + getOperator()->getName() + TP.error("Node transform '" + getOperator()->getName() +
"' requires one operand!"); "' requires one operand!");
return false;
}
bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters); 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, TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
isInputPattern = isInput; isInputPattern(isInput), HasError(false) {
for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i)
Trees.push_back(ParseTreePattern(RawPat->getElement(i), "")); Trees.push_back(ParseTreePattern(RawPat->getElement(i), ""));
} }
TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
isInputPattern = isInput; isInputPattern(isInput), HasError(false) {
Trees.push_back(ParseTreePattern(Pat, "")); Trees.push_back(ParseTreePattern(Pat, ""));
} }
TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
isInputPattern = isInput; isInputPattern(isInput), HasError(false) {
Trees.push_back(Pat); Trees.push_back(Pat);
} }
void TreePattern::error(const std::string &Msg) const { void TreePattern::error(const std::string &Msg) {
if (HasError)
return;
dump(); dump();
throw TGError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg);
HasError = true;
} }
void TreePattern::ComputeNamedNodes() { void TreePattern::ComputeNamedNodes() {
@ -1901,7 +1964,7 @@ static bool SimplifyTree(TreePatternNode *&N) {
/// InferAllTypes - Infer/propagate as many types throughout the expression /// InferAllTypes - Infer/propagate as many types throughout the expression
/// patterns as possible. Return true if all types are inferred, false /// 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:: bool TreePattern::
InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
if (NamedNodes.empty()) 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 // 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. // all of them, some may depend on the inputs of the pattern.
try {
ThePat->InferAllTypes(); ThePat->InferAllTypes();
} catch (...) { ThePat->resetError();
// 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.
}
// If debugging, print out the pattern fragment result. // If debugging, print out the pattern fragment result.
DEBUG(ThePat->dump()); DEBUG(ThePat->dump());
@ -2199,8 +2256,8 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
/* Resolve all types */; /* Resolve all types */;
if (TPN->ContainsUnresolvedType()) { if (TPN->ContainsUnresolvedType()) {
throw "Value #" + utostr(i) + " of OperandWithDefaultOps '" + PrintFatalError("Value #" + utostr(i) + " of OperandWithDefaultOps '" +
DefaultOps[i]->getName() +"' doesn't have a concrete type!"; DefaultOps[i]->getName() +"' doesn't have a concrete type!");
} }
DefaultOpInfo.DefaultOps.push_back(TPN); DefaultOpInfo.DefaultOps.push_back(TPN);
} }
@ -2746,7 +2803,7 @@ void CodeGenDAGPatterns::ParseInstructions() {
Instructions.begin(), Instructions.begin(),
E = Instructions.end(); II != E; ++II) { E = Instructions.end(); II != E; ++II) {
DAGInstruction &TheInst = II->second; DAGInstruction &TheInst = II->second;
const TreePattern *I = TheInst.getPattern(); TreePattern *I = TheInst.getPattern();
if (I == 0) continue; // No pattern. if (I == 0) continue; // No pattern.
// FIXME: Assume only the first tree is the pattern. The others are clobber // 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, static void FindNames(const TreePatternNode *P,
std::map<std::string, NameRecord> &Names, std::map<std::string, NameRecord> &Names,
const TreePattern *PatternTop) { TreePattern *PatternTop) {
if (!P->getName().empty()) { if (!P->getName().empty()) {
NameRecord &Rec = Names[P->getName()]; NameRecord &Rec = Names[P->getName()];
// If this is the first instance of the name, remember the node. // 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) { const PatternToMatch &PTM) {
// Do some sanity checking on the pattern we're about to match. // Do some sanity checking on the pattern we're about to match.
std::string Reason; std::string Reason;
@ -2895,7 +2952,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
} }
if (Errors) if (Errors)
throw "pattern conflicts"; PrintFatalError("pattern conflicts");
// Revisit instructions with undefined flags and no pattern. // Revisit instructions with undefined flags and no pattern.
if (Target.guessInstructionProperties()) { if (Target.guessInstructionProperties()) {
@ -2992,7 +3049,7 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() {
} }
} }
if (Errors) 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 /// Given a pattern result with an unresolved type, see if we can find one

View File

@ -105,7 +105,7 @@ namespace EEVT {
/// MergeInTypeInfo - This merges in type information from the specified /// MergeInTypeInfo - This merges in type information from the specified
/// argument. If 'this' changes, it returns true. If the two types are /// 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(const EEVT::TypeSet &InVT, TreePattern &TP);
bool MergeInTypeInfo(MVT::SimpleValueType 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 /// ApplyTypeConstraint - Given a node in a pattern, apply this type
/// constraint to the nodes operands. This returns true if it makes a /// constraint to the nodes operands. This returns true if it makes a
/// change, false otherwise. If a type contradiction is found, throw an /// change, false otherwise. If a type contradiction is found, an error
/// exception. /// is flagged.
bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo,
TreePattern &TP) const; TreePattern &TP) const;
}; };
@ -232,7 +232,7 @@ public:
/// ApplyTypeConstraints - Given a node in a pattern, apply the type /// ApplyTypeConstraints - Given a node in a pattern, apply the type
/// constraints for this node to the operands of the node. This returns /// 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 /// 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 ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const {
bool MadeChange = false; bool MadeChange = false;
for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) 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 /// ApplyTypeConstraints - Apply all of the type constraints relevant to
/// this node and its children in the tree. This returns true if it makes a /// 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 /// change, false otherwise. If a type contradiction is found, flag an error.
/// exception.
bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters); bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters);
/// UpdateNodeType - Set the node type of N to VT if VT contains /// UpdateNodeType - Set the node type of N to VT if VT contains
/// information. If N already contains a conflicting type, then throw an /// information. If N already contains a conflicting type, then flag an
/// exception. This returns true if any information was updated. /// error. This returns true if any information was updated.
/// ///
bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy, bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy,
TreePattern &TP) { TreePattern &TP) {
@ -514,6 +513,10 @@ class TreePattern {
/// isInputPattern - True if this is an input pattern, something to match. /// isInputPattern - True if this is an input pattern, something to match.
/// False if this is an output pattern, something to emit. /// False if this is an output pattern, something to emit.
bool isInputPattern; bool isInputPattern;
/// hasError - True if the currently processed nodes have unresolvable types
/// or other non-fatal errors
bool HasError;
public: public:
/// TreePattern constructor - Parse the specified DagInits into the /// TreePattern constructor - Parse the specified DagInits into the
@ -565,13 +568,19 @@ public:
/// InferAllTypes - Infer/propagate as many types throughout the expression /// InferAllTypes - Infer/propagate as many types throughout the expression
/// patterns as possible. Return true if all types are inferred, false /// 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> > bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> >
*NamedTypes=0); *NamedTypes=0);
/// error - Throw an exception, prefixing it with information about this /// error - If this is the first error in the current resolution step,
/// pattern. /// print it and set the error flag. Otherwise, continue silently.
void error(const std::string &Msg) const; void error(const std::string &Msg);
bool hasError() const {
return HasError;
}
void resetError() {
HasError = false;
}
void print(raw_ostream &OS) const; void print(raw_ostream &OS) const;
void dump() const; void dump() const;
@ -602,7 +611,7 @@ public:
: Pattern(TP), Results(results), Operands(operands), : Pattern(TP), Results(results), Operands(operands),
ImpResults(impresults), ResultPattern(0) {} ImpResults(impresults), ResultPattern(0) {}
const TreePattern *getPattern() const { return Pattern; } TreePattern *getPattern() const { return Pattern; }
unsigned getNumResults() const { return Results.size(); } unsigned getNumResults() const { return Results.size(); }
unsigned getNumOperands() const { return Operands.size(); } unsigned getNumOperands() const { return Operands.size(); }
unsigned getNumImpResults() const { return ImpResults.size(); } unsigned getNumImpResults() const { return ImpResults.size(); }
@ -794,7 +803,7 @@ private:
void GenerateVariants(); void GenerateVariants();
void VerifyInstructionFlags(); void VerifyInstructionFlags();
void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM); void AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM);
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
std::map<std::string, std::map<std::string,
TreePatternNode*> &InstInputs, TreePatternNode*> &InstInputs,

View File

@ -34,18 +34,18 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) { if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
if (Init->getDef()->getName() != "outs") 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 } else
throw R->getName() + ": invalid output list: use 'outs'"; PrintFatalError(R->getName() + ": invalid output list: use 'outs'");
NumDefs = OutDI->getNumArgs(); NumDefs = OutDI->getNumArgs();
DagInit *InDI = R->getValueAsDag("InOperandList"); DagInit *InDI = R->getValueAsDag("InOperandList");
if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) { if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) {
if (Init->getDef()->getName() != "ins") 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 } else
throw R->getName() + ": invalid input list: use 'ins'"; PrintFatalError(R->getName() + ": invalid input list: use 'ins'");
unsigned MIOperandNo = 0; unsigned MIOperandNo = 0;
std::set<std::string> OperandNames; std::set<std::string> OperandNames;
@ -62,7 +62,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
DefInit *Arg = dyn_cast<DefInit>(ArgInit); DefInit *Arg = dyn_cast<DefInit>(ArgInit);
if (!Arg) if (!Arg)
throw "Illegal operand for the '" + R->getName() + "' instruction!"; PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!");
Record *Rec = Arg->getDef(); Record *Rec = Arg->getDef();
std::string PrintMethod = "printOperand"; std::string PrintMethod = "printOperand";
@ -82,8 +82,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
// Verify that MIOpInfo has an 'ops' root value. // Verify that MIOpInfo has an 'ops' root value.
if (!isa<DefInit>(MIOpInfo->getOperator()) || if (!isa<DefInit>(MIOpInfo->getOperator()) ||
cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops") cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops")
throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() +
"'\n"; "'\n");
// If we have MIOpInfo, then we have #operands equal to number of entries // If we have MIOpInfo, then we have #operands equal to number of entries
// in MIOperandInfo. // in MIOperandInfo.
@ -101,16 +101,16 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
OperandType = "OPERAND_REGISTER"; OperandType = "OPERAND_REGISTER";
} else if (!Rec->isSubClassOf("PointerLikeRegClass") && } else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
!Rec->isSubClassOf("unknown_class")) !Rec->isSubClassOf("unknown_class"))
throw "Unknown operand class '" + Rec->getName() + PrintFatalError("Unknown operand class '" + Rec->getName() +
"' in '" + R->getName() + "' instruction!"; "' in '" + R->getName() + "' instruction!");
// Check that the operand has a name and that it's unique. // Check that the operand has a name and that it's unique.
if (ArgName.empty()) if (ArgName.empty())
throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) +
" has no name!"; " has no name!");
if (!OperandNames.insert(ArgName).second) if (!OperandNames.insert(ArgName).second)
throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) +
" has the same name as a previous operand!"; " has the same name as a previous operand!");
OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod,
OperandType, MIOperandNo, NumOps, OperandType, MIOperandNo, NumOps,
@ -128,13 +128,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
/// getOperandNamed - Return the index of the operand with the specified /// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the /// 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 CGIOperandList::getOperandNamed(StringRef Name) const {
unsigned OpIdx; unsigned OpIdx;
if (hasOperandNamed(Name, OpIdx)) return OpIdx; if (hasOperandNamed(Name, OpIdx)) return OpIdx;
throw "'" + TheDef->getName() + "' does not have an operand named '$" + PrintFatalError("'" + TheDef->getName() + "' does not have an operand named '$" +
Name.str() + "'!"; Name.str() + "'!");
} }
/// hasOperandNamed - Query whether the instruction has an operand of the /// 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> std::pair<unsigned,unsigned>
CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
if (Op.empty() || Op[0] != '$') 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 OpName = Op.substr(1);
std::string SubOpName; std::string SubOpName;
@ -163,7 +163,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
if (DotIdx != std::string::npos) { if (DotIdx != std::string::npos) {
SubOpName = OpName.substr(DotIdx+1); SubOpName = OpName.substr(DotIdx+1);
if (SubOpName.empty()) 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); OpName = OpName.substr(0, DotIdx);
} }
@ -173,8 +173,8 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
// If one was needed, throw. // If one was needed, throw.
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
SubOpName.empty()) SubOpName.empty())
throw TheDef->getName() + ": Illegal to refer to" PrintFatalError(TheDef->getName() + ": Illegal to refer to"
" whole operand part of complex operand '" + Op + "'"; " whole operand part of complex operand '" + Op + "'");
// Otherwise, return the operand. // Otherwise, return the operand.
return std::make_pair(OpIdx, 0U); return std::make_pair(OpIdx, 0U);
@ -183,7 +183,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
// Find the suboperand number involved. // Find the suboperand number involved.
DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
if (MIOpInfo == 0) 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. // Find the operand with the right name.
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) 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); return std::make_pair(OpIdx, i);
// Otherwise, didn't find it! // 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) { 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); std::string Name = CStr.substr(wpos+1);
wpos = Name.find_first_not_of(" \t"); wpos = Name.find_first_not_of(" \t");
if (wpos == std::string::npos) if (wpos == std::string::npos)
throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; PrintFatalError("Illegal format for @earlyclobber constraint: '" + CStr + "'");
Name = Name.substr(wpos); Name = Name.substr(wpos);
std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false); std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false);
// Build the string for the operand // Build the string for the operand
if (!Ops[Op.first].Constraints[Op.second].isNone()) 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] = Ops[Op.first].Constraints[Op.second] =
CGIOperandList::ConstraintInfo::getEarlyClobber(); CGIOperandList::ConstraintInfo::getEarlyClobber();
return; return;
@ -224,14 +224,14 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) {
// TIED_TO: $src1 = $dst // TIED_TO: $src1 = $dst
wpos = Name.find_first_of(" \t"); wpos = Name.find_first_of(" \t");
if (wpos == std::string::npos) 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::string DestOpName = Name.substr(0, wpos);
std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false); std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false);
Name = CStr.substr(pos+1); Name = CStr.substr(pos+1);
wpos = Name.find_first_not_of(" \t"); wpos = Name.find_first_not_of(" \t");
if (wpos == std::string::npos) 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::string SrcOpName = Name.substr(wpos);
std::pair<unsigned,unsigned> SrcOp = Ops.ParseOperandName(SrcOpName, false); 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); unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp);
if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) 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] = Ops[DestOp.first].Constraints[DestOp.second] =
CGIOperandList::ConstraintInfo::getTied(FlatOpNo); CGIOperandList::ConstraintInfo::getTied(FlatOpNo);
} }
@ -328,7 +329,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
ImplicitUses = R->getValueAsListOfDefs("Uses"); ImplicitUses = R->getValueAsListOfDefs("Uses");
if (neverHasSideEffects + hasSideEffects > 1) if (neverHasSideEffects + hasSideEffects > 1)
throw R->getName() + ": multiple conflicting side-effect flags set!"; PrintFatalError(R->getName() + ": multiple conflicting side-effect flags set!");
// Parse Constraints. // Parse Constraints.
ParseConstraints(R->getValueAsString("Constraints"), Operands); 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 // If the operand is a record, it must have a name, and the record type
// must match up with the instruction's argument type. // must match up with the instruction's argument type.
if (Result->getArgName(AliasOpNo).empty()) if (Result->getArgName(AliasOpNo).empty())
throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) +
" must have a name!"); " must have a name!");
ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef());
return true; return true;
@ -457,12 +458,12 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (!T.getRegisterClass(InstOpRec) if (!T.getRegisterClass(InstOpRec)
.contains(T.getRegBank().getReg(ADI->getDef()))) .contains(T.getRegBank().getReg(ADI->getDef())))
throw TGError(Loc, "fixed register " + ADI->getDef()->getName() + PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
" is not a member of the " + InstOpRec->getName() + " is not a member of the " + InstOpRec->getName() +
" register class!"); " register class!");
if (!Result->getArgName(AliasOpNo).empty()) if (!Result->getArgName(AliasOpNo).empty())
throw TGError(Loc, "result fixed register argument must " PrintFatalError(Loc, "result fixed register argument must "
"not have a name!"); "not have a name!");
ResOp = ResultOperand(ADI->getDef()); ResOp = ResultOperand(ADI->getDef());
@ -491,7 +492,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
return false; return false;
// Integer arguments can't have names. // Integer arguments can't have names.
if (!Result->getArgName(AliasOpNo).empty()) if (!Result->getArgName(AliasOpNo).empty())
throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) +
" must not have a name!"); " must not have a name!");
ResOp = ResultOperand(II->getValue()); ResOp = ResultOperand(II->getValue());
return true; return true;
@ -520,7 +521,8 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
// Verify that the root of the result is an instruction. // Verify that the root of the result is an instruction.
DefInit *DI = dyn_cast<DefInit>(Result->getOperator()); DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) 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()); ResultInst = &T.getInstruction(DI->getDef());
@ -536,7 +538,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
// same type. // same type.
Record *&Entry = NameClass[Result->getArgName(i)]; Record *&Entry = NameClass[Result->getArgName(i)];
if (Entry && Entry != ADI->getDef()) if (Entry && Entry != ADI->getDef())
throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) + PrintFatalError(R->getLoc(), "result value $" + Result->getArgName(i) +
" is both " + Entry->getName() + " and " + " is both " + Entry->getName() + " and " +
ADI->getDef()->getName() + "!"); ADI->getDef()->getName() + "!");
Entry = ADI->getDef(); Entry = ADI->getDef();
@ -554,7 +556,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
continue; continue;
if (AliasOpNo >= Result->getNumArgs()) 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; Record *InstOpRec = ResultInst->Operands[i].Rec;
unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
@ -595,7 +597,7 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
if (AliasOpNo >= Result->getNumArgs()) 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(); Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false,
R->getLoc(), T, ResOp)) { R->getLoc(), T, ResOp)) {
@ -603,18 +605,18 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
++AliasOpNo; ++AliasOpNo;
} else { } else {
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" does not match instruction operand class " + " does not match instruction operand class " +
(SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); (SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
} }
} }
continue; continue;
} }
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" does not match instruction operand class " + " does not match instruction operand class " +
InstOpRec->getName()); InstOpRec->getName());
} }
if (AliasOpNo != Result->getNumArgs()) if (AliasOpNo != Result->getNumArgs())
throw TGError(R->getLoc(), "too many operands for instruction!"); PrintFatalError(R->getLoc(), "too many operands for instruction!");
} }

View File

@ -152,7 +152,7 @@ namespace llvm {
/// getOperandNamed - Return the index of the operand with the specified /// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the /// 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; unsigned getOperandNamed(StringRef Name) const;
/// hasOperandNamed - Query whether the instruction has an operand of the /// 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", /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
/// where $foo is a whole operand and $foo.bar refers to a suboperand. /// 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 /// This aborts if the name is invalid. If AllowWholeOp is true, references
/// true, references to operands with suboperands are allowed, otherwise /// to operands with suboperands are allowed, otherwise not.
/// not.
std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op, std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
bool AllowWholeOp = true); bool AllowWholeOp = true);

View File

@ -78,6 +78,7 @@
#include "CodeGenTarget.h" #include "CodeGenTarget.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include "llvm/TableGen/Error.h"
using namespace llvm; using namespace llvm;
typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy; 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. // Each instruction map must specify at least one column for it to be valid.
if (ColValList->getSize() == 0) if (ColValList->getSize() == 0)
throw "InstrMapping record `" + MapRec->getName() + "' has empty " + PrintFatalError(MapRec->getLoc(), "InstrMapping record `" +
"`ValueCols' field!"; MapRec->getName() + "' has empty " + "`ValueCols' field!");
for (unsigned i = 0, e = ColValList->getSize(); i < e; i++) { for (unsigned i = 0, e = ColValList->getSize(); i < e; i++) {
ListInit *ColI = dyn_cast<ListInit>(ColValList->getElement(i)); ListInit *ColI = dyn_cast<ListInit>(ColValList->getElement(i));
// Make sure that all the sub-lists in 'ValueCols' have same number of // Make sure that all the sub-lists in 'ValueCols' have same number of
// elements as the fields in 'ColFields'. // elements as the fields in 'ColFields'.
if (ColI->getSize() == ColFields->getSize()) 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); ValueCols.push_back(ColI);
else {
throw "Record `" + MapRec->getName() + "', field `" + "ValueCols" +
"' entries don't match with the entries in 'ColFields'!";
}
} }
} }
@ -344,9 +344,8 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
if (MatchFound) { if (MatchFound) {
if (MatchInstr) // Already had a match if (MatchInstr) // Already had a match
// Error if multiple matches are found for a column. // Error if multiple matches are found for a column.
throw "Multiple matches found for `" + KeyInstr->getName() + PrintFatalError("Multiple matches found for `" + KeyInstr->getName() +
"', for the relation `" + InstrMapDesc.getName(); "', for the relation `" + InstrMapDesc.getName());
else
MatchInstr = CurInstr; MatchInstr = CurInstr;
} }
} }
@ -516,10 +515,9 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
for (unsigned j = 0; j < ListSize; j++) { for (unsigned j = 0; j < ListSize; j++) {
ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j)); ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j));
if (ListJ->getSize() != ColFields->getSize()) { if (ListJ->getSize() != ColFields->getSize())
throw "Record `" + CurMap->getName() + "', field `" + "ValueCols" + PrintFatalError("Record `" + CurMap->getName() + "', field "
"' entries don't match with the entries in 'ColFields' !"; "`ValueCols' entries don't match with the entries in 'ColFields' !");
}
ValueCols.push_back(ListJ); ValueCols.push_back(ListJ);
} }

View File

@ -54,19 +54,20 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf"); std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
if (!Comps.empty()) { if (!Comps.empty()) {
if (Comps.size() != 2) 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 *A = RegBank.getSubRegIdx(Comps[0]);
CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
CodeGenSubRegIndex *X = A->addComposite(B, this); CodeGenSubRegIndex *X = A->addComposite(B, this);
if (X) if (X)
throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
} }
std::vector<Record*> Parts = std::vector<Record*> Parts =
TheDef->getValueAsListOfDefs("CoveringSubRegIndices"); TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
if (!Parts.empty()) { if (!Parts.empty()) {
if (Parts.size() < 2) if (Parts.size() < 2)
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"CoveredBySubRegs must have two or more entries"); "CoveredBySubRegs must have two or more entries");
SmallVector<CodeGenSubRegIndex*, 8> IdxParts; SmallVector<CodeGenSubRegIndex*, 8> IdxParts;
for (unsigned i = 0, e = Parts.size(); i != e; ++i) for (unsigned i = 0, e = Parts.size(); i != e; ++i)
@ -112,7 +113,7 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
std::vector<Record*> SRs = TheDef->getValueAsListOfDefs("SubRegs"); std::vector<Record*> SRs = TheDef->getValueAsListOfDefs("SubRegs");
if (SRIs.size() != SRs.size()) if (SRIs.size() != SRs.size())
throw TGError(TheDef->getLoc(), PrintFatalError(TheDef->getLoc(),
"SubRegs and SubRegIndices must have the same size"); "SubRegs and SubRegIndices must have the same size");
for (unsigned i = 0, e = SRIs.size(); i != e; ++i) { for (unsigned i = 0, e = SRIs.size(); i != e; ++i) {
@ -224,7 +225,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
CodeGenRegister *SR = ExplicitSubRegs[i]; CodeGenRegister *SR = ExplicitSubRegs[i];
CodeGenSubRegIndex *Idx = ExplicitSubRegIndices[i]; CodeGenSubRegIndex *Idx = ExplicitSubRegIndices[i];
if (!SubRegs.insert(std::make_pair(Idx, SR)).second) if (!SubRegs.insert(std::make_pair(Idx, SR)).second)
throw TGError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() + PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() +
" appears twice in Register " + getName()); " appears twice in Register " + getName());
// Map explicit sub-registers first, so the names take precedence. // Map explicit sub-registers first, so the names take precedence.
// The inherited sub-registers are mapped below. // The inherited sub-registers are mapped below.
@ -308,7 +309,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
ArrayRef<SMLoc> Loc; ArrayRef<SMLoc> Loc;
if (TheDef) if (TheDef)
Loc = TheDef->getLoc(); Loc = TheDef->getLoc();
throw TGError(Loc, "Register " + getName() + PrintFatalError(Loc, "Register " + getName() +
" has itself as a sub-register"); " has itself as a sub-register");
} }
// Ensure that every sub-register has a unique name. // Ensure that every sub-register has a unique name.
@ -320,7 +321,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
ArrayRef<SMLoc> Loc; ArrayRef<SMLoc> Loc;
if (TheDef) if (TheDef)
Loc = TheDef->getLoc(); 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->second->getName() + " available as " +
SI->first->getName() + " and " + Ins->second->getName()); SI->first->getName() + " and " + Ins->second->getName());
} }
@ -467,7 +468,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) { SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) {
CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second); CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second);
if (!SubIdx) if (!SubIdx)
throw TGError(TheDef->getLoc(), "No SubRegIndex for " + PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
SI->second->getName() + " in " + getName()); SI->second->getName() + " in " + getName());
NewIdx->addComposite(SI->first, SubIdx); NewIdx->addComposite(SI->first, SubIdx);
} }
@ -592,9 +593,10 @@ struct TupleExpander : SetTheory::Expander {
unsigned Dim = Indices.size(); unsigned Dim = Indices.size();
ListInit *SubRegs = Def->getValueAsListInit("SubRegs"); ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
if (Dim != SubRegs->getSize()) if (Dim != SubRegs->getSize())
throw TGError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch"); PrintFatalError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch");
if (Dim < 2) 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. // Evaluate the sub-register lists to be zipped.
unsigned Length = ~0u; unsigned Length = ~0u;
@ -706,8 +708,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
Record *Type = TypeList[i]; Record *Type = TypeList[i];
if (!Type->isSubClassOf("ValueType")) if (!Type->isSubClassOf("ValueType"))
throw "RegTypes list member '" + Type->getName() + PrintFatalError("RegTypes list member '" + Type->getName() +
"' does not derive from the ValueType class!"; "' does not derive from the ValueType class!");
VTs.push_back(getValueType(Type)); VTs.push_back(getValueType(Type));
} }
assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); 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()); CodeGenRegister *Reg = RegBank.getReg(Order.back());
Order.pop_back(); Order.pop_back();
if (!contains(Reg)) if (!contains(Reg))
throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() + PrintFatalError(R->getLoc(), " AltOrder register " + Reg->getName() +
" is not a class member"); " is not a class member");
} }
} }
@ -1021,7 +1023,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
// Read in register class definitions. // Read in register class definitions.
std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
if (RCs.empty()) if (RCs.empty())
throw std::string("No 'RegisterClass' subclasses defined!"); PrintFatalError(std::string("No 'RegisterClass' subclasses defined!"));
// Allocate user-defined register classes. // Allocate user-defined register classes.
RegClasses.reserve(RCs.size()); RegClasses.reserve(RCs.size());
@ -1098,7 +1100,7 @@ CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
if (CodeGenRegisterClass *RC = Def2RC[Def]) if (CodeGenRegisterClass *RC = Def2RC[Def])
return RC; return RC;
throw TGError(Def->getLoc(), "Not a known RegisterClass!"); PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
} }
CodeGenSubRegIndex* CodeGenSubRegIndex*

View File

@ -63,7 +63,7 @@ struct InstRegexOp : public SetTheory::Operator {
AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) { AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) {
StringInit *SI = dyn_cast<StringInit>(*AI); StringInit *SI = dyn_cast<StringInit>(*AI);
if (!SI) if (!SI)
throw TGError(Loc, "instregex requires pattern string: " PrintFatalError(Loc, "instregex requires pattern string: "
+ Expr->getAsString()); + Expr->getAsString());
std::string pat = SI->getValue(); std::string pat = SI->getValue();
// Implement a python-style prefix match. // Implement a python-style prefix match.
@ -268,13 +268,13 @@ void CodeGenSchedModels::collectSchedRW() {
Record *AliasDef = (*AI)->getValueAsDef("AliasRW"); Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
if (MatchDef->isSubClassOf("SchedWrite")) { if (MatchDef->isSubClassOf("SchedWrite")) {
if (!AliasDef->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); scanSchedRW(AliasDef, SWDefs, RWSet);
} }
else { else {
assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite"); assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
if (!AliasDef->isSubClassOf("SchedRead")) 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); scanSchedRW(AliasDef, SRDefs, RWSet);
} }
} }
@ -305,7 +305,7 @@ void CodeGenSchedModels::collectSchedRW() {
Record *MatchDef = (*AI)->getValueAsDef("MatchRW"); Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
CodeGenSchedRW &RW = getSchedRW(MatchDef); CodeGenSchedRW &RW = getSchedRW(MatchDef);
if (RW.IsAlias) if (RW.IsAlias)
throw TGError((*AI)->getLoc(), "Cannot Alias an Alias"); PrintFatalError((*AI)->getLoc(), "Cannot Alias an Alias");
RW.Aliases.push_back(*AI); RW.Aliases.push_back(*AI);
} }
DEBUG( DEBUG(
@ -437,7 +437,7 @@ void CodeGenSchedModels::expandRWSeqForProc(
continue; continue;
} }
if (AliasDef) if (AliasDef)
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases " PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
"defined for processor " + ProcModel.ModelName + "defined for processor " + ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW."); " Ensure only one SchedAlias exists per RW.");
AliasDef = AliasRW.TheDef; AliasDef = AliasRW.TheDef;
@ -706,7 +706,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
// Sort Instrs into sets. // Sort Instrs into sets.
const RecVec *InstDefs = Sets.expand(InstRWDef); const RecVec *InstDefs = Sets.expand(InstRWDef);
if (InstDefs->empty()) 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) { for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) {
unsigned SCIdx = 0; unsigned SCIdx = 0;
@ -766,7 +766,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(), for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) { RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) { if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) {
throw TGError(InstRWDef->getLoc(), "Overlapping InstRW def " + PrintFatalError(InstRWDef->getLoc(), "Overlapping InstRW def " +
(*II)->getName() + " also matches " + (*II)->getName() + " also matches " +
(*RI)->getValue("Instrs")->getValue()->getAsString()); (*RI)->getValue("Instrs")->getValue()->getAsString());
} }
@ -825,11 +825,11 @@ void CodeGenSchedModels::collectProcItinRW() {
std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord()); std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord());
for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) { for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) {
if (!(*II)->getValueInit("SchedModel")->isComplete()) if (!(*II)->getValueInit("SchedModel")->isComplete())
throw TGError((*II)->getLoc(), "SchedModel is undefined"); PrintFatalError((*II)->getLoc(), "SchedModel is undefined");
Record *ModelDef = (*II)->getValueAsDef("SchedModel"); Record *ModelDef = (*II)->getValueAsDef("SchedModel");
ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef); ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
if (I == ProcModelMap.end()) { if (I == ProcModelMap.end()) {
throw TGError((*II)->getLoc(), "Undefined SchedMachineModel " PrintFatalError((*II)->getLoc(), "Undefined SchedMachineModel "
+ ModelDef->getName()); + ModelDef->getName());
} }
ProcModels[I->second].ItinRWDefs.push_back(*II); ProcModels[I->second].ItinRWDefs.push_back(*II);
@ -867,7 +867,7 @@ void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
if (!std::count(Matched.begin(), Matched.end(), ItinClassDef)) if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
continue; continue;
if (HasMatch) if (HasMatch)
throw TGError((*II)->getLoc(), "Duplicate itinerary class " PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
+ ItinClassDef->getName() + ItinClassDef->getName()
+ " in ItinResources for " + PM.ModelName); + " in ItinResources for " + PM.ModelName);
HasMatch = true; HasMatch = true;
@ -1095,8 +1095,9 @@ void PredTransitions::getIntersectingVariants(
if (Cnt > 1) { if (Cnt > 1) {
const CodeGenProcModel &PM = const CodeGenProcModel &PM =
*(SchedModels.procModelBegin() + Variant.ProcIdx); *(SchedModels.procModelBegin() + Variant.ProcIdx);
throw TGError(Variant.VarOrSeqDef->getLoc(), PrintFatalError(Variant.VarOrSeqDef->getLoc(),
"Multiple variants defined for processor " + PM.ModelName + "Multiple variants defined for processor " +
PM.ModelName +
" Ensure only one SchedAlias exists per RW."); " Ensure only one SchedAlias exists per RW.");
} }
} }
@ -1215,8 +1216,9 @@ void PredTransitions::substituteVariantOperand(
std::vector<TransVariant> IntersectingVariants; std::vector<TransVariant> IntersectingVariants;
getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants); getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants);
if (IntersectingVariants.empty()) if (IntersectingVariants.empty())
throw TGError(SchedRW.TheDef->getLoc(), "No variant of this type has a " PrintFatalError(SchedRW.TheDef->getLoc(),
"matching predicate on any processor "); "No variant of this type has "
"a matching predicate on any processor");
// Now expand each variant on top of its copy of the transition. // Now expand each variant on top of its copy of the transition.
for (std::vector<TransVariant>::const_iterator for (std::vector<TransVariant>::const_iterator
IVI = IntersectingVariants.begin(), IVI = IntersectingVariants.begin(),
@ -1440,7 +1442,7 @@ void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) {
if (!std::count(Matched.begin(), Matched.end(), ItinClassDef)) if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
continue; continue;
if (HasMatch) if (HasMatch)
throw TGError((*II)->getLoc(), "Duplicate itinerary class " PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
+ ItinClassDef->getName() + ItinClassDef->getName()
+ " in ItinResources for " + PM.ModelName); + " in ItinResources for " + PM.ModelName);
HasMatch = true; HasMatch = true;
@ -1519,7 +1521,7 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
if ((*RI)->getValueAsDef("Kind") == ProcResKind if ((*RI)->getValueAsDef("Kind") == ProcResKind
&& (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) { && (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) {
if (ProcUnitDef) { if (ProcUnitDef) {
throw TGError((*RI)->getLoc(), PrintFatalError((*RI)->getLoc(),
"Multiple ProcessorResourceUnits associated with " "Multiple ProcessorResourceUnits associated with "
+ ProcResKind->getName()); + ProcResKind->getName());
} }
@ -1527,7 +1529,7 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
} }
} }
if (!ProcUnitDef) { if (!ProcUnitDef) {
throw TGError(ProcResKind->getLoc(), PrintFatalError(ProcResKind->getLoc(),
"No ProcessorResources associated with " "No ProcessorResources associated with "
+ ProcResKind->getName()); + ProcResKind->getName());
} }
@ -1586,7 +1588,7 @@ unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const {
RecIter PRPos = std::find(ProcResourceDefs.begin(), ProcResourceDefs.end(), RecIter PRPos = std::find(ProcResourceDefs.begin(), ProcResourceDefs.end(),
PRDef); PRDef);
if (PRPos == ProcResourceDefs.end()) if (PRPos == ProcResourceDefs.end())
throw TGError(PRDef->getLoc(), "ProcResource def is not included in " PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in "
"the ProcResources list for " + ModelName); "the ProcResources list for " + ModelName);
// Idx=0 is reserved for invalid. // Idx=0 is reserved for invalid.
return 1 + PRPos - ProcResourceDefs.begin(); return 1 + PRPos - ProcResourceDefs.begin();

View File

@ -10,13 +10,14 @@
// This class wraps target description classes used by the various code // This class wraps target description classes used by the various code
// generation TableGen backends. This makes it easier to access the data and // 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 // 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 "CodeGenTarget.h"
#include "CodeGenIntrinsics.h" #include "CodeGenIntrinsics.h"
#include "CodeGenSchedule.h" #include "CodeGenSchedule.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
@ -124,9 +125,9 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
: Records(records), RegBank(0), SchedModels(0) { : Records(records), RegBank(0), SchedModels(0) {
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0) if (Targets.size() == 0)
throw std::string("ERROR: No 'Target' subclasses defined!"); PrintFatalError("ERROR: No 'Target' subclasses defined!");
if (Targets.size() != 1) if (Targets.size() != 1)
throw std::string("ERROR: Multiple subclasses of Target defined!"); PrintFatalError("ERROR: Multiple subclasses of Target defined!");
TargetRec = Targets[0]; TargetRec = Targets[0];
} }
@ -160,7 +161,7 @@ Record *CodeGenTarget::getInstructionSet() const {
Record *CodeGenTarget::getAsmParser() const { Record *CodeGenTarget::getAsmParser() const {
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
if (AsmParserNum >= LI.size()) 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]; return LI[AsmParserNum];
} }
@ -171,7 +172,7 @@ Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
std::vector<Record*> LI = std::vector<Record*> LI =
TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
if (i >= LI.size()) 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]; return LI[i];
} }
@ -189,7 +190,7 @@ unsigned CodeGenTarget::getAsmParserVariantCount() const {
Record *CodeGenTarget::getAsmWriter() const { Record *CodeGenTarget::getAsmWriter() const {
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
if (AsmWriterNum >= LI.size()) 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]; return LI[AsmWriterNum];
} }
@ -256,7 +257,7 @@ CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
void CodeGenTarget::ReadInstructions() const { void CodeGenTarget::ReadInstructions() const {
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
if (Insts.size() <= 2) if (Insts.size() <= 2)
throw std::string("No 'Instruction' subclasses defined!"); PrintFatalError("No 'Instruction' subclasses defined!");
// Parse the instructions defined in the .td file. // Parse the instructions defined in the .td file.
for (unsigned i = 0, e = Insts.size(); i != e; ++i) for (unsigned i = 0, e = Insts.size(); i != e; ++i)
@ -272,7 +273,7 @@ GetInstByName(const char *Name,
DenseMap<const Record*, CodeGenInstruction*>::const_iterator DenseMap<const Record*, CodeGenInstruction*>::const_iterator
I = Insts.find(Rec); I = Insts.find(Rec);
if (Rec == 0 || I == Insts.end()) 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; return I->second;
} }
@ -419,7 +420,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
if (DefName.size() <= 4 || if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_") std::string(DefName.begin(), DefName.begin() + 4) != "int_")
throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!");
EnumName = std::string(DefName.begin()+4, DefName.end()); EnumName = std::string(DefName.begin()+4, DefName.end());
@ -439,7 +440,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// Verify it starts with "llvm.". // Verify it starts with "llvm.".
if (Name.size() <= 5 || if (Name.size() <= 5 ||
std::string(Name.begin(), Name.begin() + 5) != "llvm.") std::string(Name.begin(), Name.begin() + 5) != "llvm.")
throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!");
} }
// If TargetPrefix is specified, make sure that Name starts with // If TargetPrefix is specified, make sure that Name starts with
@ -448,8 +449,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
if (Name.size() < 6+TargetPrefix.size() || if (Name.size() < 6+TargetPrefix.size() ||
std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
!= (TargetPrefix + ".")) != (TargetPrefix + "."))
throw "Intrinsic '" + DefName + "' does not start with 'llvm." + PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." +
TargetPrefix + ".'!"; TargetPrefix + ".'!");
} }
// Parse the list of return types. // Parse the list of return types.
@ -481,7 +482,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// Reject invalid types. // Reject invalid types.
if (VT == MVT::isVoid) 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.RetVTs.push_back(VT);
IS.RetTypeDefs.push_back(TyEl); IS.RetTypeDefs.push_back(TyEl);
@ -515,7 +516,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// Reject invalid types. // Reject invalid types.
if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) 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.ParamVTs.push_back(VT);
IS.ParamTypeDefs.push_back(TyEl); IS.ParamTypeDefs.push_back(TyEl);

View File

@ -9,8 +9,8 @@
// //
// This file defines wrappers for the Target class and related global // This file defines wrappers for the Target class and related global
// functionality. This makes it easier to access the data and provides a single // 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 // place that needs to check it for validity. All of these classes abort
// exceptions on error conditions. // on error conditions.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -10,6 +10,7 @@
#include "DAGISelMatcher.h" #include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h" #include "CodeGenDAGPatterns.h"
#include "CodeGenRegisters.h" #include "CodeGenRegisters.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -172,15 +173,10 @@ void MatcherGen::InferPossibleTypes() {
// diagnostics, which we know are impossible at this point. // diagnostics, which we know are impossible at this point.
TreePattern &TP = *CGP.pf_begin()->second; TreePattern &TP = *CGP.pf_begin()->second;
try {
bool MadeChange = true; bool MadeChange = true;
while (MadeChange) while (MadeChange)
MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP, MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,
true/*Ignore reg constraints*/); true/*Ignore reg constraints*/);
} catch (...) {
errs() << "Type constraint application shouldn't fail!";
abort();
}
} }
@ -876,7 +872,7 @@ void MatcherGen::EmitResultOperand(const TreePatternNode *N,
if (OpRec->isSubClassOf("SDNodeXForm")) if (OpRec->isSubClassOf("SDNodeXForm"))
return EmitResultSDNodeXFormAsOperand(N, ResultOps); return EmitResultSDNodeXFormAsOperand(N, ResultOps);
errs() << "Unknown result node to emit code for: " << *N << '\n'; 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() { void MatcherGen::EmitResultCode() {

View File

@ -117,10 +117,8 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i) for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
RecognizableInstr::processInstr(Tables, *numberedInstructions[i], 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()) if (Tables.hasConflicts())
throw TGError(Target.getTargetRecord()->getLoc(), PrintFatalError(Target.getTargetRecord()->getLoc(),
"Primary decode conflict"); "Primary decode conflict");
Tables.emit(OS); Tables.emit(OS);

View File

@ -19,6 +19,7 @@
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h" #include "llvm/TableGen/TableGenBackend.h"
#include <string> #include <string>
@ -777,7 +778,7 @@ static void ARMPopulateOperands(
errs() << "Operand type: " << rec.getName() << '\n'; errs() << "Operand type: " << rec.getName() << '\n';
errs() << "Operand name: " << operandInfo.Name << '\n'; errs() << "Operand name: " << operandInfo.Name << '\n';
errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; errs() << "Instruction name: " << inst.TheDef->getName() << '\n';
throw("Unhandled type in EDEmitter"); PrintFatalError("Unhandled type in EDEmitter");
} }
} }
} }

View File

@ -549,7 +549,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
}; };
if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck))
throw TGError(Pattern.getSrcRecord()->getLoc(), PrintFatalError(Pattern.getSrcRecord()->getLoc(),
"Duplicate record in FastISel table!"); "Duplicate record in FastISel table!");
SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo;

View File

@ -15,6 +15,7 @@
#define DEBUG_TYPE "decoder-emitter" #define DEBUG_TYPE "decoder-emitter"
#include "CodeGenTarget.h" #include "CodeGenTarget.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/ADT/APInt.h" #include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
@ -741,7 +742,7 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
switch (*I) { switch (*I) {
default: default:
throw "invalid decode table opcode"; PrintFatalError("invalid decode table opcode");
case MCD::OPC_ExtractField: { case MCD::OPC_ExtractField: {
++I; ++I;
unsigned Start = *I++; unsigned Start = *I++;

View File

@ -19,6 +19,7 @@
#include "TableGenBackends.h" #include "TableGenBackends.h"
#include "SequenceToOffsetTable.h" #include "SequenceToOffsetTable.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h" #include "llvm/TableGen/TableGenBackend.h"
#include <algorithm> #include <algorithm>
@ -343,13 +344,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
// Emit all of the target-specific flags... // Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
if (!TSF) throw "no TSFlags?"; if (!TSF)
PrintFatalError("no TSFlags?");
uint64_t Value = 0; uint64_t Value = 0;
for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(i))) if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(i)))
Value |= uint64_t(Bit->getValue()) << i; Value |= uint64_t(Bit->getValue()) << i;
else else
throw "Invalid TSFlags bit in " + Inst.TheDef->getName(); PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName());
} }
OS << ", 0x"; OS << ", 0x";
OS.write_hex(Value); OS.write_hex(Value);

View File

@ -15,6 +15,7 @@
#include "CodeGenTarget.h" #include "CodeGenTarget.h"
#include "SequenceToOffsetTable.h" #include "SequenceToOffsetTable.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h" #include "llvm/TableGen/TableGenBackend.h"
@ -249,7 +250,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
if (EVT(VT).isInteger()) { if (EVT(VT).isInteger()) {
unsigned BitWidth = EVT(VT).getSizeInBits(); unsigned BitWidth = EVT(VT).getSizeInBits();
switch (BitWidth) { 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 1: return Sig.push_back(IIT_I1);
case 8: return Sig.push_back(IIT_I8); case 8: return Sig.push_back(IIT_I8);
case 16: return Sig.push_back(IIT_I16); case 16: return Sig.push_back(IIT_I16);
@ -259,7 +260,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
} }
switch (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::f32: return Sig.push_back(IIT_F32);
case MVT::f64: return Sig.push_back(IIT_F64); case MVT::f64: return Sig.push_back(IIT_F64);
case MVT::Metadata: return Sig.push_back(IIT_METADATA); 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()) { if (EVT(VT).isVector()) {
EVT VVT = VT; EVT VVT = VT;
switch (VVT.getVectorNumElements()) { 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 2: Sig.push_back(IIT_V2); break;
case 4: Sig.push_back(IIT_V4); break; case 4: Sig.push_back(IIT_V4); break;
case 8: Sig.push_back(IIT_V8); 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, if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
Ints[i].EnumName)).second) Ints[i].EnumName)).second)
throw "Intrinsic '" + Ints[i].TheDef->getName() + PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
"': duplicate GCC builtin name!"; "': duplicate GCC builtin name!");
} }
} }

View File

@ -10,7 +10,6 @@
LEVEL = ../.. LEVEL = ../..
TOOLNAME = llvm-tblgen TOOLNAME = llvm-tblgen
USEDLIBS = LLVMTableGen.a LLVMSupport.a USEDLIBS = LLVMTableGen.a LLVMSupport.a
REQUIRES_EH := 1
# This tool has no plugins, optimize startup time. # This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1 TOOL_NO_EXPORTS = 1

View File

@ -90,7 +90,7 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
// FIXME: We probably shouldn't ever get a non-zero BaseIdx here. // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
throw TGError(Rec->getLoc(), PrintFatalError(Rec->getLoc(),
"Pseudo operand type '" + DI->getDef()->getName() + "Pseudo operand type '" + DI->getDef()->getName() +
"' does not match expansion operand type '" + "' does not match expansion operand type '" +
Insn.Operands[BaseIdx + i].Rec->getName() + "'"); Insn.Operands[BaseIdx + i].Rec->getName() + "'");
@ -129,21 +129,21 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
if (!OpDef) if (!OpDef)
throw TGError(Rec->getLoc(), Rec->getName() + PrintFatalError(Rec->getLoc(), Rec->getName() +
" has unexpected operator type!"); " has unexpected operator type!");
Record *Operator = OpDef->getDef(); Record *Operator = OpDef->getDef();
if (!Operator->isSubClassOf("Instruction")) if (!Operator->isSubClassOf("Instruction"))
throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
"' is not an instruction!"); "' is not an instruction!");
CodeGenInstruction Insn(Operator); CodeGenInstruction Insn(Operator);
if (Insn.isCodeGenOnly || Insn.isPseudo) if (Insn.isCodeGenOnly || Insn.isPseudo)
throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
"' cannot be another pseudo instruction!"); "' cannot be another pseudo instruction!");
if (Insn.Operands.size() != Dag->getNumArgs()) if (Insn.Operands.size() != Dag->getNumArgs())
throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
"' operand count mismatch"); "' operand count mismatch");
unsigned NumMIOperands = 0; unsigned NumMIOperands = 0;
@ -179,7 +179,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
StringMap<unsigned>::iterator SourceOp = StringMap<unsigned>::iterator SourceOp =
SourceOperands.find(Dag->getArgName(i)); SourceOperands.find(Dag->getArgName(i));
if (SourceOp == SourceOperands.end()) if (SourceOp == SourceOperands.end())
throw TGError(Rec->getLoc(), PrintFatalError(Rec->getLoc(),
"Pseudo output operand '" + Dag->getArgName(i) + "Pseudo output operand '" + Dag->getArgName(i) +
"' has no matching source operand."); "' has no matching source operand.");
// Map the source operand to the destination operand index for each // Map the source operand to the destination operand index for each

View File

@ -1092,7 +1092,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
else if (RegisterClasses.size() < UINT16_MAX) else if (RegisterClasses.size() < UINT16_MAX)
OS << " static const uint16_t Table["; OS << " static const uint16_t Table[";
else else
throw "Too many register classes."; PrintFatalError("Too many register classes.");
OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n";
for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
const CodeGenRegisterClass &RC = *RegisterClasses[rci]; const CodeGenRegisterClass &RC = *RegisterClasses[rci];

View File

@ -36,7 +36,7 @@ struct AddOp : public SetTheory::Operator {
struct SubOp : public SetTheory::Operator { struct SubOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (Expr->arg_size() < 2) 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()); Expr->getAsString());
RecSet Add, Sub; RecSet Add, Sub;
ST.evaluate(*Expr->arg_begin(), Add, Loc); ST.evaluate(*Expr->arg_begin(), Add, Loc);
@ -51,7 +51,7 @@ struct SubOp : public SetTheory::Operator {
struct AndOp : public SetTheory::Operator { struct AndOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (Expr->arg_size() != 2) if (Expr->arg_size() != 2)
throw TGError(Loc, "Set intersection requires two arguments: " + PrintFatalError(Loc, "Set intersection requires two arguments: " +
Expr->getAsString()); Expr->getAsString());
RecSet S1, S2; RecSet S1, S2;
ST.evaluate(Expr->arg_begin()[0], S1, Loc); 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) { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (Expr->arg_size() != 2) if (Expr->arg_size() != 2)
throw TGError(Loc, "Operator requires (Op Set, Int) arguments: " + PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " +
Expr->getAsString()); Expr->getAsString());
RecSet Set; RecSet Set;
ST.evaluate(Expr->arg_begin()[0], Set, Loc); ST.evaluate(Expr->arg_begin()[0], Set, Loc);
IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]); IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]);
if (!II) if (!II)
throw TGError(Loc, "Second argument must be an integer: " + PrintFatalError(Loc, "Second argument must be an integer: " +
Expr->getAsString()); Expr->getAsString());
apply2(ST, Expr, Set, II->getValue(), Elts, Loc); apply2(ST, Expr, Set, II->getValue(), Elts, Loc);
} }
@ -88,7 +88,7 @@ struct ShlOp : public SetIntBinOp {
RecSet &Set, int64_t N, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) { RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (N < 0) if (N < 0)
throw TGError(Loc, "Positive shift required: " + PrintFatalError(Loc, "Positive shift required: " +
Expr->getAsString()); Expr->getAsString());
if (unsigned(N) < Set.size()) if (unsigned(N) < Set.size())
Elts.insert(Set.begin() + N, Set.end()); Elts.insert(Set.begin() + N, Set.end());
@ -101,7 +101,7 @@ struct TruncOp : public SetIntBinOp {
RecSet &Set, int64_t N, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) { RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (N < 0) if (N < 0)
throw TGError(Loc, "Positive length required: " + PrintFatalError(Loc, "Positive length required: " +
Expr->getAsString()); Expr->getAsString());
if (unsigned(N) > Set.size()) if (unsigned(N) > Set.size())
N = Set.size(); N = Set.size();
@ -138,7 +138,7 @@ struct DecimateOp : public SetIntBinOp {
RecSet &Set, int64_t N, RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) { RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (N <= 0) if (N <= 0)
throw TGError(Loc, "Positive stride required: " + PrintFatalError(Loc, "Positive stride required: " +
Expr->getAsString()); Expr->getAsString());
for (unsigned I = 0; I < Set.size(); I += N) for (unsigned I = 0; I < Set.size(); I += N)
Elts.insert(Set[I]); Elts.insert(Set[I]);
@ -168,35 +168,36 @@ struct SequenceOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
int Step = 1; int Step = 1;
if (Expr->arg_size() > 4) 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()); Expr->getAsString());
else if (Expr->arg_size() == 4) { else if (Expr->arg_size() == 4) {
if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) { if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) {
Step = II->getValue(); Step = II->getValue();
} else } else
throw TGError(Loc, "Stride must be an integer: " + Expr->getAsString()); PrintFatalError(Loc, "Stride must be an integer: " +
Expr->getAsString());
} }
std::string Format; std::string Format;
if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0])) if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0]))
Format = SI->getValue(); Format = SI->getValue();
else else
throw TGError(Loc, "Format must be a string: " + Expr->getAsString()); PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString());
int64_t From, To; int64_t From, To;
if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1])) if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]))
From = II->getValue(); From = II->getValue();
else 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)) 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])) if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[2]))
To = II->getValue(); To = II->getValue();
else 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)) if (To < 0 || To >= (1 << 30))
throw TGError(Loc, "To out of range"); PrintFatalError(Loc, "To out of range");
RecordKeeper &Records = RecordKeeper &Records =
cast<DefInit>(Expr->getOperator())->getDef()->getRecords(); cast<DefInit>(Expr->getOperator())->getDef()->getRecords();
@ -212,7 +213,7 @@ struct SequenceOp : public SetTheory::Operator {
OS << format(Format.c_str(), unsigned(From)); OS << format(Format.c_str(), unsigned(From));
Record *Rec = Records.getDef(OS.str()); Record *Rec = Records.getDef(OS.str());
if (!Rec) if (!Rec)
throw TGError(Loc, "No def named '" + Name + "': " + PrintFatalError(Loc, "No def named '" + Name + "': " +
Expr->getAsString()); Expr->getAsString());
// Try to reevaluate Rec in case it is a set. // Try to reevaluate Rec in case it is a set.
if (const RecVec *Result = ST.expand(Rec)) 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. // Anything else must be a DAG.
DagInit *DagExpr = dyn_cast<DagInit>(Expr); DagInit *DagExpr = dyn_cast<DagInit>(Expr);
if (!DagExpr) if (!DagExpr)
throw TGError(Loc, "Invalid set element: " + Expr->getAsString()); PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString());
DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator()); DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator());
if (!OpInit) if (!OpInit)
throw TGError(Loc, "Bad set expression: " + Expr->getAsString()); PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString());
Operator *Op = Operators.lookup(OpInit->getDef()->getName()); Operator *Op = Operators.lookup(OpInit->getDef()->getName());
if (!Op) if (!Op)
throw TGError(Loc, "Unknown set operator: " + Expr->getAsString()); PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString());
Op->apply(*this, DagExpr, Elts, Loc); Op->apply(*this, DagExpr, Elts, Loc);
} }

View File

@ -675,7 +675,7 @@ Record *SubtargetEmitter::FindWriteResources(
continue; continue;
} }
if (AliasDef) if (AliasDef)
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases " PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
"defined for processor " + ProcModel.ModelName + "defined for processor " + ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW."); " Ensure only one SchedAlias exists per RW.");
AliasDef = AliasRW.TheDef; AliasDef = AliasRW.TheDef;
@ -692,7 +692,7 @@ Record *SubtargetEmitter::FindWriteResources(
if (AliasDef == (*WRI)->getValueAsDef("WriteType") if (AliasDef == (*WRI)->getValueAsDef("WriteType")
|| SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) { || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
if (ResDef) { 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 " + "SchedWrite and its alias on processor " +
ProcModel.ModelName); ProcModel.ModelName);
} }
@ -702,7 +702,7 @@ Record *SubtargetEmitter::FindWriteResources(
// TODO: If ProcModel has a base model (previous generation processor), // TODO: If ProcModel has a base model (previous generation processor),
// then call FindWriteResources recursively with that model here. // then call FindWriteResources recursively with that model here.
if (!ResDef) { if (!ResDef) {
throw TGError(ProcModel.ModelDef->getLoc(), PrintFatalError(ProcModel.ModelDef->getLoc(),
std::string("Processor does not define resources for ") std::string("Processor does not define resources for ")
+ SchedWrite.TheDef->getName()); + SchedWrite.TheDef->getName());
} }
@ -729,7 +729,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
continue; continue;
} }
if (AliasDef) if (AliasDef)
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases " PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
"defined for processor " + ProcModel.ModelName + "defined for processor " + ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW."); " Ensure only one SchedAlias exists per RW.");
AliasDef = AliasRW.TheDef; AliasDef = AliasRW.TheDef;
@ -746,7 +746,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
if (AliasDef == (*RAI)->getValueAsDef("ReadType") if (AliasDef == (*RAI)->getValueAsDef("ReadType")
|| SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) { || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
if (ResDef) { 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 " + "SchedRead and its alias on processor " +
ProcModel.ModelName); ProcModel.ModelName);
} }
@ -756,7 +756,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
// TODO: If ProcModel has a base model (previous generation processor), // TODO: If ProcModel has a base model (previous generation processor),
// then call FindReadAdvance recursively with that model here. // then call FindReadAdvance recursively with that model here.
if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") { if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
throw TGError(ProcModel.ModelDef->getLoc(), PrintFatalError(ProcModel.ModelDef->getLoc(),
std::string("Processor does not define resources for ") std::string("Processor does not define resources for ")
+ SchedRead.TheDef->getName()); + SchedRead.TheDef->getName());
} }
@ -1098,7 +1098,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
if (PI->hasInstrSchedModel()) if (PI->hasInstrSchedModel())
EmitProcessorResources(*PI, OS); EmitProcessorResources(*PI, OS);
else if(!PI->ProcResourceDefs.empty()) else if(!PI->ProcResourceDefs.empty())
throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines " PrintFatalError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
"ProcResources without defining WriteRes SchedWriteRes"); "ProcResources without defining WriteRes SchedWriteRes");
// Begin processor itinerary properties // Begin processor itinerary properties