1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

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. 

llvm-svn: 166712
This commit is contained in:
Joerg Sonnenberger 2012-10-25 20:33:17 +00:00
parent d69b3afa22
commit 839f6c1a88
32 changed files with 488 additions and 452 deletions

View File

@ -19,26 +19,13 @@
namespace llvm {
class TGError {
SmallVector<SMLoc, 4> Locs;
std::string Message;
public:
TGError(ArrayRef<SMLoc> locs, const std::string &message)
: Locs(locs.begin(), locs.end()), Message(message) {}
ArrayRef<SMLoc> getLoc() const { return Locs; }
const std::string &getMessage() const { return Message; }
};
void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg);
void PrintWarning(const char *Loc, const Twine &Msg);
void PrintWarning(const Twine &Msg);
void PrintWarning(const TGError &Warning);
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
void PrintError(const char *Loc, const Twine &Msg);
void PrintError(const Twine &Msg);
void PrintError(const TGError &Error);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const std::string &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc,

View File

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

View File

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

View File

@ -80,56 +80,46 @@ namespace llvm {
int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
RecordKeeper Records;
try {
// Parse the input file.
OwningPtr<MemoryBuffer> File;
if (error_code ec =
MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) {
errs() << "Could not open input file '" << InputFilename << "': "
<< ec.message() <<"\n";
return 1;
}
MemoryBuffer *F = File.take();
// Tell SrcMgr about this buffer, which is what TGParser will pick up.
SrcMgr.AddNewSourceBuffer(F, SMLoc());
// Record the location of the include directory so that the lexer can find
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
TGParser Parser(SrcMgr, Records);
if (Parser.ParseFile())
return 1;
std::string Error;
tool_output_file Out(OutputFilename.c_str(), Error);
if (!Error.empty()) {
errs() << argv0 << ": error opening " << OutputFilename
<< ":" << Error << "\n";
return 1;
}
if (!DependFilename.empty())
if (int Ret = createDependencyFile(Parser, argv0))
return Ret;
if (MainFn(Out.os(), Records))
return 1;
// Declare success.
Out.keep();
return 0;
} catch (const TGError &Error) {
PrintError(Error);
} catch (const std::string &Error) {
PrintError(Error);
} catch (const char *Error) {
PrintError(Error);
} catch (...) {
errs() << argv0 << ": Unknown unexpected exception occurred.\n";
// Parse the input file.
OwningPtr<MemoryBuffer> File;
if (error_code ec =
MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) {
errs() << "Could not open input file '" << InputFilename << "': "
<< ec.message() <<"\n";
return 1;
}
MemoryBuffer *F = File.take();
// Tell SrcMgr about this buffer, which is what TGParser will pick up.
SrcMgr.AddNewSourceBuffer(F, SMLoc());
// Record the location of the include directory so that the lexer can find
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
TGParser Parser(SrcMgr, Records);
if (Parser.ParseFile())
return 1;
std::string Error;
tool_output_file Out(OutputFilename.c_str(), Error);
if (!Error.empty()) {
errs() << argv0 << ": error opening " << OutputFilename
<< ":" << Error << "\n";
return 1;
}
if (!DependFilename.empty()) {
if (int Ret = createDependencyFile(Parser, argv0))
return Ret;
}
if (MainFn(Out.os(), Records))
return 1;
// Declare success.
Out.keep();
return 0;
return 1;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -117,11 +117,9 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);
// FIXME: As long as we are using exceptions, might as well drop this to the
// actual conflict site.
if (Tables.hasConflicts())
throw TGError(Target.getTargetRecord()->getLoc(),
"Primary decode conflict");
PrintFatalError(Target.getTargetRecord()->getLoc(),
"Primary decode conflict");
Tables.emit(OS);
return;

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@
#include "CodeGenTarget.h"
#include "SequenceToOffsetTable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
@ -249,7 +250,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
if (EVT(VT).isInteger()) {
unsigned BitWidth = EVT(VT).getSizeInBits();
switch (BitWidth) {
default: throw "unhandled integer type width in intrinsic!";
default: PrintFatalError("unhandled integer type width in intrinsic!");
case 1: return Sig.push_back(IIT_I1);
case 8: return Sig.push_back(IIT_I8);
case 16: return Sig.push_back(IIT_I16);
@ -259,7 +260,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
}
switch (VT) {
default: throw "unhandled MVT in intrinsic!";
default: PrintFatalError("unhandled MVT in intrinsic!");
case MVT::f32: return Sig.push_back(IIT_F32);
case MVT::f64: return Sig.push_back(IIT_F64);
case MVT::Metadata: return Sig.push_back(IIT_METADATA);
@ -328,7 +329,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
if (EVT(VT).isVector()) {
EVT VVT = VT;
switch (VVT.getVectorNumElements()) {
default: throw "unhandled vector type width in intrinsic!";
default: PrintFatalError("unhandled vector type width in intrinsic!");
case 2: Sig.push_back(IIT_V2); break;
case 4: Sig.push_back(IIT_V4); break;
case 8: Sig.push_back(IIT_V8); break;
@ -692,8 +693,8 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
Ints[i].EnumName)).second)
throw "Intrinsic '" + Ints[i].TheDef->getName() +
"': duplicate GCC builtin name!";
PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
"': duplicate GCC builtin name!");
}
}

View File

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

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

View File

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

View File

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

View File

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