V = BitsInit::get(NewBits);
}
- if (RV->setValue(V))
+ if (RV->setValue(V)) {
+ std::string InitType = "";
+ if (BitsInit *BI = dyn_cast<BitsInit>(V)) {
+ InitType = (Twine("' of type bit initializer with length ") +
+ Twine(BI->getNumBits())).str();
+ }
return Error(Loc, "Value '" + ValName->getAsUnquotedString() + "' of type '"
+ RV->getType()->getAsString() +
"' is incompatible with initializer '" + V->getAsString()
+ + InitType
+ "'");
+ }
return false;
}
// Add all of the values in the superclass into the current def.
for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
- if (AddValue(NewDef, SubMultiClass.RefRange.Start, MCVals[i]))
+ if (AddValue(NewDef, SubMultiClass.RefRange.Start, MCVals[i])) {
+ delete NewDef;
return true;
+ }
CurMC->DefPrototypes.push_back(NewDef);
}
TypedInit *IVal = dyn_cast<TypedInit>(IterVals[i].IterValue);
if (!IVal) {
Error(Loc, "foreach iterator value is untyped");
+ delete IterRec;
return true;
}
if (SetValue(IterRec, Loc, IterVar->getName(),
std::vector<unsigned>(), IVal)) {
Error(Loc, "when instantiating this def");
+ delete IterRec;
return true;
}
}
if (Records.getDef(IterRec->getNameInitAsString())) {
- Error(Loc, "def already exists: " + IterRec->getNameInitAsString());
- return true;
+ // If this record is anonymous, it's no problem, just generate a new name
+ if (IterRec->isAnonymous())
+ IterRec->setName(GetNewAnonymousName());
+ else {
+ Error(Loc, "def already exists: " + IterRec->getNameInitAsString());
+ delete IterRec;
+ return true;
+ }
}
Records.addDef(IterRec);
///
/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
///
-Init *TGParser::ParseOperation(Record *CurRec) {
+Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
switch (Lex.getCode()) {
default:
TokError("unknown operation");
ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
StringRecTy *SType = dyn_cast<StringRecTy>(LHSt->getType());
if (!LType && !SType) {
- TokError("expected list or string type argumnet in unary operator");
+ TokError("expected list or string type argument in unary operator");
return nullptr;
}
}
if (Code == UnOpInit::HEAD
|| Code == UnOpInit::TAIL) {
if (!LHSl && !LHSt) {
- TokError("expected list type argumnet in unary operator");
+ TokError("expected list type argument in unary operator");
return nullptr;
}
assert(LHSt && "expected list type argument in unary operator");
ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
if (!LType) {
- TokError("expected list type argumnet in unary operator");
+ TokError("expected list type argument in unary operator");
return nullptr;
}
if (Code == UnOpInit::HEAD) {
case tgtok::XConcat:
case tgtok::XADD:
+ case tgtok::XAND:
case tgtok::XSRA:
case tgtok::XSRL:
case tgtok::XSHL:
case tgtok::XEq:
+ case tgtok::XListConcat:
case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')'
tgtok::TokKind OpTok = Lex.getCode();
SMLoc OpLoc = Lex.getLoc();
default: llvm_unreachable("Unhandled code!");
case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break;
case tgtok::XADD: Code = BinOpInit::ADD; Type = IntRecTy::get(); break;
+ case tgtok::XAND: Code = BinOpInit::AND; Type = IntRecTy::get(); break;
case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break;
case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break;
case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break;
case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break;
+ case tgtok::XListConcat:
+ Code = BinOpInit::LISTCONCAT;
+ // We don't know the list type until we parse the first argument
+ break;
case tgtok::XStrConcat:
Code = BinOpInit::STRCONCAT;
Type = StringRecTy::get();
}
Lex.Lex(); // eat the ')'
+ // If we are doing !listconcat, we should know the type by now
+ if (OpTok == tgtok::XListConcat) {
+ if (VarInit *Arg0 = dyn_cast<VarInit>(InitList[0]))
+ Type = Arg0->getType();
+ else if (ListInit *Arg0 = dyn_cast<ListInit>(InitList[0]))
+ Type = Arg0->getType();
+ else {
+ InitList[0]->dump();
+ Error(OpLoc, "expected a list");
+ return nullptr;
+ }
+ }
+
// We allow multiple operands to associative operators like !strconcat as
// shorthand for nesting them.
- if (Code == BinOpInit::STRCONCAT) {
+ if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT) {
while (InitList.size() > 2) {
Init *RHS = InitList.pop_back_val();
RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))
}
Lex.Lex(); // eat the ','
- Init *MHS = ParseValue(CurRec);
- if (!MHS) return nullptr;
+ Init *MHS = ParseValue(CurRec, ItemType);
+ if (!MHS)
+ return nullptr;
if (Lex.getCode() != tgtok::comma) {
TokError("expected ',' in ternary operator");
}
Lex.Lex(); // eat the ','
- Init *RHS = ParseValue(CurRec);
- if (!RHS) return nullptr;
+ Init *RHS = ParseValue(CurRec, ItemType);
+ if (!RHS)
+ return nullptr;
if (Lex.getCode() != tgtok::r_paren) {
TokError("expected ')' in binary operator");
/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
+/// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
///
Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
Lex.Lex(); // Skip '#'.
return ParseSimpleValue(CurRec, ItemType, Mode);
case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break;
+ case tgtok::BinaryIntVal: {
+ auto BinaryVal = Lex.getCurBinaryIntVal();
+ SmallVector<Init*, 16> Bits(BinaryVal.second);
+ for (unsigned i = 0, e = BinaryVal.second; i != e; ++i)
+ Bits[i] = BitInit::get(BinaryVal.first & (1LL << i));
+ R = BitsInit::get(Bits);
+ Lex.Lex();
+ break;
+ }
case tgtok::StrVal: {
std::string Val = Lex.getCurStrVal();
Lex.Lex();
SCRef.Rec = Class;
SCRef.TemplateArgs = ValueList;
// Add info about the subclass to NewRec.
- if (AddSubClass(NewRec, SCRef))
+ if (AddSubClass(NewRec, SCRef)) {
+ delete NewRec;
return nullptr;
+ }
if (!CurMultiClass) {
NewRec->resolveReferences();
Records.addDef(NewRec);
}
Lex.Lex(); // eat the '}'
- SmallVector<Init *, 16> NewBits(Vals.size());
+ SmallVector<Init *, 16> NewBits;
+ // As we parse { a, b, ... }, 'a' is the highest bit, but we parse it
+ // first. We'll first read everything in to a vector, then we can reverse
+ // it to get the bits in the correct order for the BitsInit value.
for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ // bits<n> values are allowed to initialize n bits.
+ if (BitsInit *BI = dyn_cast<BitsInit>(Vals[i])) {
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ NewBits.push_back(BI->getBit((e - i) - 1));
+ continue;
+ }
+ // All other values must be convertible to just a single bit.
Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get());
if (!Bit) {
Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+
") is not convertable to a bit");
return nullptr;
}
- NewBits[Vals.size()-i-1] = Bit;
+ NewBits.push_back(Bit);
}
+ std::reverse(NewBits.begin(), NewBits.end());
return BitsInit::get(NewBits);
}
case tgtok::l_square: { // Value ::= '[' ValueList ']'
case tgtok::XCast: // Value ::= !unop '(' Value ')'
case tgtok::XConcat:
case tgtok::XADD:
+ case tgtok::XAND:
case tgtok::XSRA:
case tgtok::XSRL:
case tgtok::XSHL:
case tgtok::XEq:
+ case tgtok::XListConcat:
case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
case tgtok::XIf:
case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- return ParseOperation(CurRec);
+ return ParseOperation(CurRec, ItemType);
}
}
Init *Val = ParseValue(CurRec, Type);
if (!Val ||
SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
- return nullptr;
+ // Return the name, even if an error is thrown. This is so that we can
+ // continue to make some progress, even without the value having been
+ // initialized.
+ return DeclName;
}
return DeclName;
// Parse ObjectName and make a record for it.
Record *CurRec;
+ bool CurRecOwnershipTransferred = false;
Init *Name = ParseObjectName(CurMultiClass);
if (Name)
CurRec = new Record(Name, DefLoc, Records);
if (Records.getDef(CurRec->getNameInitAsString())) {
Error(DefLoc, "def '" + CurRec->getNameInitAsString()
+ "' already defined");
+ delete CurRec;
return true;
}
Records.addDef(CurRec);
+ CurRecOwnershipTransferred = true;
if (ParseObjectBody(CurRec))
return true;
// before this object, instantiated prior to defs derived from this object,
// and this available for indirect name resolution when defs derived from
// this object are instantiated.
- if (ParseObjectBody(CurRec))
+ if (ParseObjectBody(CurRec)) {
+ delete CurRec;
return true;
+ }
// Otherwise, a def inside a multiclass, add it to the multiclass.
for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
== CurRec->getNameInit()) {
Error(DefLoc, "def '" + CurRec->getNameInitAsString() +
"' already defined in this multiclass!");
+ delete CurRec;
return true;
}
CurMultiClass->DefPrototypes.push_back(CurRec);
- } else if (ParseObjectBody(CurRec))
+ CurRecOwnershipTransferred = true;
+ } else if (ParseObjectBody(CurRec)) {
+ delete CurRec;
return true;
+ }
if (!CurMultiClass) // Def's in multiclasses aren't really defs.
// See Record::setName(). This resolve step will see any new name
if (ProcessForeachDefs(CurRec, DefLoc)) {
Error(DefLoc,
"Could not process loops for def" + CurRec->getNameInitAsString());
+ if (!CurRecOwnershipTransferred)
+ delete CurRec;
return true;
}
+ if (!CurRecOwnershipTransferred)
+ delete CurRec;
return false;
}
Error(DefmPrefixRange.Start, "Could not resolve "
+ CurRec->getNameInitAsString() + ":NAME to '"
+ DefmPrefix->getAsUnquotedString() + "'");
+ delete CurRec;
return nullptr;
}
Error(DefmPrefixRange.Start, "def '" + CurRec->getNameInitAsString() +
"' already defined, instantiating defm with subdef '" +
DefProto->getNameInitAsString() + "'");
+ delete CurRec;
return nullptr;
}