summaryrefslogtreecommitdiff
path: root/lib/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/TableGen')
-rw-r--r--lib/TableGen/Main.cpp30
-rw-r--r--lib/TableGen/Record.cpp48
-rw-r--r--lib/TableGen/TGLexer.cpp3
-rw-r--r--lib/TableGen/TGLexer.h17
-rw-r--r--lib/TableGen/TGParser.cpp223
-rw-r--r--lib/TableGen/TGParser.h6
6 files changed, 195 insertions, 132 deletions
diff --git a/lib/TableGen/Main.cpp b/lib/TableGen/Main.cpp
index e317fbfa373d..c44045152a4d 100644
--- a/lib/TableGen/Main.cpp
+++ b/lib/TableGen/Main.cpp
@@ -56,19 +56,16 @@ static int createDependencyFile(const TGParser &Parser, const char *argv0) {
errs() << argv0 << ": the option -d must be used together with -o\n";
return 1;
}
- std::string Error;
- tool_output_file DepOut(DependFilename.c_str(), Error, sys::fs::F_Text);
- if (!Error.empty()) {
- errs() << argv0 << ": error opening " << DependFilename
- << ":" << Error << "\n";
+ std::error_code EC;
+ tool_output_file DepOut(DependFilename, EC, sys::fs::F_Text);
+ if (EC) {
+ errs() << argv0 << ": error opening " << DependFilename << ":"
+ << EC.message() << "\n";
return 1;
}
DepOut.os() << OutputFilename << ":";
- const TGLexer::DependenciesMapTy &Dependencies = Parser.getDependencies();
- for (TGLexer::DependenciesMapTy::const_iterator I = Dependencies.begin(),
- E = Dependencies.end();
- I != E; ++I) {
- DepOut.os() << " " << I->first;
+ for (const auto &Dep : Parser.getDependencies()) {
+ DepOut.os() << ' ' << Dep.first;
}
DepOut.os() << "\n";
DepOut.keep();
@@ -88,10 +85,9 @@ int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
<< "': " << EC.message() << "\n";
return 1;
}
- MemoryBuffer *F = FileOrErr.get().release();
// Tell SrcMgr about this buffer, which is what TGParser will pick up.
- SrcMgr.AddNewSourceBuffer(F, SMLoc());
+ SrcMgr.AddNewSourceBuffer(std::move(*FileOrErr), SMLoc());
// Record the location of the include directory so that the lexer can find
// it later.
@@ -102,11 +98,11 @@ int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
if (Parser.ParseFile())
return 1;
- std::string Error;
- tool_output_file Out(OutputFilename.c_str(), Error, sys::fs::F_Text);
- if (!Error.empty()) {
- errs() << argv0 << ": error opening " << OutputFilename
- << ":" << Error << "\n";
+ std::error_code EC;
+ tool_output_file Out(OutputFilename, EC, sys::fs::F_Text);
+ if (EC) {
+ errs() << argv0 << ": error opening " << OutputFilename << ":"
+ << EC.message() << "\n";
return 1;
}
if (!DependFilename.empty()) {
diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp
index 0f40904ae919..3a2ae96340c3 100644
--- a/lib/TableGen/Record.cpp
+++ b/lib/TableGen/Record.cpp
@@ -114,8 +114,21 @@ Init *BitRecTy::convertValue(IntInit *II) {
Init *BitRecTy::convertValue(TypedInit *VI) {
RecTy *Ty = VI->getType();
- if (isa<BitRecTy>(Ty) || isa<BitsRecTy>(Ty) || isa<IntRecTy>(Ty))
+ if (isa<BitRecTy>(Ty))
return VI; // Accept variable if it is already of bit type!
+ if (auto *BitsTy = dyn_cast<BitsRecTy>(Ty))
+ // Accept only bits<1> expression.
+ return BitsTy->getNumBits() == 1 ? VI : nullptr;
+ // Ternary !if can be converted to bit, but only if both sides are
+ // convertible to a bit.
+ if (TernOpInit *TOI = dyn_cast<TernOpInit>(VI)) {
+ if (TOI->getOpcode() != TernOpInit::TernaryOp::IF)
+ return nullptr;
+ if (!TOI->getMHS()->convertInitializerTo(BitRecTy::get()) ||
+ !TOI->getRHS()->convertInitializerTo(BitRecTy::get()))
+ return nullptr;
+ return TOI;
+ }
return nullptr;
}
@@ -799,7 +812,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
return VarInit::get(MCName, RV->getType());
}
}
-
+ assert(CurRec && "NULL pointer");
if (Record *D = (CurRec->getRecords()).getDef(Name))
return DefInit::get(D);
@@ -952,6 +965,7 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
break;
}
case ADD:
+ case AND:
case SHL:
case SRA:
case SRL: {
@@ -965,6 +979,7 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
switch (getOpcode()) {
default: llvm_unreachable("Bad opcode!");
case ADD: Result = LHSv + RHSv; break;
+ case AND: Result = LHSv & RHSv; break;
case SHL: Result = LHSv << RHSv; break;
case SRA: Result = LHSv >> RHSv; break;
case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
@@ -991,6 +1006,7 @@ std::string BinOpInit::getAsString() const {
switch (Opc) {
case CONCAT: Result = "!con"; break;
case ADD: Result = "!add"; break;
+ case AND: Result = "!and"; break;
case SHL: Result = "!shl"; break;
case SRA: Result = "!sra"; break;
case SRL: Result = "!srl"; break;
@@ -1692,13 +1708,6 @@ const std::string &Record::getName() const {
}
void Record::setName(Init *NewName) {
- if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) {
- TrackedRecords.removeDef(Name->getAsUnquotedString());
- TrackedRecords.addDef(this);
- } else if (TrackedRecords.getClass(Name->getAsUnquotedString()) == this) {
- TrackedRecords.removeClass(Name->getAsUnquotedString());
- TrackedRecords.addClass(this);
- } // Otherwise this isn't yet registered.
Name = NewName;
checkName();
// DO NOT resolve record values to the name at this point because
@@ -1998,16 +2007,14 @@ void RecordKeeper::dump() const { errs() << *this; }
raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {
OS << "------------- Classes -----------------\n";
- const std::map<std::string, Record*> &Classes = RK.getClasses();
- for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
- E = Classes.end(); I != E; ++I)
- OS << "class " << *I->second;
+ const auto &Classes = RK.getClasses();
+ for (const auto &C : Classes)
+ OS << "class " << *C.second;
OS << "------------- Defs -----------------\n";
- const std::map<std::string, Record*> &Defs = RK.getDefs();
- for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
- E = Defs.end(); I != E; ++I)
- OS << "def " << *I->second;
+ const auto &Defs = RK.getDefs();
+ for (const auto &D : Defs)
+ OS << "def " << *D.second;
return OS;
}
@@ -2022,10 +2029,9 @@ RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
PrintFatalError("ERROR: Couldn't find the `" + ClassName + "' class!\n");
std::vector<Record*> Defs;
- for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
- E = getDefs().end(); I != E; ++I)
- if (I->second->isSubClassOf(Class))
- Defs.push_back(I->second);
+ for (const auto &D : getDefs())
+ if (D.second->isSubClassOf(Class))
+ Defs.push_back(D.second.get());
return Defs;
}
diff --git a/lib/TableGen/TGLexer.cpp b/lib/TableGen/TGLexer.cpp
index fc1d3ca3392f..63b85842d6a9 100644
--- a/lib/TableGen/TGLexer.cpp
+++ b/lib/TableGen/TGLexer.cpp
@@ -411,7 +411,7 @@ tgtok::TokKind TGLexer::LexNumber() {
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "Invalid binary number");
CurIntVal = strtoll(NumStart, nullptr, 2);
- return tgtok::IntVal;
+ return tgtok::BinaryIntVal;
}
}
@@ -471,6 +471,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("tail", tgtok::XTail)
.Case("con", tgtok::XConcat)
.Case("add", tgtok::XADD)
+ .Case("and", tgtok::XAND)
.Case("shl", tgtok::XSHL)
.Case("sra", tgtok::XSRA)
.Case("srl", tgtok::XSRL)
diff --git a/lib/TableGen/TGLexer.h b/lib/TableGen/TGLexer.h
index a2c95ca833df..1f750fcd8d96 100644
--- a/lib/TableGen/TGLexer.h
+++ b/lib/TableGen/TGLexer.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef TGLEXER_H
-#define TGLEXER_H
+#ifndef LLVM_LIB_TABLEGEN_TGLEXER_H
+#define LLVM_LIB_TABLEGEN_TGLEXER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
@@ -47,11 +47,15 @@ namespace tgtok {
MultiClass, String,
// !keywords.
- XConcat, XADD, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, XSubst,
- XForEach, XHead, XTail, XEmpty, XIf, XEq,
+ XConcat, XADD, XAND, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
+ XSubst, XForEach, XHead, XTail, XEmpty, XIf, XEq,
// Integer value.
IntVal,
+
+ // Binary constant. Note that these are sized according to the number of
+ // bits given.
+ BinaryIntVal,
// String valued tokens.
Id, StrVal, VarName, CodeFragment
@@ -105,6 +109,11 @@ public:
assert(CurCode == tgtok::IntVal && "This token isn't an integer");
return CurIntVal;
}
+ std::pair<int64_t, unsigned> getCurBinaryIntVal() const {
+ assert(CurCode == tgtok::BinaryIntVal &&
+ "This token isn't a binary integer");
+ return std::make_pair(CurIntVal, (CurPtr - TokStart)-2);
+ }
SMLoc getLoc() const;
diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp
index 0550692ebce7..a438cb6fc8f2 100644
--- a/lib/TableGen/TGParser.cpp
+++ b/lib/TableGen/TGParser.cpp
@@ -135,11 +135,18 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
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;
}
@@ -217,7 +224,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVals[i]))
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(),
@@ -225,14 +232,14 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
i != iend;
++i) {
// Clone the def and add it to the current multiclass
- Record *NewDef = new Record(**i);
+ auto NewDef = make_unique<Record>(**i);
// 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.get(), SubMultiClass.RefRange.Start, MCVals[i]))
return true;
- CurMC->DefPrototypes.push_back(NewDef);
+ CurMC->DefPrototypes.push_back(std::move(NewDef));
}
const std::vector<Init *> &SMCTArgs = SMC->Rec.getTemplateArgs();
@@ -262,14 +269,9 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
// 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;
@@ -333,24 +335,20 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){
// 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()));
@@ -361,16 +359,15 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){
if (Records.getDef(IterRec->getNameInitAsString())) {
// 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());
- return true;
- }
+ 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;
}
@@ -457,7 +454,7 @@ MultiClass *TGParser::ParseMultiClassID() {
return nullptr;
}
- MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
+ MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get();
if (!Result)
TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
@@ -904,6 +901,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XConcat:
case tgtok::XADD:
+ case tgtok::XAND:
case tgtok::XSRA:
case tgtok::XSRL:
case tgtok::XSHL:
@@ -921,6 +919,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
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;
@@ -1173,6 +1172,15 @@ 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();
@@ -1226,8 +1234,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
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;
@@ -1235,12 +1244,16 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
// 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 =
@@ -1284,17 +1297,40 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
}
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 ']'
@@ -1439,6 +1475,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XCast: // Value ::= !unop '(' Value ')'
case tgtok::XConcat:
case tgtok::XADD:
+ case tgtok::XAND:
case tgtok::XSRA:
case tgtok::XSRL:
case tgtok::XSHL:
@@ -1727,7 +1764,10 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
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;
@@ -1983,24 +2023,23 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
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;
@@ -2016,14 +2055,13 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
// 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))
+ == 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
@@ -2047,9 +2085,8 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
}
if (ProcessForeachDefs(CurRec, DefLoc)) {
- Error(DefLoc,
- "Could not process loops for def" + CurRec->getNameInitAsString());
- return true;
+ return Error(DefLoc, "Could not process loops for def" +
+ CurRec->getNameInitAsString());
}
return false;
@@ -2127,8 +2164,10 @@ bool TGParser::ParseClass() {
+ "' 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.
@@ -2196,7 +2235,7 @@ bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
// 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'");
@@ -2246,11 +2285,14 @@ bool TGParser::ParseMultiClass() {
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.
@@ -2286,25 +2328,24 @@ bool TGParser::ParseMultiClass() {
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 '}'.
@@ -2350,18 +2391,18 @@ InstantiateMulticlassDef(MultiClass &MC,
// 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)) {
+ if (SetValue(CurRec.get(), Ref.RefRange.Start, "NAME",
+ std::vector<unsigned>(), DefmPrefix)) {
Error(DefmPrefixRange.Start, "Could not resolve "
+ CurRec->getNameInitAsString() + ":NAME to '"
+ DefmPrefix->getAsUnquotedString() + "'");
@@ -2399,10 +2440,14 @@ InstantiateMulticlassDef(MultiClass &MC,
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,
@@ -2458,7 +2503,7 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC,
== 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 =
@@ -2508,7 +2553,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
// 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;
@@ -2520,7 +2565,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
// 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 *DefProto = MC->DefPrototypes[i].get();
Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix,
SMRange(DefmLoc,
@@ -2535,6 +2580,12 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
if (ResolveMulticlassDef(*MC, CurRec, DefProto, 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);
}
diff --git a/lib/TableGen/TGParser.h b/lib/TableGen/TGParser.h
index 9f4b7e90826a..22a00e591951 100644
--- a/lib/TableGen/TGParser.h
+++ b/lib/TableGen/TGParser.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef TGPARSER_H
-#define TGPARSER_H
+#ifndef LLVM_LIB_TABLEGEN_TGPARSER_H
+#define LLVM_LIB_TABLEGEN_TGPARSER_H
#include "TGLexer.h"
#include "llvm/ADT/Twine.h"
@@ -55,7 +55,7 @@ namespace llvm {
class TGParser {
TGLexer Lex;
std::vector<std::vector<LetRecord> > LetStack;
- std::map<std::string, MultiClass*> MultiClasses;
+ std::map<std::string, std::unique_ptr<MultiClass>> MultiClasses;
/// Loops - Keep track of any foreach loops we are within.
///