/// SetValue -
/// Return true on error, false on success.
bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
- const std::vector<unsigned> &BitList, Init *V) {
+ const std::vector<unsigned> &BitList, Init *V,
+ bool AllowSelfAssignment) {
if (!V) return false;
if (!CurRec) CurRec = &CurMultiClass->Rec;
// in the resolution machinery.
if (BitList.empty())
if (VarInit *VI = dyn_cast<VarInit>(V))
- if (VI->getNameInit() == ValName)
- return false;
+ if (VI->getNameInit() == ValName && !AllowSelfAssignment)
+ return true;
// If we are assigning to a subset of the bits in the value... then we must be
// assigning to a field of BitsRecTy, which must have a BitsInit
for (unsigned i = 0, e = BitList.size(); i != e; ++i) {
unsigned Bit = BitList[i];
if (NewBits[Bit])
- return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
+ return Error(Loc, "Cannot set bit #" + Twine(Bit) + " of value '" +
ValName->getAsUnquotedString() + "' more than once");
NewBits[Bit] = BInit->getBit(i);
}
bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
Record *SC = SubClass.Rec;
// Add all of the values in the subclass into the current class.
- const std::vector<RecordVal> &Vals = SC->getValues();
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (AddValue(CurRec, SubClass.RefRange.Start, Vals[i]))
+ for (const RecordVal &Val : SC->getValues())
+ if (AddValue(CurRec, SubClass.RefRange.Start, Val))
return true;
- const std::vector<Init *> &TArgs = SC->getTemplateArgs();
+ ArrayRef<Init *> TArgs = SC->getTemplateArgs();
// Ensure that an appropriate number of template arguments are specified.
if (TArgs.size() < SubClass.TemplateArgs.size())
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
return Error(SubClass.RefRange.Start,
"Value not specified for template argument #" +
- utostr(i) + " (" + TArgs[i]->getAsUnquotedString() +
+ Twine(i) + " (" + TArgs[i]->getAsUnquotedString() +
") of subclass '" + SC->getNameInitAsString() + "'!");
}
}
// Since everything went well, we can now set the "superclass" list for the
// current record.
- const std::vector<Record*> &SCs = SC->getSuperClasses();
+ ArrayRef<Record *> SCs = SC->getSuperClasses();
ArrayRef<SMRange> SCRanges = SC->getSuperClassRanges();
for (unsigned i = 0, e = SCs.size(); i != e; ++i) {
if (CurRec->isSubClassOf(SCs[i]))
CurMC->DefPrototypes.push_back(std::move(NewDef));
}
- const std::vector<Init *> &SMCTArgs = SMC->Rec.getTemplateArgs();
+ ArrayRef<Init *> SMCTArgs = SMC->Rec.getTemplateArgs();
// Ensure that an appropriate number of template arguments are
// specified.
} else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
return Error(SubMultiClass.RefRange.Start,
"Value not specified for template argument #" +
- utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString() +
+ Twine(i) + " (" + SMCTArgs[i]->getAsUnquotedString() +
") of subclass '" + SMC->Rec.getNameInitAsString() + "'!");
}
}
}
// Process each value.
- for (int64_t i = 0; i < List->getSize(); ++i) {
+ for (unsigned i = 0; i < List->size(); ++i) {
Init *ItemVal = List->resolveListElementReference(*CurRec, nullptr, i);
IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal));
if (ProcessForeachDefs(CurRec, Loc, IterVals))
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);
+ for (IterRecord &IR : IterVals) {
+ VarInit *IterVar = IR.IterVar;
+ TypedInit *IVal = dyn_cast<TypedInit>(IR.IterValue);
if (!IVal)
return Error(Loc, "foreach iterator value is untyped");
return nullptr;
}
- if (LHSl && LHSl->getSize() == 0) {
+ if (LHSl && LHSl->empty()) {
TokError("empty list argument in unary operator");
return nullptr;
}
// 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()+
+ Error(BraceLoc, "Element #" + Twine(i) + " (" + Vals[i]->getAsString() +
") is not convertable to a bit");
return nullptr;
}
if (ItemType) {
ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);
if (!ListType) {
- std::string s;
- raw_string_ostream ss(s);
- ss << "Type mismatch for list, expected list type, got "
- << ItemType->getAsString();
- TokError(ss.str());
+ TokError(Twine("Type mismatch for list, expected list type, got ") +
+ ItemType->getAsString());
return nullptr;
}
GivenListTy = ListType;
// DagArg ::= VARNAME
if (Lex.getCode() == tgtok::VarName) {
// A missing value is treated like '?'.
- Result.push_back(std::make_pair(UnsetInit::get(), Lex.getCurStrVal()));
+ Result.emplace_back(UnsetInit::get(), Lex.getCurStrVal());
Lex.Lex();
} else {
// DagArg ::= Value (':' VARNAME)?
RecTy *ItemType = EltTy;
unsigned int ArgN = 0;
if (ArgsRec && !EltTy) {
- const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs();
+ ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
if (TArgs.empty()) {
TokError("template argument provided to non-template class");
return std::vector<Init*>();
Lex.Lex(); // Eat the comma
if (ArgsRec && !EltTy) {
- const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs();
+ ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
if (ArgN >= TArgs.size()) {
TokError("too many template arguments");
return std::vector<Init*>();
assert(!IterType && "Type already initialized?");
IterType = IntRecTy::get();
std::vector<Init*> Values;
- for (unsigned i = 0, e = Ranges.size(); i != e; ++i)
- Values.push_back(IntInit::get(Ranges[i]));
+ for (unsigned R : Ranges)
+ Values.push_back(IntInit::get(R));
ForeachListValue = ListInit::get(Values, IterType);
}
/// \brief Apply the current let bindings to \a CurRec.
/// \returns true on error, false otherwise.
bool TGParser::ApplyLetStack(Record *CurRec) {
- for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
- for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
- if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
- LetStack[i][j].Bits, LetStack[i][j].Value))
+ for (std::vector<LetRecord> &LetInfo : LetStack)
+ for (LetRecord &LR : LetInfo)
+ if (SetValue(CurRec, LR.Loc, LR.Name, LR.Bits, LR.Value))
return true;
return false;
}
if (!Val) return std::vector<LetRecord>();
// Now that we have everything, add the record.
- Result.push_back(LetRecord(Name, Bits, Val, NameLoc));
+ Result.emplace_back(std::move(Name), std::move(Bits), Val, NameLoc);
if (Lex.getCode() != tgtok::comma)
return Result;
return false;
}
-Record *TGParser::
-InstantiateMulticlassDef(MultiClass &MC,
- Record *DefProto,
- Init *&DefmPrefix,
- SMRange DefmPrefixRange) {
+Record *TGParser::InstantiateMulticlassDef(MultiClass &MC, Record *DefProto,
+ Init *&DefmPrefix,
+ SMRange DefmPrefixRange,
+ ArrayRef<Init *> TArgs,
+ std::vector<Init *> &TemplateVals) {
// We need to preserve DefProto so it can be reused for later
// instantiations, so create a new Record to inherit from it.
}
Init *DefName = DefProto->getNameInit();
-
StringInit *DefNameString = dyn_cast<StringInit>(DefName);
if (DefNameString) {
// though, so that uses in nested multiclass names don't get
// confused.
if (SetValue(CurRec.get(), Ref.RefRange.Start, "NAME",
- std::vector<unsigned>(), DefmPrefix)) {
+ std::vector<unsigned>(), DefmPrefix,
+ /*AllowSelfAssignment*/true)) {
Error(DefmPrefixRange.Start, "Could not resolve " +
CurRec->getNameInitAsString() + ":NAME to '" +
DefmPrefix->getAsUnquotedString() + "'");
RecordVal *DefNameRV = CurRec->getValue("NAME");
CurRec->resolveReferencesTo(DefNameRV);
+ // Check if the name is a complex pattern.
+ // If so, resolve it.
+ DefName = CurRec->getNameInit();
+ DefNameString = dyn_cast<StringInit>(DefName);
+
+ // OK the pattern is more complex than simply using NAME.
+ // Let's use the heavy weaponery.
+ if (!DefNameString) {
+ ResolveMulticlassDefArgs(MC, CurRec.get(), DefmPrefixRange.Start,
+ Lex.getLoc(), TArgs, TemplateVals,
+ false/*Delete args*/);
+ DefName = CurRec->getNameInit();
+ DefNameString = dyn_cast<StringInit>(DefName);
+
+ if (!DefNameString)
+ DefName = DefName->convertInitializerTo(StringRecTy::get());
+
+ // We ran out of options here...
+ DefNameString = dyn_cast<StringInit>(DefName);
+ if (!DefNameString) {
+ PrintFatalError(CurRec->getLoc()[CurRec->getLoc().size() - 1],
+ DefName->getAsUnquotedString() + " is not a string.");
+ return nullptr;
+ }
+
+ CurRec->setName(DefName);
+ }
+
// Now that NAME references are resolved and we're at the top level of
// any multiclass expansions, add the record to the RecordKeeper. If we are
// currently in a multiclass, it means this defm appears inside a
// multiclass and its name won't be fully resolvable until we see
- // the top-level defm. Therefore, we don't add this to the
- // RecordKeeper at this point. If we did we could get duplicate
+ // the top-level defm. Therefore, we don't add this to the
+ // RecordKeeper at this point. If we did we could get duplicate
// defs as more than one probably refers to NAME or some other
// common internal placeholder.
return CurRec.release();
}
-bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC,
- Record *CurRec,
- SMLoc DefmPrefixLoc,
- SMLoc SubClassLoc,
- const std::vector<Init *> &TArgs,
+bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, Record *CurRec,
+ SMLoc DefmPrefixLoc, SMLoc SubClassLoc,
+ ArrayRef<Init *> TArgs,
std::vector<Init *> &TemplateVals,
bool DeleteArgs) {
// Loop over all of the template arguments, setting them to the specified
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
return Error(SubClassLoc, "value not specified for template argument #" +
- utostr(i) + " (" + TArgs[i]->getAsUnquotedString() +
+ Twine(i) + " (" + TArgs[i]->getAsUnquotedString() +
") of multiclassclass '" + MC.Rec.getNameInitAsString() +
"'");
}
std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
// Verify that the correct number of template arguments were specified.
- const std::vector<Init *> &TArgs = MC->Rec.getTemplateArgs();
+ ArrayRef<Init *> TArgs = MC->Rec.getTemplateArgs();
if (TArgs.size() < TemplateVals.size())
return Error(SubClassLoc,
"more template args specified than multiclass expects");
// Loop over all the def's in the multiclass, instantiating each one.
for (const std::unique_ptr<Record> &DefProto : MC->DefPrototypes) {
+ // The record name construction goes as follow:
+ // - If the def name is a string, prepend the prefix.
+ // - If the def name is a more complex pattern, use that pattern.
+ // As a result, the record is instanciated before resolving
+ // arguments, as it would make its name a string.
Record *CurRec = InstantiateMulticlassDef(*MC, DefProto.get(), DefmPrefix,
SMRange(DefmLoc,
- DefmPrefixEndLoc));
+ DefmPrefixEndLoc),
+ TArgs, TemplateVals);
if (!CurRec)
return true;
+ // Now that the record is instanciated, we can resolve arguments.
if (ResolveMulticlassDefArgs(*MC, CurRec, DefmLoc, SubClassLoc,
TArgs, TemplateVals, true/*Delete args*/))
return Error(SubClassLoc, "could not instantiate def");