Refactor Multiclass Def Processing

Move the code to instantiate a multiclass def, bind its arguments and
resolve its members into three helper functions.  These will be reused
to support a new kind of multiclass def: a multidef.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141229 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Greene 2011-10-05 22:42:07 +00:00
parent 792860883e
commit e499a2df44
2 changed files with 131 additions and 87 deletions

View File

@ -1919,6 +1919,115 @@ bool TGParser::ParseMultiClass() {
return false;
}
Record *TGParser::
InstantiateMulticlassDef(MultiClass &MC,
Record *DefProto,
const std::string &DefmPrefix,
SMLoc DefmPrefixLoc) {
// Add in the defm name. If the defm prefix is empty, give each
// instantiated def a unique name. Otherwise, if "#NAME#" exists in the
// name, substitute the prefix for #NAME#. Otherwise, use the defm name
// as a prefix.
std::string DefName = DefProto->getName();
if (DefmPrefix.empty()) {
DefName = GetNewAnonymousName();
} else {
std::string::size_type idx = DefName.find("#NAME#");
if (idx != std::string::npos) {
DefName.replace(idx, 6, DefmPrefix);
} else {
// Add the suffix to the defm name to get the new name.
DefName = DefmPrefix + DefName;
}
}
Record *CurRec = new Record(DefName, DefmPrefixLoc, Records);
SubClassReference Ref;
Ref.RefLoc = DefmPrefixLoc;
Ref.Rec = DefProto;
AddSubClass(CurRec, Ref);
return CurRec;
}
bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC,
Record *CurRec,
SMLoc DefmPrefixLoc,
SMLoc SubClassLoc,
const std::vector<std::string> &TArgs,
std::vector<Init *> &TemplateVals,
bool DeleteArgs) {
// Loop over all of the template arguments, setting them to the specified
// value or leaving them as the default if necessary.
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
// Check if a value is specified for this temp-arg.
if (i < TemplateVals.size()) {
// Set it now.
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] + ") of multiclassclass '" +
MC.Rec.getName() + "'");
}
}
return false;
}
bool TGParser::ResolveMulticlassDef(MultiClass &MC,
Record *CurRec,
Record *DefProto,
SMLoc DefmPrefixLoc) {
// If the mdef is inside a 'let' expression, add to each def.
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))
return Error(DefmPrefixLoc, "when instantiating this defm");
// Ensure redefinition doesn't happen.
if (Records.getDef(CurRec->getName()))
return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
"' already defined, instantiating defm with subdef '" +
DefProto->getName() + "'");
// Don't create a top level definition for defm inside multiclasses,
// instead, only update the prototypes and bind the template args
// with the new created definition.
if (CurMultiClass) {
for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
i != e; ++i)
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName())
return Error(DefmPrefixLoc, "defm '" + CurRec->getName() +
"' already defined in this multiclass!");
CurMultiClass->DefPrototypes.push_back(CurRec);
// Copy the template arguments for the multiclass into the new def.
const std::vector<std::string> &TA =
CurMultiClass->Rec.getTemplateArgs();
for (unsigned i = 0, e = TA.size(); i != e; ++i) {
const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
assert(RV && "Template arg doesn't exist?");
CurRec->addValue(*RV);
}
} else {
Records.addDef(CurRec);
}
return false;
}
/// ParseDefm - Parse the instantiation of a multiclass.
///
/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
@ -1968,99 +2077,19 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
Record *DefProto = MC->DefPrototypes[i];
// Add in the defm name. If the defm prefix is empty, give each
// instantiated def a unique name. Otherwise, if "#NAME#" exists in the
// name, substitute the prefix for #NAME#. Otherwise, use the defm name
// as a prefix.
std::string DefName = DefProto->getName();
if (DefmPrefix.empty()) {
DefName = GetNewAnonymousName();
} else {
std::string::size_type idx = DefName.find("#NAME#");
if (idx != std::string::npos) {
DefName.replace(idx, 6, DefmPrefix);
} else {
// Add the suffix to the defm name to get the new name.
DefName = DefmPrefix + DefName;
}
}
Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, DefmPrefixLoc);
Record *CurRec = new Record(DefName, DefmPrefixLoc, Records);
if (ResolveMulticlassDefArgs(*MC, CurRec, DefmPrefixLoc, SubClassLoc,
TArgs, TemplateVals, true/*Delete args*/))
return Error(SubClassLoc, "could not instantiate def");
SubClassReference Ref;
Ref.RefLoc = DefmPrefixLoc;
Ref.Rec = DefProto;
AddSubClass(CurRec, Ref);
// Loop over all of the template arguments, setting them to the specified
// value or leaving them as the default if necessary.
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
// Check if a value is specified for this temp-arg.
if (i < TemplateVals.size()) {
// Set it now.
if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(),
TemplateVals[i]))
return true;
// Resolve it next.
CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
// 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] + ") of multiclassclass '" +
MC->Rec.getName() + "'");
}
}
// If the mdef is inside a 'let' expression, add to each def.
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)) {
Error(DefmPrefixLoc, "when instantiating this defm");
return true;
}
// Ensure redefinition doesn't happen.
if (Records.getDef(CurRec->getName()))
return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
"' already defined, instantiating defm with subdef '" +
DefProto->getName() + "'");
// Don't create a top level definition for defm inside multiclasses,
// instead, only update the prototypes and bind the template args
// with the new created definition.
if (CurMultiClass) {
for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
i != e; ++i) {
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
Error(DefmPrefixLoc, "defm '" + CurRec->getName() +
"' already defined in this multiclass!");
return 0;
}
}
CurMultiClass->DefPrototypes.push_back(CurRec);
// Copy the template arguments for the multiclass into the new def.
const std::vector<std::string> &TA =
CurMultiClass->Rec.getTemplateArgs();
for (unsigned i = 0, e = TA.size(); i != e; ++i) {
const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
assert(RV && "Template arg doesn't exist?");
CurRec->addValue(*RV);
}
} else {
Records.addDef(CurRec);
}
if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmPrefixLoc))
return Error(SubClassLoc, "could not instantiate def");
NewRecDefs.push_back(CurRec);
}
if (Lex.getCode() != tgtok::comma) break;
Lex.Lex(); // eat ','.

View File

@ -83,6 +83,21 @@ private: // Parser methods.
bool ParseObject(MultiClass *MC);
bool ParseClass();
bool ParseMultiClass();
Record *InstantiateMulticlassDef(MultiClass &MC,
Record *DefProto,
const std::string &DefmPrefix,
SMLoc DefmPrefixLoc);
bool ResolveMulticlassDefArgs(MultiClass &MC,
Record *DefProto,
SMLoc DefmPrefixLoc,
SMLoc SubClassLoc,
const std::vector<std::string> &TArgs,
std::vector<Init *> &TemplateVals,
bool DeleteArgs);
bool ResolveMulticlassDef(MultiClass &MC,
Record *CurRec,
Record *DefProto,
SMLoc DefmPrefixLoc);
bool ParseDefm(MultiClass *CurMultiClass);
bool ParseDef(MultiClass *CurMultiClass);
bool ParseTopLevelLet(MultiClass *CurMultiClass);