/// ParseObjectName - If an object name is specified, return it. Otherwise,
/// return an anonymous name.
-/// ObjectName ::= ID
+/// ObjectName ::= Value [ '#' Value ]*
/// ObjectName ::= /*empty*/
///
-std::string TGParser::ParseObjectName() {
- if (Lex.getCode() != tgtok::Id)
- return GetNewAnonymousName();
+Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {
+ switch (Lex.getCode()) {
+ case tgtok::colon:
+ case tgtok::semi:
+ case tgtok::l_brace:
+ // 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.
+ return StringInit::get(GetNewAnonymousName());
+ break;
+ default:
+ break;
+ }
- std::string Ret = Lex.getCurStrVal();
- Lex.Lex();
- return Ret;
-}
+ Record *CurRec = 0;
+ if (CurMultiClass)
+ CurRec = &CurMultiClass->Rec;
+
+ RecTy *Type = 0;
+ if (CurRec) {
+ const TypedInit *CurRecName =
+ dynamic_cast<const TypedInit *>(CurRec->getNameInit());
+ if (!CurRecName) {
+ TokError("Record name is not typed!");
+ return 0;
+ }
+ Type = CurRecName->getType();
+ }
+ return ParseValue(CurRec, Type, ParseNameMode);
+}
/// ParseClassID - Parse and resolve a reference to a class name. This returns
/// null on error.
/// IDValue ::= ID [multiclass template argument]
/// IDValue ::= ID [def name]
///
-Init *TGParser::ParseIDValue(Record *CurRec) {
+Init *TGParser::ParseIDValue(Record *CurRec, IDParseMode Mode) {
assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue");
std::string Name = Lex.getCurStrVal();
SMLoc Loc = Lex.getLoc();
/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
/// has already been read.
Init *TGParser::ParseIDValue(Record *CurRec,
- const std::string &Name, SMLoc NameLoc) {
+ const std::string &Name, SMLoc NameLoc,
+ IDParseMode Mode) {
if (CurRec) {
if (const RecordVal *RV = CurRec->getValue(Name))
return VarInit::get(Name, RV->getType());
}
}
+ if (Mode == ParseNameMode)
+ return StringInit::get(Name);
+
if (Record *D = Records.getDef(Name))
return DefInit::get(D);
- Error(NameLoc, "Variable not defined: '" + Name + "'");
- return 0;
+ if (Mode == ParseValueMode) {
+ Error(NameLoc, "Variable not defined: '" + Name + "'");
+ return 0;
+ }
+
+ return StringInit::get(Name);
}
/// ParseOperation - Parse an operator. This returns null on error.
/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
///
-Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) {
+Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
+ IDParseMode Mode) {
Init *R = 0;
switch (Lex.getCode()) {
default: TokError("Unknown token when parsing a value"); break;
+ case tgtok::paste:
+ // This is a leading paste operation. This is deprecated but
+ // still exists in some .td files. Ignore it.
+ Lex.Lex(); // Skip '#'.
+ return ParseSimpleValue(CurRec, ItemType, Mode);
+ break;
case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break;
case tgtok::StrVal: {
std::string Val = Lex.getCurStrVal();
SMLoc NameLoc = Lex.getLoc();
std::string Name = Lex.getCurStrVal();
if (Lex.Lex() != tgtok::less) // consume the Id.
- return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue
+ return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue
// Value ::= ID '<' ValueListNE '>'
if (Lex.Lex() == tgtok::greater) {
/// ValueSuffix ::= '[' BitList ']'
/// ValueSuffix ::= '.' ID
///
-Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) {
- Init *Result = ParseSimpleValue(CurRec, ItemType);
+Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
+ Init *Result = ParseSimpleValue(CurRec, ItemType, Mode);
if (Result == 0) return 0;
// Parse the suffixes now if present.
switch (Lex.getCode()) {
default: return Result;
case tgtok::l_brace: {
+ if (Mode == ParseNameMode)
+ // This is the beginning of the object body.
+ return Result;
+
SMLoc CurlyLoc = Lex.getLoc();
Lex.Lex(); // eat the '{'
std::vector<unsigned> Ranges = ParseRangeList();
Result = FieldInit::get(Result, Lex.getCurStrVal());
Lex.Lex(); // eat field name
break;
+
+ case tgtok::paste:
+ SMLoc PasteLoc = Lex.getLoc();
+
+ // Create a !strconcat() operation, first casting each operand to
+ // a string if necessary.
+
+ TypedInit *LHS = dynamic_cast<TypedInit *>(Result);
+ if (!LHS) {
+ Error(PasteLoc, "LHS of paste is not typed!");
+ return 0;
+ }
+
+ if (LHS->getType() != StringRecTy::get()) {
+ LHS = UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get());
+ }
+
+ TypedInit *RHS = 0;
+
+ Lex.Lex(); // Eat the '#'.
+ switch (Lex.getCode()) {
+ case tgtok::colon:
+ case tgtok::semi:
+ case tgtok::l_brace:
+ // 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;
+
+ default:
+ Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode);
+ RHS = dynamic_cast<TypedInit *>(RHSResult);
+ if (!RHS) {
+ Error(PasteLoc, "RHS of paste is not typed!");
+ return 0;
+ }
+
+ if (RHS->getType() != StringRecTy::get()) {
+ RHS = UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get());
+ }
+
+ break;
+ }
+
+ Result = BinOpInit::get(BinOpInit::STRCONCAT, LHS, RHS,
+ StringRecTy::get())->Fold(CurRec, CurMultiClass);
+ break;
}
}
}
Lex.Lex(); // Eat the 'def' token.
// Parse ObjectName and make a record for it.
- Record *CurRec = new Record(ParseObjectName(), DefLoc, Records);
+ Record *CurRec = new Record(ParseObjectName(CurMultiClass), DefLoc, Records);
if (!CurMultiClass) {
// Top-level def definition.
Record *CurRec = Records.getClass(Lex.getCurStrVal());
if (CurRec) {
// If the body was previously defined, this is an error.
- if (!CurRec->getValues().empty() ||
+ if (CurRec->getValues().size() > 1 || // Account for NAME.
!CurRec->getSuperClasses().empty() ||
!CurRec->getTemplateArgs().empty())
- return TokError("Class '" + CurRec->getName() + "' 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);
Record *TGParser::
InstantiateMulticlassDef(MultiClass &MC,
Record *DefProto,
- const std::string &DefmPrefix,
+ Init *DefmPrefix,
SMLoc DefmPrefixLoc) {
+ // We need to preserve DefProto so it can be reused for later
+ // instantiations, so create a new Record to inherit from it.
+
// 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;
- }
+
+ if (DefmPrefix == 0)
+ DefmPrefix = StringInit::get(GetNewAnonymousName());
+
+ Init *DefName = DefProto->getNameInit();
+
+ StringInit *DefNameString = dynamic_cast<StringInit *>(DefName);
+
+ if (DefNameString != 0) {
+ // We have a fully expanded string so there are no operators to
+ // resolve. We should concatenate the given prefix and name.
+ DefName =
+ BinOpInit::get(BinOpInit::STRCONCAT,
+ UnOpInit::get(UnOpInit::CAST, DefmPrefix,
+ StringRecTy::get())->Fold(DefProto, &MC),
+ DefName, StringRecTy::get())->Fold(DefProto, &MC);
}
Record *CurRec = new Record(DefName, DefmPrefixLoc, Records);
Ref.Rec = DefProto;
AddSubClass(CurRec, Ref);
+ if (DefNameString == 0) {
+ // We must resolve references to NAME.
+ if (SetValue(CurRec, Ref.RefLoc, "NAME", std::vector<unsigned>(),
+ DefmPrefix)) {
+ Error(DefmPrefixLoc, "Could not resolve "
+ + CurRec->getNameInitAsString() + ":NAME to '"
+ + DefmPrefix->getAsUnquotedString() + "'");
+ return 0;
+ }
+
+ RecordVal *DefNameRV = CurRec->getValue("NAME");
+ CurRec->resolveReferencesTo(DefNameRV);
+ }
+
+ if (!CurMultiClass) {
+ // We do this after resolving NAME because before resolution, many
+ // multiclass defs will have the same name expression. 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
+ // defs as more than one probably refers to NAME or some other
+ // common internal placeholder.
+
+ // Ensure redefinition doesn't happen.
+ if (Records.getDef(CurRec->getNameInitAsString())) {
+ Error(DefmPrefixLoc, "def '" + CurRec->getNameInitAsString() +
+ "' already defined, instantiating defm with subdef '" +
+ DefProto->getNameInitAsString() + "'");
+ return 0;
+ }
+
+ Records.addDef(CurRec);
+ }
+
return CurRec;
}
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() +
+ if (CurMultiClass->DefPrototypes[i]->getNameInit()
+ == CurRec->getNameInit())
+ return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() +
"' already defined in this multiclass!");
CurMultiClass->DefPrototypes.push_back(CurRec);
assert(RV && "Template arg doesn't exist?");
CurRec->addValue(*RV);
}
- } else {
- Records.addDef(CurRec);
}
return false;
bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
- std::string DefmPrefix;
+ Init *DefmPrefix = 0;
+
if (Lex.Lex() == tgtok::Id) { // eat the defm.
- DefmPrefix = Lex.getCurStrVal();
- Lex.Lex(); // Eat the defm prefix.
+ DefmPrefix = ParseObjectName(CurMultiClass);
}
SMLoc DefmPrefixLoc = Lex.getLoc();