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,
-set(LLVM_REQUIRES_EH 1)
-
add_llvm_library(LLVMTableGen
Error.cpp
Main.cpp
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);
}
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);
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;
}
LIBRARYNAME = LLVMTableGen
BUILD_ARCHIVE = 1
-REQUIRES_EH = 1
-
include $(LEVEL)/Makefile.common
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();
}
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());
}
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());
}
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());
}
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;
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) {
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) {
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() {
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()
}
/// 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 {
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 {
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 {
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;
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!");
}
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(),
// 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);
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() + "'.");
// 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.
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");
// 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");
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!");
// 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
// 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();
// 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::
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);
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);
}
// 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
return;
}
- throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
+ PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" +
OperandName.str() + "'");
}
// 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!");
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);
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)
// 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 ";
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];
}
}
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
!= 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;
// 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]))
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.
-set(LLVM_REQUIRES_EH 1)
set(LLVM_LINK_COMPONENTS Support)
add_tablegen(llvm-tblgen LLVM
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
+#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
O << Action->getValueAsString("Predicate");
} else {
Action->dump();
- throw "Unknown CCPredicateAction!";
+ PrintFatalError("Unknown CCPredicateAction!");
}
O << ") {\n";
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(";
O << IndentStr << IndentStr << "return false;\n";
} else {
Action->dump();
- throw "Unknown CCAction!";
+ PrintFatalError("Unknown CCAction!");
}
}
}
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;
/// 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()) {
// 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");
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");
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");
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");
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;
}
/// 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;
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;
+ }
}
// 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.
// 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;
}
/// 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);
}
}
- 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;
}
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;
/// 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);
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());
/// 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")) {
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();
/// 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())) {
TP.error("Integer value '" + itostr(II->getValue()) +
"' is out of range for type '" + getEnumName(getType(0)) + "'!");
- return MadeChange;
+ return false;
}
return false;
}
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);
// 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)
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++);
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;
}
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);
//
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() {
/// 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())
// 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());
/* 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);
}
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
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.
}
}
-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;
}
if (Errors)
- throw "pattern conflicts";
+ PrintFatalError("pattern conflicts");
// Revisit instructions with undefined flags and no pattern.
if (Target.guessInstructionProperties()) {
}
}
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
/// 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) {
/// 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;
};
/// 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)
/// 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) {
/// 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
/// 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;
: 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(); }
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,
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;
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";
// 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.
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,
/// 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
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;
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);
}
// 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);
// 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)
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) {
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;
// 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);
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);
}
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);
// 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;
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;
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;
}
// 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());
// 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();
}
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;
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)) {
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!");
}
/// 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
/// 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);
#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;
// 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);
}
}
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;
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);
}
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)
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]));
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));
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 =
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());
}
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);
}
}
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;
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!");
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");
}
}
// 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());
if (CodeGenRegisterClass *RC = Def2RC[Def])
return RC;
- throw TGError(Def->getLoc(), "Not a known RegisterClass!");
+ PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
}
CodeGenSubRegIndex*
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.
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);
}
}
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(
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) {
// 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;
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());
}
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);
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;
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")) {
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(),
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);
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;
}
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();
}
// 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"
: 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];
}
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];
}
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];
}
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];
}
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)
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;
}
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());
// 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
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.
// 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);
// 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);
//
// 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.
//
//===----------------------------------------------------------------------===//
#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"
// 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*/);
}
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() {
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;
#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>
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");
}
}
}
};
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;
#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"
switch (*I) {
default:
- throw "invalid decode table opcode";
+ PrintFatalError("invalid decode table opcode");
case MCD::OPC_ExtractField: {
++I;
unsigned Start = *I++;
#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>
// 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);
#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"
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);
}
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);
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;
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!");
}
}
LEVEL = ../..
TOOLNAME = llvm-tblgen
USEDLIBS = LLVMTableGen.a LLVMSupport.a
-REQUIRES_EH := 1
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
// 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() + "'");
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)
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)
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];
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);
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);
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);
}
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());
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();
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]);
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();
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))
// 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);
}
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;
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);
}
// 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());
}
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;
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);
}
// 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());
}
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