//===----------------------------------------------------------------------===//
#include "TGParser.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
MC->dump();
errs() << "Template args:\n";
- for (std::vector<Init *>::const_iterator i = TemplateArgs.begin(),
- iend = TemplateArgs.end();
- i != iend;
- ++i) {
- (*i)->dump();
- }
+ for (Init *TA : TemplateArgs)
+ TA->dump();
}
} // end namespace llvm
RecordVal *RV = CurRec->getValue(ValName);
if (!RV)
- return Error(Loc, "Value '" + ValName->getAsUnquotedString()
- + "' unknown!");
+ return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
+ "' unknown!");
// Do not allow assignments like 'X = X'. This will just cause infinite loops
// in the resolution machinery.
if (!BitList.empty()) {
BitsInit *CurVal = dyn_cast<BitsInit>(RV->getValue());
if (!CurVal)
- return Error(Loc, "Value '" + ValName->getAsUnquotedString()
- + "' is not a bits type");
+ return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
+ "' is not a bits type");
// Convert the incoming value to a bits type of the appropriate size...
Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size()));
- if (!BI) {
+ if (!BI)
return Error(Loc, "Initializer is not compatible with bit range");
- }
// We should have a BitsInit type now.
- BitsInit *BInit = dyn_cast<BitsInit>(BI);
- assert(BInit != nullptr);
+ BitsInit *BInit = cast<BitsInit>(BI);
SmallVector<Init *, 16> NewBits(CurVal->getNumBits());
V = BitsInit::get(NewBits);
}
- if (RV->setValue(V))
- return Error(Loc, "Value '" + ValName->getAsUnquotedString() + "' of type '"
- + RV->getType()->getAsString() +
- "' is incompatible with initializer '" + V->getAsString()
- + "'");
+ 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;
}
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
return Error(SubClass.RefRange.Start,
- "Value not specified for template argument #"
- + utostr(i) + " (" + TArgs[i]->getAsUnquotedString()
- + ") of subclass '" + SC->getNameInitAsString() + "'!");
+ "Value not specified for template argument #" +
+ utostr(i) + " (" + TArgs[i]->getAsUnquotedString() +
+ ") of subclass '" + SC->getNameInitAsString() + "'!");
}
}
MultiClass *SMC = SubMultiClass.MC;
Record *CurRec = &CurMC->Rec;
- const std::vector<RecordVal> &MCVals = CurRec->getValues();
-
// Add all of the values in the subclass into the current class.
- const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
- for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
- if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVals[i]))
+ for (const auto &SMCVal : SMC->Rec.getValues())
+ if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVal))
return true;
- int newDefStart = CurMC->DefPrototypes.size();
+ unsigned newDefStart = CurMC->DefPrototypes.size();
// Add all of the defs in the subclass into the current multiclass.
- for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(),
- iend = SMC->DefPrototypes.end();
- i != iend;
- ++i) {
+ for (const std::unique_ptr<Record> &R : SMC->DefPrototypes) {
// Clone the def and add it to the current multiclass
- Record *NewDef = new Record(**i);
+ auto NewDef = make_unique<Record>(*R);
// 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]))
+ for (const auto &MCVal : CurRec->getValues())
+ if (AddValue(NewDef.get(), SubMultiClass.RefRange.Start, MCVal))
return true;
- CurMC->DefPrototypes.push_back(NewDef);
+ CurMC->DefPrototypes.push_back(std::move(NewDef));
}
const std::vector<Init *> &SMCTArgs = SMC->Rec.getTemplateArgs();
// If a value is specified for this template arg, set it in the
// new defs now.
- for (MultiClass::RecordVector::iterator j =
- CurMC->DefPrototypes.begin() + newDefStart,
- jend = CurMC->DefPrototypes.end();
- j != jend;
- ++j) {
- Record *Def = *j;
-
- if (SetValue(Def, SubMultiClass.RefRange.Start, SMCTArgs[i],
+ for (const auto &Def :
+ makeArrayRef(CurMC->DefPrototypes).slice(newDefStart)) {
+ if (SetValue(Def.get(), SubMultiClass.RefRange.Start, SMCTArgs[i],
std::vector<unsigned>(),
SubMultiClass.TemplateArgs[i]))
return true;
}
} else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
return Error(SubMultiClass.RefRange.Start,
- "Value not specified for template argument #"
- + utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString()
- + ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!");
+ "Value not specified for template argument #" +
+ utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString() +
+ ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!");
}
}
// This is the bottom of the recursion. We have all of the iterator values
// for this point in the iteration space. Instantiate a new record to
// reflect this combination of values.
- Record *IterRec = new Record(*CurRec);
+ auto IterRec = make_unique<Record>(*CurRec);
// Set the iterator values now.
for (unsigned i = 0, e = IterVals.size(); i != e; ++i) {
VarInit *IterVar = IterVals[i].IterVar;
TypedInit *IVal = dyn_cast<TypedInit>(IterVals[i].IterValue);
- if (!IVal) {
- Error(Loc, "foreach iterator value is untyped");
- return true;
- }
+ if (!IVal)
+ return Error(Loc, "foreach iterator value is untyped");
IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false));
- if (SetValue(IterRec, Loc, IterVar->getName(),
- std::vector<unsigned>(), IVal)) {
- Error(Loc, "when instantiating this def");
- return true;
- }
+ if (SetValue(IterRec.get(), Loc, IterVar->getName(),
+ std::vector<unsigned>(), IVal))
+ return Error(Loc, "when instantiating this def");
// Resolve it next.
IterRec->resolveReferencesTo(IterRec->getValue(IterVar->getName()));
}
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())
+ return Error(Loc, "def already exists: " +IterRec->getNameInitAsString());
+
+ IterRec->setName(GetNewAnonymousName());
}
- Records.addDef(IterRec);
- IterRec->resolveReferences();
+ Record *IterRecSave = IterRec.get(); // Keep a copy before release.
+ Records.addDef(std::move(IterRec));
+ IterRecSave->resolveReferences();
return false;
}
/// GetNewAnonymousName - Generate a unique anonymous name that can be used as
/// an identifier.
std::string TGParser::GetNewAnonymousName() {
- unsigned Tmp = AnonCounter++; // MSVC2012 ICEs without this.
- return "anonymous_" + utostr(Tmp);
+ return "anonymous_" + utostr(AnonCounter++);
}
/// ParseObjectName - If an object name is specified, return it. Otherwise,
return nullptr;
}
- MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
+ MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get();
if (!Result)
TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
Lex.Lex();
// Add to the range.
- if (Start < End) {
+ if (Start < End)
for (; Start <= End; ++Start)
Ranges.push_back(Start);
- } else {
+ else
for (; Start >= End; --Start)
Ranges.push_back(Start);
- }
return false;
}
}
// If this is in a foreach loop, make sure it's not a loop iterator
- for (LoopVector::iterator i = Loops.begin(), iend = Loops.end();
- i != iend;
- ++i) {
- VarInit *IterVar = dyn_cast<VarInit>(i->IterVar);
+ for (const auto &L : Loops) {
+ VarInit *IterVar = dyn_cast<VarInit>(L.IterVar);
if (IterVar && IterVar->getName() == Name)
return IterVar;
}
Error(NameLoc, "Variable not defined: '" + Name + "'");
return nullptr;
}
-
+
return StringInit::get(Name);
}
///
/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
///
-Init *TGParser::ParseOperation(Record *CurRec) {
+Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
switch (Lex.getCode()) {
default:
TokError("unknown operation");
Init *LHS = ParseValue(CurRec);
if (!LHS) return nullptr;
- if (Code == UnOpInit::HEAD
- || Code == UnOpInit::TAIL
- || Code == UnOpInit::EMPTY) {
+ if (Code == UnOpInit::HEAD ||
+ Code == UnOpInit::TAIL ||
+ Code == UnOpInit::EMPTY) {
ListInit *LHSl = dyn_cast<ListInit>(LHS);
StringInit *LHSs = dyn_cast<StringInit>(LHS);
TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
}
}
- if (Code == UnOpInit::HEAD
- || Code == UnOpInit::TAIL) {
+ if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
if (!LHSl && !LHSt) {
TokError("expected list type argument in unary operator");
return nullptr;
}
- if (LHSl && LHSl->getSize() == 0) {
+ if (LHSl && LHSl->empty()) {
TokError("empty list argument in unary operator");
return nullptr;
}
TokError("untyped list element in unary operator");
return nullptr;
}
- if (Code == UnOpInit::HEAD) {
- Type = Itemt->getType();
- } else {
- Type = ListRecTy::get(Itemt->getType());
- }
+ Type = (Code == UnOpInit::HEAD) ? Itemt->getType()
+ : ListRecTy::get(Itemt->getType());
} else {
assert(LHSt && "expected list type argument in unary operator");
ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
TokError("expected list type argument in unary operator");
return nullptr;
}
- if (Code == UnOpInit::HEAD) {
- Type = LType->getElementType();
- } else {
- Type = LType;
- }
+ Type = (Code == UnOpInit::HEAD) ? LType->getElementType() : LType;
}
}
}
case tgtok::XConcat:
case tgtok::XADD:
+ case tgtok::XAND:
case tgtok::XSRA:
case tgtok::XSRL:
case tgtok::XSHL:
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;
}
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");
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();
SMLoc EndLoc = Lex.getLoc();
// Create the new record, set it as CurRec temporarily.
- Record *NewRec = new Record(GetNewAnonymousName(), NameLoc, Records,
- /*IsAnonymous=*/true);
+ auto NewRecOwner = llvm::make_unique<Record>(GetNewAnonymousName(), NameLoc,
+ Records, /*IsAnonymous=*/true);
+ Record *NewRec = NewRecOwner.get(); // Keep a copy since we may release.
SubClassReference SCRef;
SCRef.RefRange = SMRange(NameLoc, EndLoc);
SCRef.Rec = Class;
// Add info about the subclass to NewRec.
if (AddSubClass(NewRec, SCRef))
return nullptr;
+
if (!CurMultiClass) {
NewRec->resolveReferences();
- Records.addDef(NewRec);
+ Records.addDef(std::move(NewRecOwner));
} else {
+ // This needs to get resolved once the multiclass template arguments are
+ // known before any use.
+ NewRec->setResolveFirst(true);
// Otherwise, we're inside a multiclass, add it to the multiclass.
- CurMultiClass->DefPrototypes.push_back(NewRec);
+ CurMultiClass->DefPrototypes.push_back(std::move(NewRecOwner));
// Copy the template arguments for the multiclass into the def.
- const std::vector<Init *> &TArgs =
- CurMultiClass->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArg);
assert(RV && "Template arg doesn't exist?");
NewRec->addValue(*RV);
}
}
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) {
+ // FIXME: The following two loops would not be duplicated
+ // if the API was a little more orthogonal.
+
+ // 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;
+ }
+ // bits<n> can also come from variable initializers.
+ if (VarInit *VI = dyn_cast<VarInit>(Vals[i])) {
+ if (BitsRecTy *BitsRec = dyn_cast<BitsRecTy>(VI->getType())) {
+ for (unsigned i = 0, e = BitsRec->getNumBits(); i != e; ++i)
+ NewBits.push_back(VI->getBit((e - i) - 1));
+ continue;
+ }
+ // Fallthrough to try convert this to a bit.
+ }
+ // 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 ']'
// Check elements
RecTy *EltTy = nullptr;
- for (std::vector<Init *>::iterator i = Vals.begin(), ie = Vals.end();
- i != ie;
- ++i) {
- TypedInit *TArg = dyn_cast<TypedInit>(*i);
+ for (Init *V : Vals) {
+ TypedInit *TArg = dyn_cast<TypedInit>(V);
if (!TArg) {
TokError("Untyped list element");
return nullptr;
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::XIf:
case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- return ParseOperation(CurRec);
+ return ParseOperation(CurRec, ItemType);
}
}
Error(PasteLoc, "LHS of paste is not typed!");
return nullptr;
}
-
+
if (LHS->getType() != StringRecTy::get()) {
LHS = UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get());
}
// These are all of the tokens that can begin an object body.
// Some of these can also begin values but we disallow those cases
// because they are unlikely to be useful.
-
+
// Trailing paste, concat with an empty string.
RHS = StringInit::get("");
break;
if (RHS->getType() != StringRecTy::get()) {
RHS = UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get());
}
-
+
break;
}
unsigned int ArgN = 0;
if (ArgsRec && !EltTy) {
const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs();
- if (!TArgs.size()) {
+ if (TArgs.empty()) {
TokError("template argument provided to non-template class");
return std::vector<Init*>();
}
Lex.Lex();
if (ParsingTemplateArgs) {
- if (CurRec) {
+ if (CurRec)
DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
- } else {
+ else
assert(CurMultiClass);
- }
if (CurMultiClass)
DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName,
"::");
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;
Lex.Lex(); // Eat the 'def' token.
// Parse ObjectName and make a record for it.
- Record *CurRec;
+ std::unique_ptr<Record> CurRecOwner;
Init *Name = ParseObjectName(CurMultiClass);
if (Name)
- CurRec = new Record(Name, DefLoc, Records);
+ CurRecOwner = make_unique<Record>(Name, DefLoc, Records);
else
- CurRec = new Record(GetNewAnonymousName(), DefLoc, Records,
- /*IsAnonymous=*/true);
+ CurRecOwner = llvm::make_unique<Record>(GetNewAnonymousName(), DefLoc,
+ Records, /*IsAnonymous=*/true);
+ Record *CurRec = CurRecOwner.get(); // Keep a copy since we may release.
if (!CurMultiClass && Loops.empty()) {
// Top-level def definition.
// Ensure redefinition doesn't happen.
- if (Records.getDef(CurRec->getNameInitAsString())) {
- Error(DefLoc, "def '" + CurRec->getNameInitAsString()
- + "' already defined");
- return true;
- }
- Records.addDef(CurRec);
+ if (Records.getDef(CurRec->getNameInitAsString()))
+ return Error(DefLoc, "def '" + CurRec->getNameInitAsString()+
+ "' already defined");
+ Records.addDef(std::move(CurRecOwner));
if (ParseObjectBody(CurRec))
return true;
return true;
// Otherwise, a def inside a multiclass, add it to the multiclass.
- for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
- if (CurMultiClass->DefPrototypes[i]->getNameInit()
- == CurRec->getNameInit()) {
- Error(DefLoc, "def '" + CurRec->getNameInitAsString() +
- "' already defined in this multiclass!");
- return true;
- }
- CurMultiClass->DefPrototypes.push_back(CurRec);
- } else if (ParseObjectBody(CurRec))
+ for (const auto &Proto : CurMultiClass->DefPrototypes)
+ if (Proto->getNameInit() == CurRec->getNameInit())
+ return Error(DefLoc, "def '" + CurRec->getNameInitAsString() +
+ "' already defined in this multiclass!");
+ CurMultiClass->DefPrototypes.push_back(std::move(CurRecOwner));
+ } else if (ParseObjectBody(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 (CurMultiClass) {
// Copy the template arguments for the multiclass into the def.
- const std::vector<Init *> &TArgs =
- CurMultiClass->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArg);
assert(RV && "Template arg doesn't exist?");
CurRec->addValue(*RV);
}
}
- if (ProcessForeachDefs(CurRec, DefLoc)) {
- Error(DefLoc,
- "Could not process loops for def" + CurRec->getNameInitAsString());
- return true;
- }
+ if (ProcessForeachDefs(CurRec, DefLoc))
+ return Error(DefLoc, "Could not process loops for def" +
+ CurRec->getNameInitAsString());
return false;
}
// FOREACH Declaration IN Object
if (ParseObject(CurMultiClass))
return true;
- }
- else {
+ } else {
SMLoc BraceLoc = Lex.getLoc();
// Otherwise, this is a group foreach.
Lex.Lex(); // eat the '{'.
if (CurRec->getValues().size() > 1 || // Account for NAME.
!CurRec->getSuperClasses().empty() ||
!CurRec->getTemplateArgs().empty())
- return TokError("Class '" + CurRec->getNameInitAsString()
- + "' already defined");
+ return TokError("Class '" + CurRec->getNameInitAsString() +
+ "' already defined");
} else {
// If this is the first reference to this class, create and add it.
- CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records);
- Records.addClass(CurRec);
+ auto NewRec =
+ llvm::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records);
+ CurRec = NewRec.get();
+ Records.addClass(std::move(NewRec));
}
Lex.Lex(); // eat the name.
// Add this entry to the let stack.
std::vector<LetRecord> LetInfo = ParseLetList();
if (LetInfo.empty()) return true;
- LetStack.push_back(LetInfo);
+ LetStack.push_back(std::move(LetInfo));
if (Lex.getCode() != tgtok::In)
return TokError("expected 'in' at end of top-level 'let'");
return TokError("expected identifier after multiclass for name");
std::string Name = Lex.getCurStrVal();
- if (MultiClasses.count(Name))
+ auto Result =
+ MultiClasses.insert(std::make_pair(Name,
+ llvm::make_unique<MultiClass>(Name, Lex.getLoc(),Records)));
+
+ if (!Result.second)
return TokError("multiclass '" + Name + "' already defined");
- CurMultiClass = MultiClasses[Name] = new MultiClass(Name,
- Lex.getLoc(), Records);
+ CurMultiClass = Result.first->second.get();
Lex.Lex(); // Eat the identifier.
// If there are template args, parse them.
if (Lex.getCode() != tgtok::l_brace) {
if (!inherits)
return TokError("expected '{' in multiclass definition");
- else if (Lex.getCode() != tgtok::semi)
+ if (Lex.getCode() != tgtok::semi)
return TokError("expected ';' in multiclass definition");
- else
- Lex.Lex(); // eat the ';'.
+ Lex.Lex(); // eat the ';'.
} else {
if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
return TokError("multiclass must contain at least one def");
while (Lex.getCode() != tgtok::r_brace) {
switch (Lex.getCode()) {
- default:
- return TokError("expected 'let', 'def' or 'defm' in multiclass body");
- case tgtok::Let:
- case tgtok::Def:
- case tgtok::Defm:
- case tgtok::Foreach:
- if (ParseObject(CurMultiClass))
- return true;
- break;
+ default:
+ return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+ case tgtok::Let:
+ case tgtok::Def:
+ case tgtok::Defm:
+ case tgtok::Foreach:
+ if (ParseObject(CurMultiClass))
+ return true;
+ break;
}
}
Lex.Lex(); // eat the '}'.
// Make a trail of SMLocs from the multiclass instantiations.
SmallVector<SMLoc, 4> Locs(1, DefmPrefixRange.Start);
Locs.append(DefProto->getLoc().begin(), DefProto->getLoc().end());
- Record *CurRec = new Record(DefName, Locs, Records, IsAnonymous);
+ auto CurRec = make_unique<Record>(DefName, Locs, Records, IsAnonymous);
SubClassReference Ref;
Ref.RefRange = DefmPrefixRange;
Ref.Rec = DefProto;
- AddSubClass(CurRec, Ref);
+ AddSubClass(CurRec.get(), Ref);
// Set the value for NAME. We don't resolve references to it 'til later,
// though, so that uses in nested multiclass names don't get
// confused.
- if (SetValue(CurRec, Ref.RefRange.Start, "NAME", std::vector<unsigned>(),
- DefmPrefix)) {
- Error(DefmPrefixRange.Start, "Could not resolve "
- + CurRec->getNameInitAsString() + ":NAME to '"
- + DefmPrefix->getAsUnquotedString() + "'");
+ if (SetValue(CurRec.get(), Ref.RefRange.Start, "NAME",
+ std::vector<unsigned>(), DefmPrefix)) {
+ Error(DefmPrefixRange.Start, "Could not resolve " +
+ CurRec->getNameInitAsString() + ":NAME to '" +
+ DefmPrefix->getAsUnquotedString() + "'");
return nullptr;
}
return nullptr;
}
- Records.addDef(CurRec);
+ Record *CurRecSave = CurRec.get(); // Keep a copy before we release.
+ Records.addDef(std::move(CurRec));
+ return CurRecSave;
}
- return CurRec;
+ // FIXME This is bad but the ownership transfer to caller is pretty messy.
+ // The unique_ptr in this function at least protects the exits above.
+ return CurRec.release();
}
bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC,
if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(),
TemplateVals[i]))
return true;
-
+
// Resolve it next.
CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
if (DeleteArgs)
// Now remove it.
CurRec->removeValue(TArgs[i]);
-
+
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
- return Error(SubClassLoc, "value not specified for template argument #"+
- utostr(i) + " (" + TArgs[i]->getAsUnquotedString()
- + ") of multiclassclass '" + MC.Rec.getNameInitAsString()
- + "'");
+ return Error(SubClassLoc, "value not specified for template argument #" +
+ utostr(i) + " (" + TArgs[i]->getAsUnquotedString() +
+ ") of multiclassclass '" + MC.Rec.getNameInitAsString() +
+ "'");
}
}
return false;
// with the new created definition.
if (!CurMultiClass)
return false;
- for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
- i != e; ++i)
- if (CurMultiClass->DefPrototypes[i]->getNameInit()
- == CurRec->getNameInit())
+ for (const auto &Proto : CurMultiClass->DefPrototypes)
+ if (Proto->getNameInit() == CurRec->getNameInit())
return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() +
"' already defined in this multiclass!");
- CurMultiClass->DefPrototypes.push_back(CurRec);
+ CurMultiClass->DefPrototypes.push_back(std::unique_ptr<Record>(CurRec));
// Copy the template arguments for the multiclass into the new def.
- const std::vector<Init *> &TA =
- CurMultiClass->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TA.size(); i != e; ++i) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
+ for (Init * TA : CurMultiClass->Rec.getTemplateArgs()) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TA);
assert(RV && "Template arg doesn't exist?");
CurRec->addValue(*RV);
}
// To instantiate a multiclass, we need to first get the multiclass, then
// instantiate each def contained in the multiclass with the SubClassRef
// template parameters.
- MultiClass *MC = MultiClasses[Ref.Rec->getName()];
+ MultiClass *MC = MultiClasses[Ref.Rec->getName()].get();
assert(MC && "Didn't lookup multiclass correctly?");
std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
"more template args specified than multiclass expects");
// Loop over all the def's in the multiclass, instantiating each one.
- for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
- Record *DefProto = MC->DefPrototypes[i];
-
- Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix,
+ for (const std::unique_ptr<Record> &DefProto : MC->DefPrototypes) {
+ Record *CurRec = InstantiateMulticlassDef(*MC, DefProto.get(), DefmPrefix,
SMRange(DefmLoc,
DefmPrefixEndLoc));
if (!CurRec)
TArgs, TemplateVals, true/*Delete args*/))
return Error(SubClassLoc, "could not instantiate def");
- if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmLoc))
+ if (ResolveMulticlassDef(*MC, CurRec, DefProto.get(), DefmLoc))
return Error(SubClassLoc, "could not instantiate def");
+ // Defs that can be used by other definitions should be fully resolved
+ // before any use.
+ if (DefProto->isResolveFirst() && !CurMultiClass) {
+ CurRec->resolveReferences();
+ CurRec->setResolveFirst(false);
+ }
NewRecDefs.push_back(CurRec);
}
// Get the expanded definition prototypes and teach them about
// the record values the current class to inherit has
- for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
- Record *CurRec = NewRecDefs[i];
-
+ for (Record *CurRec : NewRecDefs) {
// Add it.
if (AddSubClass(CurRec, SubClass))
return true;
}
if (!CurMultiClass)
- for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
+ for (Record *CurRec : NewRecDefs)
// See Record::setName(). This resolve step will see any new
// name for the def that might have been created when resolving
// inheritance, values and arguments above.
- NewRecDefs[i]->resolveReferences();
+ CurRec->resolveReferences();
if (Lex.getCode() != tgtok::semi)
return TokError("expected ';' at end of defm");