2007-11-22 20:49:04 +00:00
|
|
|
//===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:37:13 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-11-22 20:49:04 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Implement the Parser for TableGen.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "TGParser.h"
|
2015-03-01 21:28:53 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2007-11-22 20:49:04 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/TableGen/Record.h"
|
2009-07-03 00:10:29 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <sstream>
|
2007-11-22 20:49:04 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Support Code for the Semantic Actions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
struct SubClassReference {
|
2013-01-10 18:50:11 +00:00
|
|
|
SMRange RefRange;
|
2007-11-22 20:49:04 +00:00
|
|
|
Record *Rec;
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> TemplateArgs;
|
2014-04-09 04:50:04 +00:00
|
|
|
SubClassReference() : Rec(nullptr) {}
|
2009-04-24 16:55:41 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
bool isInvalid() const { return Rec == nullptr; }
|
2007-11-22 20:49:04 +00:00
|
|
|
};
|
2009-04-22 16:42:54 +00:00
|
|
|
|
|
|
|
struct SubMultiClassReference {
|
2013-01-10 18:50:11 +00:00
|
|
|
SMRange RefRange;
|
2009-04-22 16:42:54 +00:00
|
|
|
MultiClass *MC;
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> TemplateArgs;
|
2014-04-09 04:50:04 +00:00
|
|
|
SubMultiClassReference() : MC(nullptr) {}
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
bool isInvalid() const { return MC == nullptr; }
|
2009-04-24 16:55:41 +00:00
|
|
|
void dump() const;
|
2009-04-22 16:42:54 +00:00
|
|
|
};
|
2009-04-24 16:55:41 +00:00
|
|
|
|
|
|
|
void SubMultiClassReference::dump() const {
|
2009-07-03 00:10:29 +00:00
|
|
|
errs() << "Multiclass:\n";
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-04-24 16:55:41 +00:00
|
|
|
MC->dump();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
errs() << "Template args:\n";
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Init *TA : TemplateArgs) {
|
|
|
|
TA->dump();
|
2009-04-24 16:55:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
} // end namespace llvm
|
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!CurRec)
|
2007-11-22 20:49:04 +00:00
|
|
|
CurRec = &CurMultiClass->Rec;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2012-01-13 03:16:35 +00:00
|
|
|
if (RecordVal *ERV = CurRec->getValue(RV.getNameInit())) {
|
2007-11-22 20:49:04 +00:00
|
|
|
// The value already exists in the class, treat this as a set.
|
|
|
|
if (ERV->setValue(RV.getValue()))
|
|
|
|
return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
|
|
|
|
RV.getType()->getAsString() + "' is incompatible with " +
|
2009-11-22 04:24:42 +00:00
|
|
|
"previous definition of type '" +
|
2007-11-22 20:49:04 +00:00
|
|
|
ERV->getType()->getAsString() + "'");
|
|
|
|
} else {
|
|
|
|
CurRec->addValue(RV);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// SetValue -
|
|
|
|
/// Return true on error, false on success.
|
2011-10-19 13:02:39 +00:00
|
|
|
bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
|
2011-07-29 22:43:06 +00:00
|
|
|
const std::vector<unsigned> &BitList, Init *V) {
|
2007-11-22 20:49:04 +00:00
|
|
|
if (!V) return false;
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!CurRec) CurRec = &CurMultiClass->Rec;
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
RecordVal *RV = CurRec->getValue(ValName);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!RV)
|
2015-04-30 05:54:22 +00:00
|
|
|
return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
|
|
|
|
"' unknown!");
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
// Do not allow assignments like 'X = X'. This will just cause infinite loops
|
|
|
|
// in the resolution machinery.
|
|
|
|
if (BitList.empty())
|
2012-10-10 20:24:43 +00:00
|
|
|
if (VarInit *VI = dyn_cast<VarInit>(V))
|
2011-10-19 13:02:39 +00:00
|
|
|
if (VI->getNameInit() == ValName)
|
2007-11-22 20:49:04 +00:00
|
|
|
return false;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// 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
|
|
|
|
// initializer.
|
|
|
|
//
|
|
|
|
if (!BitList.empty()) {
|
2012-10-10 20:24:43 +00:00
|
|
|
BitsInit *CurVal = dyn_cast<BitsInit>(RV->getValue());
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!CurVal)
|
2015-04-30 05:54:22 +00:00
|
|
|
return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
|
|
|
|
"' is not a bits type");
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
// Convert the incoming value to a bits type of the appropriate size...
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size()));
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!BI) {
|
2007-11-22 20:49:04 +00:00
|
|
|
return Error(Loc, "Initializer is not compatible with bit range");
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// We should have a BitsInit type now.
|
2015-04-29 07:13:05 +00:00
|
|
|
BitsInit *BInit = cast<BitsInit>(BI);
|
2007-11-22 20:49:04 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init *, 16> NewBits(CurVal->getNumBits());
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
// Loop over bits, assigning values as appropriate.
|
|
|
|
for (unsigned i = 0, e = BitList.size(); i != e; ++i) {
|
|
|
|
unsigned Bit = BitList[i];
|
2011-07-29 19:07:00 +00:00
|
|
|
if (NewBits[Bit])
|
2007-11-22 20:49:04 +00:00
|
|
|
return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
|
2011-10-19 13:02:39 +00:00
|
|
|
ValName->getAsUnquotedString() + "' more than once");
|
2011-07-29 19:07:00 +00:00
|
|
|
NewBits[Bit] = BInit->getBit(i);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!NewBits[i])
|
2011-07-29 19:07:00 +00:00
|
|
|
NewBits[i] = CurVal->getBit(i);
|
2007-11-22 20:49:04 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
V = BitsInit::get(NewBits);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
2014-07-31 01:43:57 +00:00
|
|
|
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();
|
|
|
|
}
|
2015-04-30 05:54:22 +00:00
|
|
|
return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
|
|
|
|
"' of type '" + RV->getType()->getAsString() +
|
|
|
|
"' is incompatible with initializer '" + V->getAsString() +
|
|
|
|
InitType + "'");
|
2014-07-31 01:43:57 +00:00
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
|
|
|
|
/// args as SubClass's template arguments.
|
2009-02-14 16:06:42 +00:00
|
|
|
bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
|
2007-11-22 20:49:04 +00:00
|
|
|
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)
|
2013-01-10 18:50:11 +00:00
|
|
|
if (AddValue(CurRec, SubClass.RefRange.Start, Vals[i]))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
|
|
|
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &TArgs = SC->getTemplateArgs();
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
// Ensure that an appropriate number of template arguments are specified.
|
|
|
|
if (TArgs.size() < SubClass.TemplateArgs.size())
|
2013-01-10 18:50:11 +00:00
|
|
|
return Error(SubClass.RefRange.Start,
|
|
|
|
"More template args specified than expected");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// 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) {
|
|
|
|
if (i < SubClass.TemplateArgs.size()) {
|
|
|
|
// If a value is specified for this template arg, set it now.
|
2013-01-10 18:50:11 +00:00
|
|
|
if (SetValue(CurRec, SubClass.RefRange.Start, TArgs[i],
|
|
|
|
std::vector<unsigned>(), SubClass.TemplateArgs[i]))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Resolve it next.
|
|
|
|
CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Now remove it.
|
|
|
|
CurRec->removeValue(TArgs[i]);
|
|
|
|
|
|
|
|
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
|
2013-01-10 18:50:11 +00:00
|
|
|
return Error(SubClass.RefRange.Start,
|
2015-04-30 05:54:22 +00:00
|
|
|
"Value not specified for template argument #" +
|
|
|
|
utostr(i) + " (" + TArgs[i]->getAsUnquotedString() +
|
|
|
|
") of subclass '" + SC->getNameInitAsString() + "'!");
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since everything went well, we can now set the "superclass" list for the
|
|
|
|
// current record.
|
|
|
|
const std::vector<Record*> &SCs = SC->getSuperClasses();
|
2013-01-10 18:50:11 +00:00
|
|
|
ArrayRef<SMRange> SCRanges = SC->getSuperClassRanges();
|
2007-11-22 20:49:04 +00:00
|
|
|
for (unsigned i = 0, e = SCs.size(); i != e; ++i) {
|
|
|
|
if (CurRec->isSubClassOf(SCs[i]))
|
2013-01-10 18:50:11 +00:00
|
|
|
return Error(SubClass.RefRange.Start,
|
2007-11-22 20:49:04 +00:00
|
|
|
"Already subclass of '" + SCs[i]->getName() + "'!\n");
|
2013-01-10 18:50:11 +00:00
|
|
|
CurRec->addSuperClass(SCs[i], SCRanges[i]);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (CurRec->isSubClassOf(SC))
|
2013-01-10 18:50:11 +00:00
|
|
|
return Error(SubClass.RefRange.Start,
|
2007-11-22 20:49:04 +00:00
|
|
|
"Already subclass of '" + SC->getName() + "'!\n");
|
2013-01-10 18:50:11 +00:00
|
|
|
CurRec->addSuperClass(SC, SubClass.RefRange);
|
2007-11-22 20:49:04 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
/// AddSubMultiClass - Add SubMultiClass as a subclass to
|
2009-04-30 18:26:19 +00:00
|
|
|
/// CurMC, resolving its template args as SubMultiClass's
|
2009-04-22 16:42:54 +00:00
|
|
|
/// template arguments.
|
2009-04-30 18:26:19 +00:00
|
|
|
bool TGParser::AddSubMultiClass(MultiClass *CurMC,
|
2009-04-30 17:46:20 +00:00
|
|
|
SubMultiClassReference &SubMultiClass) {
|
2009-04-22 16:42:54 +00:00
|
|
|
MultiClass *SMC = SubMultiClass.MC;
|
2009-04-30 18:26:19 +00:00
|
|
|
Record *CurRec = &CurMC->Rec;
|
2009-04-22 16:42:54 +00:00
|
|
|
|
|
|
|
// Add all of the values in the subclass into the current class.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const auto &SMCVal : SMC->Rec.getValues())
|
|
|
|
if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVal))
|
2009-04-22 16:42:54 +00:00
|
|
|
return true;
|
|
|
|
|
2014-11-30 00:24:32 +00:00
|
|
|
unsigned newDefStart = CurMC->DefPrototypes.size();
|
2009-04-24 16:55:41 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// Add all of the defs in the subclass into the current multiclass.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const std::unique_ptr<Record> &R : SMC->DefPrototypes) {
|
2009-04-22 16:42:54 +00:00
|
|
|
// Clone the def and add it to the current multiclass
|
2015-04-29 04:43:36 +00:00
|
|
|
auto NewDef = make_unique<Record>(*R);
|
2009-04-22 16:42:54 +00:00
|
|
|
|
|
|
|
// Add all of the values in the superclass into the current def.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const auto &MCVal : CurRec->getValues())
|
|
|
|
if (AddValue(NewDef.get(), SubMultiClass.RefRange.Start, MCVal))
|
2009-04-22 16:42:54 +00:00
|
|
|
return true;
|
|
|
|
|
2014-12-11 05:25:33 +00:00
|
|
|
CurMC->DefPrototypes.push_back(std::move(NewDef));
|
2009-04-22 16:42:54 +00:00
|
|
|
}
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &SMCTArgs = SMC->Rec.getTemplateArgs();
|
2009-04-22 16:42:54 +00:00
|
|
|
|
2009-04-24 16:55:41 +00:00
|
|
|
// Ensure that an appropriate number of template arguments are
|
|
|
|
// specified.
|
2009-04-22 16:42:54 +00:00
|
|
|
if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
|
2013-01-10 18:50:11 +00:00
|
|
|
return Error(SubMultiClass.RefRange.Start,
|
2009-04-24 16:55:41 +00:00
|
|
|
"More template args specified than expected");
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// 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 = SMCTArgs.size(); i != e; ++i) {
|
|
|
|
if (i < SubMultiClass.TemplateArgs.size()) {
|
2009-04-24 16:55:41 +00:00
|
|
|
// If a value is specified for this template arg, set it in the
|
|
|
|
// superclass now.
|
2013-01-10 18:50:11 +00:00
|
|
|
if (SetValue(CurRec, SubMultiClass.RefRange.Start, SMCTArgs[i],
|
2009-04-28 19:41:44 +00:00
|
|
|
std::vector<unsigned>(),
|
2009-04-22 16:42:54 +00:00
|
|
|
SubMultiClass.TemplateArgs[i]))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Resolve it next.
|
|
|
|
CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// Now remove it.
|
|
|
|
CurRec->removeValue(SMCTArgs[i]);
|
|
|
|
|
2009-04-24 16:55:41 +00:00
|
|
|
// If a value is specified for this template arg, set it in the
|
|
|
|
// new defs now.
|
2014-12-11 05:25:33 +00:00
|
|
|
for (const auto &Def :
|
|
|
|
makeArrayRef(CurMC->DefPrototypes).slice(newDefStart)) {
|
|
|
|
if (SetValue(Def.get(), SubMultiClass.RefRange.Start, SMCTArgs[i],
|
2009-04-28 19:41:44 +00:00
|
|
|
std::vector<unsigned>(),
|
2009-04-22 16:42:54 +00:00
|
|
|
SubMultiClass.TemplateArgs[i]))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Resolve it next.
|
|
|
|
Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
|
|
|
|
|
|
|
|
// Now remove it
|
|
|
|
Def->removeValue(SMCTArgs[i]);
|
|
|
|
}
|
|
|
|
} else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
|
2013-01-10 18:50:11 +00:00
|
|
|
return Error(SubMultiClass.RefRange.Start,
|
2015-04-30 05:54:22 +00:00
|
|
|
"Value not specified for template argument #" +
|
|
|
|
utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString() +
|
|
|
|
") of subclass '" + SMC->Rec.getNameInitAsString() + "'!");
|
2009-04-22 16:42:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-02-22 16:09:41 +00:00
|
|
|
/// ProcessForeachDefs - Given a record, apply all of the variable
|
|
|
|
/// values in all surrounding foreach loops, creating new records for
|
|
|
|
/// each combination of values.
|
2012-05-24 22:17:33 +00:00
|
|
|
bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc) {
|
|
|
|
if (Loops.empty())
|
|
|
|
return false;
|
|
|
|
|
2012-02-22 16:09:41 +00:00
|
|
|
// We want to instantiate a new copy of CurRec for each combination
|
|
|
|
// of nested loop iterator values. We don't want top instantiate
|
|
|
|
// any copies until we have values for each loop iterator.
|
|
|
|
IterSet IterVals;
|
2012-05-24 22:17:33 +00:00
|
|
|
return ProcessForeachDefs(CurRec, Loc, IterVals);
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ProcessForeachDefs - Given a record, a loop and a loop iterator,
|
|
|
|
/// apply each of the variable values in this loop and then process
|
|
|
|
/// subloops.
|
2012-05-24 22:17:33 +00:00
|
|
|
bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){
|
|
|
|
// Recursively build a tuple of iterator values.
|
|
|
|
if (IterVals.size() != Loops.size()) {
|
|
|
|
assert(IterVals.size() < Loops.size());
|
|
|
|
ForeachLoop &CurLoop = Loops[IterVals.size()];
|
2012-10-10 20:24:43 +00:00
|
|
|
ListInit *List = dyn_cast<ListInit>(CurLoop.ListValue);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!List) {
|
2012-05-24 22:17:33 +00:00
|
|
|
Error(Loc, "Loop list is not a list");
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
// Process each value.
|
|
|
|
for (int64_t i = 0; i < List->getSize(); ++i) {
|
2014-04-09 04:50:04 +00:00
|
|
|
Init *ItemVal = List->resolveListElementReference(*CurRec, nullptr, i);
|
2012-05-24 22:17:33 +00:00
|
|
|
IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal));
|
|
|
|
if (ProcessForeachDefs(CurRec, Loc, IterVals))
|
|
|
|
return true;
|
|
|
|
IterVals.pop_back();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
// 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.
|
2014-11-29 05:31:10 +00:00
|
|
|
auto IterRec = make_unique<Record>(*CurRec);
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
// Set the iterator values now.
|
|
|
|
for (unsigned i = 0, e = IterVals.size(); i != e; ++i) {
|
|
|
|
VarInit *IterVar = IterVals[i].IterVar;
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *IVal = dyn_cast<TypedInit>(IterVals[i].IterValue);
|
2014-11-29 05:31:10 +00:00
|
|
|
if (!IVal)
|
|
|
|
return Error(Loc, "foreach iterator value is untyped");
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false));
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2014-11-29 05:31:10 +00:00
|
|
|
if (SetValue(IterRec.get(), Loc, IterVar->getName(),
|
|
|
|
std::vector<unsigned>(), IVal))
|
|
|
|
return Error(Loc, "when instantiating this def");
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
// Resolve it next.
|
|
|
|
IterRec->resolveReferencesTo(IterRec->getValue(IterVar->getName()));
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
// Remove it.
|
|
|
|
IterRec->removeValue(IterVar->getName());
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
2012-05-24 22:17:33 +00:00
|
|
|
|
|
|
|
if (Records.getDef(IterRec->getNameInitAsString())) {
|
2014-06-10 12:41:14 +00:00
|
|
|
// If this record is anonymous, it's no problem, just generate a new name
|
2014-11-29 05:31:10 +00:00
|
|
|
if (!IterRec->isAnonymous())
|
|
|
|
return Error(Loc, "def already exists: " +IterRec->getNameInitAsString());
|
|
|
|
|
|
|
|
IterRec->setName(GetNewAnonymousName());
|
2012-05-24 22:17:33 +00:00
|
|
|
}
|
|
|
|
|
2014-11-29 05:31:10 +00:00
|
|
|
Record *IterRecSave = IterRec.get(); // Keep a copy before release.
|
2014-11-29 05:52:51 +00:00
|
|
|
Records.addDef(std::move(IterRec));
|
2014-11-29 05:31:10 +00:00
|
|
|
IterRecSave->resolveReferences();
|
2012-02-22 16:09:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Parser Code
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// isObjectStart - Return true if this is a valid first token for an Object.
|
|
|
|
static bool isObjectStart(tgtok::TokKind K) {
|
|
|
|
return K == tgtok::Class || K == tgtok::Def ||
|
2012-02-22 16:09:41 +00:00
|
|
|
K == tgtok::Defm || K == tgtok::Let ||
|
|
|
|
K == tgtok::MultiClass || K == tgtok::Foreach;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
2013-12-21 18:51:00 +00:00
|
|
|
/// GetNewAnonymousName - Generate a unique anonymous name that can be used as
|
|
|
|
/// an identifier.
|
|
|
|
std::string TGParser::GetNewAnonymousName() {
|
2015-02-16 19:33:36 +00:00
|
|
|
return "anonymous_" + utostr(AnonCounter++);
|
2010-10-05 22:51:56 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseObjectName - If an object name is specified, return it. Otherwise,
|
2013-01-10 18:50:05 +00:00
|
|
|
/// return 0.
|
2011-10-19 13:04:29 +00:00
|
|
|
/// ObjectName ::= Value [ '#' Value ]*
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ObjectName ::= /*empty*/
|
|
|
|
///
|
2011-10-19 13:04:29 +00:00
|
|
|
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.
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-10-19 13:04:29 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2010-10-23 07:32:37 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
Record *CurRec = nullptr;
|
2011-10-19 13:04:29 +00:00
|
|
|
if (CurMultiClass)
|
|
|
|
CurRec = &CurMultiClass->Rec;
|
2007-11-22 20:49:04 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *Type = nullptr;
|
2011-10-19 13:04:29 +00:00
|
|
|
if (CurRec) {
|
2012-10-10 20:24:47 +00:00
|
|
|
const TypedInit *CurRecName = dyn_cast<TypedInit>(CurRec->getNameInit());
|
2011-10-19 13:04:29 +00:00
|
|
|
if (!CurRecName) {
|
|
|
|
TokError("Record name is not typed!");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-10-19 13:04:29 +00:00
|
|
|
}
|
|
|
|
Type = CurRecName->getType();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ParseValue(CurRec, Type, ParseNameMode);
|
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
/// ParseClassID - Parse and resolve a reference to a class name. This returns
|
|
|
|
/// null on error.
|
|
|
|
///
|
|
|
|
/// ClassID ::= ID
|
|
|
|
///
|
|
|
|
Record *TGParser::ParseClassID() {
|
|
|
|
if (Lex.getCode() != tgtok::Id) {
|
|
|
|
TokError("expected name for ClassID");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
Record *Result = Records.getClass(Lex.getCurStrVal());
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result)
|
2007-11-22 20:49:04 +00:00
|
|
|
TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex();
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-04-28 19:41:44 +00:00
|
|
|
/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
|
|
|
|
/// This returns null on error.
|
2009-04-22 16:42:54 +00:00
|
|
|
///
|
|
|
|
/// MultiClassID ::= ID
|
|
|
|
///
|
|
|
|
MultiClass *TGParser::ParseMultiClassID() {
|
|
|
|
if (Lex.getCode() != tgtok::Id) {
|
2013-01-09 02:11:57 +00:00
|
|
|
TokError("expected name for MultiClassID");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-04-22 16:42:54 +00:00
|
|
|
}
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2014-12-11 05:25:30 +00:00
|
|
|
MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get();
|
2014-11-30 01:20:17 +00:00
|
|
|
if (!Result)
|
2013-01-09 02:11:57 +00:00
|
|
|
TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
Lex.Lex();
|
2014-11-30 01:20:17 +00:00
|
|
|
return Result;
|
2009-04-22 16:42:54 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseSubClassReference - Parse a reference to a subclass or to a templated
|
|
|
|
/// subclass. This returns a SubClassRefTy with a null Record* on error.
|
|
|
|
///
|
|
|
|
/// SubClassRef ::= ClassID
|
|
|
|
/// SubClassRef ::= ClassID '<' ValueList '>'
|
|
|
|
///
|
|
|
|
SubClassReference TGParser::
|
|
|
|
ParseSubClassReference(Record *CurRec, bool isDefm) {
|
|
|
|
SubClassReference Result;
|
2013-01-10 18:50:11 +00:00
|
|
|
Result.RefRange.Start = Lex.getLoc();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2013-01-09 02:17:14 +00:00
|
|
|
if (isDefm) {
|
|
|
|
if (MultiClass *MC = ParseMultiClassID())
|
|
|
|
Result.Rec = &MC->Rec;
|
|
|
|
} else {
|
2007-11-22 20:49:04 +00:00
|
|
|
Result.Rec = ParseClassID();
|
2013-01-09 02:17:14 +00:00
|
|
|
}
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result.Rec) return Result;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If there is no template arg list, we're done.
|
2013-01-10 18:50:11 +00:00
|
|
|
if (Lex.getCode() != tgtok::less) {
|
|
|
|
Result.RefRange.End = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
2013-01-10 18:50:11 +00:00
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // Eat the '<'
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() == tgtok::greater) {
|
|
|
|
TokError("subclass reference requires a non-empty list of template values");
|
2014-04-09 04:50:04 +00:00
|
|
|
Result.Rec = nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-08 20:23:18 +00:00
|
|
|
Result.TemplateArgs = ParseValueList(CurRec, Result.Rec);
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Result.TemplateArgs.empty()) {
|
2014-04-09 04:50:04 +00:00
|
|
|
Result.Rec = nullptr; // Error parsing value list.
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected '>' in template value list");
|
2014-04-09 04:50:04 +00:00
|
|
|
Result.Rec = nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
Lex.Lex();
|
2013-01-10 18:50:11 +00:00
|
|
|
Result.RefRange.End = Lex.getLoc();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-04-28 19:41:44 +00:00
|
|
|
/// ParseSubMultiClassReference - Parse a reference to a subclass or to a
|
|
|
|
/// templated submulticlass. This returns a SubMultiClassRefTy with a null
|
|
|
|
/// Record* on error.
|
2009-04-22 16:42:54 +00:00
|
|
|
///
|
|
|
|
/// SubMultiClassRef ::= MultiClassID
|
|
|
|
/// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
|
|
|
|
///
|
|
|
|
SubMultiClassReference TGParser::
|
|
|
|
ParseSubMultiClassReference(MultiClass *CurMC) {
|
|
|
|
SubMultiClassReference Result;
|
2013-01-10 18:50:11 +00:00
|
|
|
Result.RefRange.Start = Lex.getLoc();
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
Result.MC = ParseMultiClassID();
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result.MC) return Result;
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// If there is no template arg list, we're done.
|
2013-01-10 18:50:11 +00:00
|
|
|
if (Lex.getCode() != tgtok::less) {
|
|
|
|
Result.RefRange.End = Lex.getLoc();
|
2009-04-22 16:42:54 +00:00
|
|
|
return Result;
|
2013-01-10 18:50:11 +00:00
|
|
|
}
|
2009-04-22 16:42:54 +00:00
|
|
|
Lex.Lex(); // Eat the '<'
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
if (Lex.getCode() == tgtok::greater) {
|
|
|
|
TokError("subclass reference requires a non-empty list of template values");
|
2014-04-09 04:50:04 +00:00
|
|
|
Result.MC = nullptr;
|
2009-04-22 16:42:54 +00:00
|
|
|
return Result;
|
|
|
|
}
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-06-08 20:23:18 +00:00
|
|
|
Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec);
|
2009-04-22 16:42:54 +00:00
|
|
|
if (Result.TemplateArgs.empty()) {
|
2014-04-09 04:50:04 +00:00
|
|
|
Result.MC = nullptr; // Error parsing value list.
|
2009-04-22 16:42:54 +00:00
|
|
|
return Result;
|
|
|
|
}
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected '>' in template value list");
|
2014-04-09 04:50:04 +00:00
|
|
|
Result.MC = nullptr;
|
2009-04-22 16:42:54 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
Lex.Lex();
|
2013-01-10 18:50:11 +00:00
|
|
|
Result.RefRange.End = Lex.getLoc();
|
2009-04-22 16:42:54 +00:00
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseRangePiece - Parse a bit/value range.
|
|
|
|
/// RangePiece ::= INTVAL
|
|
|
|
/// RangePiece ::= INTVAL '-' INTVAL
|
|
|
|
/// RangePiece ::= INTVAL INTVAL
|
|
|
|
bool TGParser::ParseRangePiece(std::vector<unsigned> &Ranges) {
|
2008-01-10 07:01:53 +00:00
|
|
|
if (Lex.getCode() != tgtok::IntVal) {
|
|
|
|
TokError("expected integer or bitrange");
|
|
|
|
return true;
|
|
|
|
}
|
2008-10-17 01:33:43 +00:00
|
|
|
int64_t Start = Lex.getCurIntVal();
|
|
|
|
int64_t End;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Start < 0)
|
|
|
|
return TokError("invalid range, cannot be negative");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
switch (Lex.Lex()) { // eat first character.
|
2009-11-22 04:24:42 +00:00
|
|
|
default:
|
2007-11-22 20:49:04 +00:00
|
|
|
Ranges.push_back(Start);
|
|
|
|
return false;
|
|
|
|
case tgtok::minus:
|
|
|
|
if (Lex.Lex() != tgtok::IntVal) {
|
|
|
|
TokError("expected integer value as end of range");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
End = Lex.getCurIntVal();
|
|
|
|
break;
|
|
|
|
case tgtok::IntVal:
|
|
|
|
End = -Lex.getCurIntVal();
|
|
|
|
break;
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
if (End < 0)
|
2007-11-22 20:49:04 +00:00
|
|
|
return TokError("invalid range, cannot be negative");
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Add to the range.
|
|
|
|
if (Start < End) {
|
|
|
|
for (; Start <= End; ++Start)
|
|
|
|
Ranges.push_back(Start);
|
|
|
|
} else {
|
|
|
|
for (; Start >= End; --Start)
|
|
|
|
Ranges.push_back(Start);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseRangeList - Parse a list of scalars and ranges into scalar values.
|
|
|
|
///
|
|
|
|
/// RangeList ::= RangePiece (',' RangePiece)*
|
|
|
|
///
|
|
|
|
std::vector<unsigned> TGParser::ParseRangeList() {
|
|
|
|
std::vector<unsigned> Result;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Parse the first piece.
|
|
|
|
if (ParseRangePiece(Result))
|
|
|
|
return std::vector<unsigned>();
|
|
|
|
while (Lex.getCode() == tgtok::comma) {
|
|
|
|
Lex.Lex(); // Eat the comma.
|
|
|
|
|
|
|
|
// Parse the next range piece.
|
|
|
|
if (ParseRangePiece(Result))
|
|
|
|
return std::vector<unsigned>();
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
|
|
|
|
/// OptionalRangeList ::= '<' RangeList '>'
|
|
|
|
/// OptionalRangeList ::= /*empty*/
|
|
|
|
bool TGParser::ParseOptionalRangeList(std::vector<unsigned> &Ranges) {
|
|
|
|
if (Lex.getCode() != tgtok::less)
|
|
|
|
return false;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc StartLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // eat the '<'
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Parse the range list.
|
|
|
|
Ranges = ParseRangeList();
|
|
|
|
if (Ranges.empty()) return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected '>' at end of range list");
|
|
|
|
return Error(StartLoc, "to match this '<'");
|
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '>'.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
|
|
|
|
/// OptionalBitList ::= '{' RangeList '}'
|
|
|
|
/// OptionalBitList ::= /*empty*/
|
|
|
|
bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) {
|
|
|
|
if (Lex.getCode() != tgtok::l_brace)
|
|
|
|
return false;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc StartLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // eat the '{'
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Parse the range list.
|
|
|
|
Ranges = ParseRangeList();
|
|
|
|
if (Ranges.empty()) return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
TokError("expected '}' at end of bit list");
|
|
|
|
return Error(StartLoc, "to match this '{'");
|
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '}'.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ParseType - Parse and return a tblgen type. This returns null on error.
|
|
|
|
///
|
|
|
|
/// Type ::= STRING // string type
|
2012-01-13 03:38:34 +00:00
|
|
|
/// Type ::= CODE // code type
|
2007-11-22 20:49:04 +00:00
|
|
|
/// Type ::= BIT // bit type
|
|
|
|
/// Type ::= BITS '<' INTVAL '>' // bits<x> type
|
|
|
|
/// Type ::= INT // int type
|
|
|
|
/// Type ::= LIST '<' Type '>' // list<x> type
|
|
|
|
/// Type ::= DAG // dag type
|
|
|
|
/// Type ::= ClassID // Record Type
|
|
|
|
///
|
|
|
|
RecTy *TGParser::ParseType() {
|
|
|
|
switch (Lex.getCode()) {
|
2014-04-09 04:50:04 +00:00
|
|
|
default: TokError("Unknown token when expecting a type"); return nullptr;
|
2011-07-18 17:02:57 +00:00
|
|
|
case tgtok::String: Lex.Lex(); return StringRecTy::get();
|
2012-01-13 03:38:34 +00:00
|
|
|
case tgtok::Code: Lex.Lex(); return StringRecTy::get();
|
2011-07-18 17:02:57 +00:00
|
|
|
case tgtok::Bit: Lex.Lex(); return BitRecTy::get();
|
|
|
|
case tgtok::Int: Lex.Lex(); return IntRecTy::get();
|
|
|
|
case tgtok::Dag: Lex.Lex(); return DagRecTy::get();
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::Id:
|
2011-07-18 17:02:57 +00:00
|
|
|
if (Record *R = ParseClassID()) return RecordRecTy::get(R);
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::Bits: {
|
|
|
|
if (Lex.Lex() != tgtok::less) { // Eat 'bits'
|
|
|
|
TokError("expected '<' after bits type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
|
|
|
|
TokError("expected integer in bits<n> type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2008-10-17 01:33:43 +00:00
|
|
|
uint64_t Val = Lex.getCurIntVal();
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.Lex() != tgtok::greater) { // Eat count.
|
|
|
|
TokError("expected '>' at end of bits<n> type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // Eat '>'
|
2011-07-18 17:02:57 +00:00
|
|
|
return BitsRecTy::get(Val);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
case tgtok::List: {
|
|
|
|
if (Lex.Lex() != tgtok::less) { // Eat 'bits'
|
|
|
|
TokError("expected '<' after list type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // Eat '<'
|
|
|
|
RecTy *SubType = ParseType();
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!SubType) return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected '>' at end of list<ty> type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // Eat '>'
|
2011-07-18 17:02:57 +00:00
|
|
|
return ListRecTy::get(SubType);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
|
|
|
|
/// has already been read.
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *TGParser::ParseIDValue(Record *CurRec,
|
2011-10-19 13:04:20 +00:00
|
|
|
const std::string &Name, SMLoc NameLoc,
|
|
|
|
IDParseMode Mode) {
|
2007-11-22 20:49:04 +00:00
|
|
|
if (CurRec) {
|
|
|
|
if (const RecordVal *RV = CurRec->getValue(Name))
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(Name, RV->getType());
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name, ":");
|
|
|
|
|
2011-10-05 22:42:54 +00:00
|
|
|
if (CurMultiClass)
|
2011-10-19 13:02:42 +00:00
|
|
|
TemplateArgName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name,
|
|
|
|
"::");
|
2011-10-05 22:42:54 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (CurRec->isTemplateArg(TemplateArgName)) {
|
|
|
|
const RecordVal *RV = CurRec->getValue(TemplateArgName);
|
|
|
|
assert(RV && "Template arg doesn't exist??");
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(TemplateArgName, RV->getType());
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (CurMultiClass) {
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name,
|
|
|
|
"::");
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (CurMultiClass->Rec.isTemplateArg(MCName)) {
|
|
|
|
const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
|
|
|
|
assert(RV && "Template arg doesn't exist??");
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(MCName, RV->getType());
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2012-02-22 16:09:41 +00:00
|
|
|
// If this is in a foreach loop, make sure it's not a loop iterator
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const auto &L : Loops) {
|
|
|
|
VarInit *IterVar = dyn_cast<VarInit>(L.IterVar);
|
2012-02-22 16:09:41 +00:00
|
|
|
if (IterVar && IterVar->getName() == Name)
|
|
|
|
return IterVar;
|
|
|
|
}
|
|
|
|
|
2011-10-19 13:04:21 +00:00
|
|
|
if (Mode == ParseNameMode)
|
|
|
|
return StringInit::get(Name);
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Record *D = Records.getDef(Name))
|
2011-07-18 17:02:57 +00:00
|
|
|
return DefInit::get(D);
|
2007-11-22 20:49:04 +00:00
|
|
|
|
2011-10-19 13:04:21 +00:00
|
|
|
if (Mode == ParseValueMode) {
|
|
|
|
Error(NameLoc, "Variable not defined: '" + Name + "'");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-10-19 13:04:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return StringInit::get(Name);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
2009-05-14 20:54:48 +00:00
|
|
|
/// ParseOperation - Parse an operator. This returns null on error.
|
|
|
|
///
|
|
|
|
/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
|
|
|
|
///
|
2014-06-10 20:10:08 +00:00
|
|
|
Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
2009-05-14 20:54:48 +00:00
|
|
|
switch (Lex.getCode()) {
|
|
|
|
default:
|
|
|
|
TokError("unknown operation");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-01-07 17:05:37 +00:00
|
|
|
case tgtok::XHead:
|
|
|
|
case tgtok::XTail:
|
|
|
|
case tgtok::XEmpty:
|
2009-05-14 21:22:49 +00:00
|
|
|
case tgtok::XCast: { // Value ::= !unop '(' Value ')'
|
|
|
|
UnOpInit::UnaryOp Code;
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *Type = nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2009-05-14 21:22:49 +00:00
|
|
|
switch (Lex.getCode()) {
|
2012-02-07 05:05:23 +00:00
|
|
|
default: llvm_unreachable("Unhandled code!");
|
2009-05-14 21:22:49 +00:00
|
|
|
case tgtok::XCast:
|
|
|
|
Lex.Lex(); // eat the operation
|
|
|
|
Code = UnOpInit::CAST;
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2009-05-14 21:22:49 +00:00
|
|
|
Type = ParseOperatorType();
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Type) {
|
2009-05-14 22:38:31 +00:00
|
|
|
TokError("did not get type for unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2009-05-14 22:38:31 +00:00
|
|
|
break;
|
2011-01-07 17:05:37 +00:00
|
|
|
case tgtok::XHead:
|
2009-05-14 22:38:31 +00:00
|
|
|
Lex.Lex(); // eat the operation
|
2011-01-07 17:05:37 +00:00
|
|
|
Code = UnOpInit::HEAD;
|
2009-05-14 22:38:31 +00:00
|
|
|
break;
|
2011-01-07 17:05:37 +00:00
|
|
|
case tgtok::XTail:
|
2009-05-14 22:38:31 +00:00
|
|
|
Lex.Lex(); // eat the operation
|
2011-01-07 17:05:37 +00:00
|
|
|
Code = UnOpInit::TAIL;
|
2009-05-14 22:38:31 +00:00
|
|
|
break;
|
2011-01-07 17:05:37 +00:00
|
|
|
case tgtok::XEmpty:
|
2009-05-14 22:38:31 +00:00
|
|
|
Lex.Lex(); // eat the operation
|
2011-01-07 17:05:37 +00:00
|
|
|
Code = UnOpInit::EMPTY;
|
2011-07-18 17:02:57 +00:00
|
|
|
Type = IntRecTy::get();
|
2009-05-14 21:22:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Lex.getCode() != tgtok::l_paren) {
|
|
|
|
TokError("expected '(' after unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '('
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *LHS = ParseValue(CurRec);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!LHS) return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2015-04-30 05:54:22 +00:00
|
|
|
if (Code == UnOpInit::HEAD ||
|
|
|
|
Code == UnOpInit::TAIL ||
|
|
|
|
Code == UnOpInit::EMPTY) {
|
2012-10-10 20:24:43 +00:00
|
|
|
ListInit *LHSl = dyn_cast<ListInit>(LHS);
|
|
|
|
StringInit *LHSs = dyn_cast<StringInit>(LHS);
|
|
|
|
TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!LHSl && !LHSs && !LHSt) {
|
2009-06-08 20:23:18 +00:00
|
|
|
TokError("expected list or string type argument in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
|
|
|
if (LHSt) {
|
2012-10-05 03:31:58 +00:00
|
|
|
ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
|
|
|
|
StringRecTy *SType = dyn_cast<StringRecTy>(LHSt->getType());
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!LType && !SType) {
|
2014-05-31 05:18:52 +00:00
|
|
|
TokError("expected list or string type argument in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-30 05:54:22 +00:00
|
|
|
if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!LHSl && !LHSt) {
|
2014-05-31 05:18:52 +00:00
|
|
|
TokError("expected list type argument in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-05-14 22:38:31 +00:00
|
|
|
if (LHSl && LHSl->getSize() == 0) {
|
|
|
|
TokError("empty list argument in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
|
|
|
if (LHSl) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Item = LHSl->getElement(0);
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *Itemt = dyn_cast<TypedInit>(Item);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Itemt) {
|
2009-05-14 22:38:31 +00:00
|
|
|
TokError("untyped list element in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
2011-01-07 17:05:37 +00:00
|
|
|
if (Code == UnOpInit::HEAD) {
|
2009-05-14 22:38:31 +00:00
|
|
|
Type = Itemt->getType();
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2011-07-18 17:02:57 +00:00
|
|
|
Type = ListRecTy::get(Itemt->getType());
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 22:38:31 +00:00
|
|
|
assert(LHSt && "expected list type argument in unary operator");
|
2012-10-05 03:31:58 +00:00
|
|
|
ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!LType) {
|
2014-05-31 05:18:52 +00:00
|
|
|
TokError("expected list type argument in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
2011-01-07 17:05:37 +00:00
|
|
|
if (Code == UnOpInit::HEAD) {
|
2009-05-14 22:38:31 +00:00
|
|
|
Type = LType->getElementType();
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 22:38:31 +00:00
|
|
|
Type = LType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-14 21:22:49 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_paren) {
|
|
|
|
TokError("expected ')' in unary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ')'
|
2011-07-29 19:07:07 +00:00
|
|
|
return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass);
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
|
|
|
case tgtok::XConcat:
|
2013-01-25 14:49:08 +00:00
|
|
|
case tgtok::XADD:
|
2014-08-05 09:43:25 +00:00
|
|
|
case tgtok::XAND:
|
2009-11-22 04:24:42 +00:00
|
|
|
case tgtok::XSRA:
|
2009-05-14 20:54:48 +00:00
|
|
|
case tgtok::XSRL:
|
|
|
|
case tgtok::XSHL:
|
2010-01-05 19:11:42 +00:00
|
|
|
case tgtok::XEq:
|
2014-05-07 10:13:19 +00:00
|
|
|
case tgtok::XListConcat:
|
2010-10-06 00:19:21 +00:00
|
|
|
case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')'
|
2010-10-05 23:58:18 +00:00
|
|
|
tgtok::TokKind OpTok = Lex.getCode();
|
|
|
|
SMLoc OpLoc = Lex.getLoc();
|
|
|
|
Lex.Lex(); // eat the operation
|
|
|
|
|
2009-05-14 20:54:48 +00:00
|
|
|
BinOpInit::BinaryOp Code;
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *Type = nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
switch (OpTok) {
|
2012-02-07 05:05:23 +00:00
|
|
|
default: llvm_unreachable("Unhandled code!");
|
2011-07-18 17:02:57 +00:00
|
|
|
case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break;
|
2013-01-25 14:49:08 +00:00
|
|
|
case tgtok::XADD: Code = BinOpInit::ADD; Type = IntRecTy::get(); break;
|
2014-08-05 09:43:25 +00:00
|
|
|
case tgtok::XAND: Code = BinOpInit::AND; Type = IntRecTy::get(); break;
|
2011-07-18 17:02:57 +00:00
|
|
|
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;
|
|
|
|
case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break;
|
2014-05-07 10:13:19 +00:00
|
|
|
case tgtok::XListConcat:
|
|
|
|
Code = BinOpInit::LISTCONCAT;
|
|
|
|
// We don't know the list type until we parse the first argument
|
|
|
|
break;
|
2009-11-22 04:24:42 +00:00
|
|
|
case tgtok::XStrConcat:
|
2009-05-14 20:54:48 +00:00
|
|
|
Code = BinOpInit::STRCONCAT;
|
2011-07-18 17:02:57 +00:00
|
|
|
Type = StringRecTy::get();
|
2009-05-14 20:54:48 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-10-23 07:32:37 +00:00
|
|
|
|
2009-05-14 20:54:48 +00:00
|
|
|
if (Lex.getCode() != tgtok::l_paren) {
|
|
|
|
TokError("expected '(' after binary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '('
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init*, 2> InitList;
|
2010-10-23 07:32:37 +00:00
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
InitList.push_back(ParseValue(CurRec));
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!InitList.back()) return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
while (Lex.getCode() == tgtok::comma) {
|
|
|
|
Lex.Lex(); // eat the ','
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
InitList.push_back(ParseValue(CurRec));
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!InitList.back()) return nullptr;
|
2010-10-05 23:58:18 +00:00
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::r_paren) {
|
2010-10-05 23:58:18 +00:00
|
|
|
TokError("expected ')' in operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ')'
|
2010-10-05 23:58:18 +00:00
|
|
|
|
2014-05-07 10:13:19 +00:00
|
|
|
// If we are doing !listconcat, we should know the type by now
|
|
|
|
if (OpTok == tgtok::XListConcat) {
|
|
|
|
if (VarInit *Arg0 = dyn_cast<VarInit>(InitList[0]))
|
|
|
|
Type = Arg0->getType();
|
|
|
|
else if (ListInit *Arg0 = dyn_cast<ListInit>(InitList[0]))
|
|
|
|
Type = Arg0->getType();
|
|
|
|
else {
|
|
|
|
InitList[0]->dump();
|
|
|
|
Error(OpLoc, "expected a list");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
// We allow multiple operands to associative operators like !strconcat as
|
|
|
|
// shorthand for nesting them.
|
2014-05-07 10:13:19 +00:00
|
|
|
if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT) {
|
2010-10-05 23:58:18 +00:00
|
|
|
while (InitList.size() > 2) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *RHS = InitList.pop_back_val();
|
2011-07-29 19:07:07 +00:00
|
|
|
RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))
|
|
|
|
->Fold(CurRec, CurMultiClass);
|
2010-10-05 23:58:18 +00:00
|
|
|
InitList.back() = RHS;
|
|
|
|
}
|
|
|
|
}
|
2010-10-23 07:32:37 +00:00
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
if (InitList.size() == 2)
|
2011-07-29 19:07:07 +00:00
|
|
|
return (BinOpInit::get(Code, InitList[0], InitList[1], Type))
|
2010-10-05 23:58:18 +00:00
|
|
|
->Fold(CurRec, CurMultiClass);
|
2010-10-23 07:32:37 +00:00
|
|
|
|
2010-10-05 23:58:18 +00:00
|
|
|
Error(OpLoc, "expected two operands to operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
|
2009-05-14 23:26:46 +00:00
|
|
|
case tgtok::XIf:
|
2009-05-14 22:23:47 +00:00
|
|
|
case tgtok::XForEach:
|
2009-05-14 21:54:42 +00:00
|
|
|
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
|
|
|
|
TernOpInit::TernaryOp Code;
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *Type = nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
|
|
|
|
tgtok::TokKind LexCode = Lex.getCode();
|
|
|
|
Lex.Lex(); // eat the operation
|
|
|
|
switch (LexCode) {
|
2012-02-07 05:05:23 +00:00
|
|
|
default: llvm_unreachable("Unhandled code!");
|
2009-05-14 23:26:46 +00:00
|
|
|
case tgtok::XIf:
|
|
|
|
Code = TernOpInit::IF;
|
|
|
|
break;
|
2009-05-14 22:23:47 +00:00
|
|
|
case tgtok::XForEach:
|
|
|
|
Code = TernOpInit::FOREACH;
|
|
|
|
break;
|
2009-05-14 21:54:42 +00:00
|
|
|
case tgtok::XSubst:
|
|
|
|
Code = TernOpInit::SUBST;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Lex.getCode() != tgtok::l_paren) {
|
|
|
|
TokError("expected '(' after ternary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '('
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *LHS = ParseValue(CurRec);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!LHS) return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::comma) {
|
|
|
|
TokError("expected ',' in ternary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ','
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-06-10 20:10:08 +00:00
|
|
|
Init *MHS = ParseValue(CurRec, ItemType);
|
|
|
|
if (!MHS)
|
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::comma) {
|
|
|
|
TokError("expected ',' in ternary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ','
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-06-10 20:10:08 +00:00
|
|
|
Init *RHS = ParseValue(CurRec, ItemType);
|
|
|
|
if (!RHS)
|
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::r_paren) {
|
|
|
|
TokError("expected ')' in binary operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ')'
|
|
|
|
|
|
|
|
switch (LexCode) {
|
2012-02-07 05:05:23 +00:00
|
|
|
default: llvm_unreachable("Unhandled code!");
|
2009-05-14 23:26:46 +00:00
|
|
|
case tgtok::XIf: {
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *MHSTy = nullptr;
|
|
|
|
RecTy *RHSTy = nullptr;
|
2010-12-13 01:46:19 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (TypedInit *MHSt = dyn_cast<TypedInit>(MHS))
|
2010-12-13 01:46:19 +00:00
|
|
|
MHSTy = MHSt->getType();
|
2012-10-10 20:24:43 +00:00
|
|
|
if (BitsInit *MHSbits = dyn_cast<BitsInit>(MHS))
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
MHSTy = BitsRecTy::get(MHSbits->getNumBits());
|
2012-10-10 20:24:47 +00:00
|
|
|
if (isa<BitInit>(MHS))
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
MHSTy = BitRecTy::get();
|
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (TypedInit *RHSt = dyn_cast<TypedInit>(RHS))
|
2010-12-13 01:46:19 +00:00
|
|
|
RHSTy = RHSt->getType();
|
2012-10-10 20:24:43 +00:00
|
|
|
if (BitsInit *RHSbits = dyn_cast<BitsInit>(RHS))
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
RHSTy = BitsRecTy::get(RHSbits->getNumBits());
|
2012-10-10 20:24:47 +00:00
|
|
|
if (isa<BitInit>(RHS))
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
RHSTy = BitRecTy::get();
|
|
|
|
|
|
|
|
// For UnsetInit, it's typed from the other hand.
|
2012-10-10 20:24:47 +00:00
|
|
|
if (isa<UnsetInit>(MHS))
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
MHSTy = RHSTy;
|
2012-10-10 20:24:47 +00:00
|
|
|
if (isa<UnsetInit>(RHS))
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
RHSTy = MHSTy;
|
2010-12-13 01:46:19 +00:00
|
|
|
|
|
|
|
if (!MHSTy || !RHSTy) {
|
2009-05-14 23:26:46 +00:00
|
|
|
TokError("could not get type for !if");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 23:26:46 +00:00
|
|
|
}
|
2010-12-13 01:46:19 +00:00
|
|
|
|
|
|
|
if (MHSTy->typeIsConvertibleTo(RHSTy)) {
|
|
|
|
Type = RHSTy;
|
|
|
|
} else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
|
|
|
|
Type = MHSTy;
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 23:26:46 +00:00
|
|
|
TokError("inconsistent types for !if");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 23:26:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-05-14 22:23:47 +00:00
|
|
|
case tgtok::XForEach: {
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!MHSt) {
|
2009-05-14 22:23:47 +00:00
|
|
|
TokError("could not get type for !foreach");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 22:23:47 +00:00
|
|
|
}
|
|
|
|
Type = MHSt->getType();
|
|
|
|
break;
|
|
|
|
}
|
2009-05-14 21:54:42 +00:00
|
|
|
case tgtok::XSubst: {
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!RHSt) {
|
2009-05-14 21:54:42 +00:00
|
|
|
TokError("could not get type for !subst");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
Type = RHSt->getType();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec,
|
2009-11-22 04:24:42 +00:00
|
|
|
CurMultiClass);
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseOperatorType - Parse a type for an operator. This returns
|
|
|
|
/// null on error.
|
|
|
|
///
|
|
|
|
/// OperatorType ::= '<' Type '>'
|
|
|
|
///
|
2009-08-12 22:10:57 +00:00
|
|
|
RecTy *TGParser::ParseOperatorType() {
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *Type = nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::less) {
|
|
|
|
TokError("expected type name for operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the <
|
|
|
|
|
|
|
|
Type = ParseType();
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Type) {
|
2009-05-14 20:54:48 +00:00
|
|
|
TokError("expected type name for operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected type name for operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the >
|
|
|
|
|
|
|
|
return Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseSimpleValue - Parse a tblgen value. This returns null on error.
|
|
|
|
///
|
|
|
|
/// SimpleValue ::= IDValue
|
|
|
|
/// SimpleValue ::= INTVAL
|
2009-03-11 17:08:13 +00:00
|
|
|
/// SimpleValue ::= STRVAL+
|
2007-11-22 20:49:04 +00:00
|
|
|
/// SimpleValue ::= CODEFRAGMENT
|
|
|
|
/// SimpleValue ::= '?'
|
|
|
|
/// SimpleValue ::= '{' ValueList '}'
|
|
|
|
/// SimpleValue ::= ID '<' ValueListNE '>'
|
|
|
|
/// SimpleValue ::= '[' ValueList ']'
|
|
|
|
/// SimpleValue ::= '(' IDValue DagArgList ')'
|
|
|
|
/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
|
2013-01-25 14:49:08 +00:00
|
|
|
/// SimpleValue ::= ADDTOK '(' Value ',' Value ')'
|
2007-11-22 20:49:04 +00:00
|
|
|
/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
|
|
|
|
/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
|
|
|
|
/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
|
2014-05-07 10:13:19 +00:00
|
|
|
/// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
|
2007-11-22 20:49:04 +00:00
|
|
|
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
|
|
|
|
///
|
2011-10-19 13:04:20 +00:00
|
|
|
Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
|
|
|
IDParseMode Mode) {
|
2014-04-09 04:50:04 +00:00
|
|
|
Init *R = nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
switch (Lex.getCode()) {
|
|
|
|
default: TokError("Unknown token when parsing a value"); break;
|
2011-10-19 13:04:43 +00:00
|
|
|
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);
|
2011-07-29 19:07:07 +00:00
|
|
|
case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break;
|
2014-08-07 05:47:00 +00:00
|
|
|
case tgtok::BinaryIntVal: {
|
|
|
|
auto BinaryVal = Lex.getCurBinaryIntVal();
|
|
|
|
SmallVector<Init*, 16> Bits(BinaryVal.second);
|
|
|
|
for (unsigned i = 0, e = BinaryVal.second; i != e; ++i)
|
2014-08-07 12:07:33 +00:00
|
|
|
Bits[i] = BitInit::get(BinaryVal.first & (1LL << i));
|
2014-08-07 05:47:00 +00:00
|
|
|
R = BitsInit::get(Bits);
|
|
|
|
Lex.Lex();
|
|
|
|
break;
|
|
|
|
}
|
2009-03-11 17:08:13 +00:00
|
|
|
case tgtok::StrVal: {
|
|
|
|
std::string Val = Lex.getCurStrVal();
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-03-26 16:17:51 +00:00
|
|
|
// Handle multiple consecutive concatenated strings.
|
2009-03-11 17:08:13 +00:00
|
|
|
while (Lex.getCode() == tgtok::StrVal) {
|
|
|
|
Val += Lex.getCurStrVal();
|
|
|
|
Lex.Lex();
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
R = StringInit::get(Val);
|
2009-03-11 17:08:13 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::CodeFragment:
|
2012-01-13 03:38:34 +00:00
|
|
|
R = StringInit::get(Lex.getCurStrVal());
|
2010-10-06 04:31:40 +00:00
|
|
|
Lex.Lex();
|
|
|
|
break;
|
|
|
|
case tgtok::question:
|
2011-07-29 19:07:07 +00:00
|
|
|
R = UnsetInit::get();
|
2010-10-06 04:31:40 +00:00
|
|
|
Lex.Lex();
|
|
|
|
break;
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::Id: {
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc NameLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
std::string Name = Lex.getCurStrVal();
|
|
|
|
if (Lex.Lex() != tgtok::less) // consume the Id.
|
2011-10-19 13:04:20 +00:00
|
|
|
return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Value ::= ID '<' ValueListNE '>'
|
|
|
|
if (Lex.Lex() == tgtok::greater) {
|
|
|
|
TokError("expected non-empty value list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-06-08 20:23:18 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// This is a CLASS<initvalslist> expression. This is supposed to synthesize
|
|
|
|
// a new anonymous definition, deriving from CLASS<initvalslist> with no
|
|
|
|
// body.
|
|
|
|
Record *Class = Records.getClass(Name);
|
|
|
|
if (!Class) {
|
|
|
|
Error(NameLoc, "Expected a class name, got '" + Name + "'");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-06-08 20:23:18 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> ValueList = ParseValueList(CurRec, Class);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (ValueList.empty()) return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-08 20:23:18 +00:00
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected '>' at end of value list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '>'
|
2013-01-10 18:50:11 +00:00
|
|
|
SMLoc EndLoc = Lex.getLoc();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Create the new record, set it as CurRec temporarily.
|
Speculatively qualify some llvm::make_unique calls trying to please MSVC
It was failing with this kind of error:
C:\b\build\slave\CrWinClang\build\src\third_party\llvm\lib\TableGen\TGParser.cpp(1243) : error C2668: 'llvm::make_unique' : ambiguous call to overloaded function
C:\b\build\slave\CrWinClang\build\src\third_party\llvm\include\llvm/ADT/STLExtras.h(408): could be 'std::unique_ptr<llvm::Record,std::default_delete<_Ty>> llvm::make_unique<llvm::Record,std::string,llvm::SMLoc&,llvm::RecordKeeper&,bool>(std::string &&,llvm::SMLoc &,llvm::RecordKeeper &,bool &&)'
with
[
_Ty=llvm::Record
]
C:\b\depot_tools\win_toolchain\vs2013_files\win8sdk\bin\..\..\VC\include\memory(1637): or 'std::unique_ptr<llvm::Record,std::default_delete<_Ty>> std::make_unique<llvm::Record,std::string,llvm::SMLoc&,llvm::RecordKeeper&,bool>(std::string &&,llvm::SMLoc &,llvm::RecordKeeper &,bool &&)' [found using argument-dependent lookup]
with
[
_Ty=llvm::Record
]
while trying to match the argument list '(std::string, llvm::SMLoc, llvm::RecordKeeper, bool)'
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222967 91177308-0d34-0410-b5e6-96231b3b80d8
2014-11-30 00:24:43 +00:00
|
|
|
auto NewRecOwner = llvm::make_unique<Record>(GetNewAnonymousName(), NameLoc,
|
|
|
|
Records, /*IsAnonymous=*/true);
|
2014-11-29 05:31:10 +00:00
|
|
|
Record *NewRec = NewRecOwner.get(); // Keep a copy since we may release.
|
2007-11-22 20:49:04 +00:00
|
|
|
SubClassReference SCRef;
|
2013-01-10 18:50:11 +00:00
|
|
|
SCRef.RefRange = SMRange(NameLoc, EndLoc);
|
2007-11-22 20:49:04 +00:00
|
|
|
SCRef.Rec = Class;
|
|
|
|
SCRef.TemplateArgs = ValueList;
|
|
|
|
// Add info about the subclass to NewRec.
|
2014-11-29 05:31:10 +00:00
|
|
|
if (AddSubClass(NewRec, SCRef))
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2014-11-29 05:31:10 +00:00
|
|
|
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
if (!CurMultiClass) {
|
|
|
|
NewRec->resolveReferences();
|
2014-11-29 05:52:51 +00:00
|
|
|
Records.addDef(std::move(NewRecOwner));
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
} else {
|
2014-09-16 17:14:13 +00:00
|
|
|
// This needs to get resolved once the multiclass template arguments are
|
|
|
|
// known before any use.
|
|
|
|
NewRec->setResolveFirst(true);
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
// Otherwise, we're inside a multiclass, add it to the multiclass.
|
2014-12-11 05:25:33 +00:00
|
|
|
CurMultiClass->DefPrototypes.push_back(std::move(NewRecOwner));
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
|
|
|
|
// Copy the template arguments for the multiclass into the def.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) {
|
|
|
|
const RecordVal *RV = CurMultiClass->Rec.getValue(TArg);
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
assert(RV && "Template arg doesn't exist?");
|
|
|
|
NewRec->addValue(*RV);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can't return the prototype def here, instead return:
|
|
|
|
// !cast<ItemType>(!strconcat(NAME, AnonName)).
|
|
|
|
const RecordVal *MCNameRV = CurMultiClass->Rec.getValue("NAME");
|
|
|
|
assert(MCNameRV && "multiclass record must have a NAME");
|
|
|
|
|
|
|
|
return UnOpInit::get(UnOpInit::CAST,
|
|
|
|
BinOpInit::get(BinOpInit::STRCONCAT,
|
|
|
|
VarInit::get(MCNameRV->getName(),
|
|
|
|
MCNameRV->getType()),
|
|
|
|
NewRec->getNameInit(),
|
|
|
|
StringRecTy::get()),
|
|
|
|
Class->getDefInit()->getType());
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// The result of the expression is a reference to the new record.
|
2011-07-18 17:02:57 +00:00
|
|
|
return DefInit::get(NewRec);
|
2009-11-22 04:24:42 +00:00
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::l_brace: { // Value ::= '{' ValueList '}'
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc BraceLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // eat the '{'
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> Vals;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
Vals = ParseValueList(CurRec);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (Vals.empty()) return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
TokError("expected '}' at end of bit list value");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '}'
|
2009-11-22 04:24:42 +00:00
|
|
|
|
Change the { } expression in tablegen to accept sized binary literals which are not just 0 and 1.
It also allows nested { } expressions, as now that they are sized, we can merge pull bits from the nested value.
In the current behaviour, everything in { } must have been convertible to a single bit.
However, now that binary literals are sized, its useful to be able to initialize a range of bits.
So, for example, its now possible to do
bits<8> x = { 0, 1, { 0b1001 }, 0, 0b0 }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215086 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 05:47:07 +00:00
|
|
|
SmallVector<Init *, 16> NewBits;
|
2011-07-29 19:07:00 +00:00
|
|
|
|
Change the { } expression in tablegen to accept sized binary literals which are not just 0 and 1.
It also allows nested { } expressions, as now that they are sized, we can merge pull bits from the nested value.
In the current behaviour, everything in { } must have been convertible to a single bit.
However, now that binary literals are sized, its useful to be able to initialize a range of bits.
So, for example, its now possible to do
bits<8> x = { 0, 1, { 0b1001 }, 0, 0b0 }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215086 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 05:47:07 +00:00
|
|
|
// 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.
|
2007-11-22 20:49:04 +00:00
|
|
|
for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
|
2014-08-29 22:43:30 +00:00
|
|
|
// FIXME: The following two loops would not be duplicated
|
|
|
|
// if the API was a little more orthogonal.
|
|
|
|
|
Change the { } expression in tablegen to accept sized binary literals which are not just 0 and 1.
It also allows nested { } expressions, as now that they are sized, we can merge pull bits from the nested value.
In the current behaviour, everything in { } must have been convertible to a single bit.
However, now that binary literals are sized, its useful to be able to initialize a range of bits.
So, for example, its now possible to do
bits<8> x = { 0, 1, { 0b1001 }, 0, 0b0 }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215086 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 05:47:07 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2014-08-29 19:41:04 +00:00
|
|
|
// 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.
|
|
|
|
}
|
Change the { } expression in tablegen to accept sized binary literals which are not just 0 and 1.
It also allows nested { } expressions, as now that they are sized, we can merge pull bits from the nested value.
In the current behaviour, everything in { } must have been convertible to a single bit.
However, now that binary literals are sized, its useful to be able to initialize a range of bits.
So, for example, its now possible to do
bits<8> x = { 0, 1, { 0b1001 }, 0, 0b0 }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215086 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 05:47:07 +00:00
|
|
|
// All other values must be convertible to just a single bit.
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get());
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Bit) {
|
2007-11-22 21:06:59 +00:00
|
|
|
Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+
|
|
|
|
") is not convertable to a bit");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
Change the { } expression in tablegen to accept sized binary literals which are not just 0 and 1.
It also allows nested { } expressions, as now that they are sized, we can merge pull bits from the nested value.
In the current behaviour, everything in { } must have been convertible to a single bit.
However, now that binary literals are sized, its useful to be able to initialize a range of bits.
So, for example, its now possible to do
bits<8> x = { 0, 1, { 0b1001 }, 0, 0b0 }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215086 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 05:47:07 +00:00
|
|
|
NewBits.push_back(Bit);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
Change the { } expression in tablegen to accept sized binary literals which are not just 0 and 1.
It also allows nested { } expressions, as now that they are sized, we can merge pull bits from the nested value.
In the current behaviour, everything in { } must have been convertible to a single bit.
However, now that binary literals are sized, its useful to be able to initialize a range of bits.
So, for example, its now possible to do
bits<8> x = { 0, 1, { 0b1001 }, 0, 0b0 }
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215086 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 05:47:07 +00:00
|
|
|
std::reverse(NewBits.begin(), NewBits.end());
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
case tgtok::l_square: { // Value ::= '[' ValueList ']'
|
|
|
|
Lex.Lex(); // eat the '['
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> Vals;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *DeducedEltTy = nullptr;
|
|
|
|
ListRecTy *GivenListTy = nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (ItemType) {
|
2012-10-05 03:31:58 +00:00
|
|
|
ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!ListType) {
|
2014-06-26 22:52:05 +00:00
|
|
|
std::string s;
|
|
|
|
raw_string_ostream ss(s);
|
2013-08-06 22:51:21 +00:00
|
|
|
ss << "Type mismatch for list, expected list type, got "
|
|
|
|
<< ItemType->getAsString();
|
|
|
|
TokError(ss.str());
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
GivenListTy = ListType;
|
2009-11-22 04:24:42 +00:00
|
|
|
}
|
2009-06-08 20:23:18 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_square) {
|
2014-04-09 04:50:04 +00:00
|
|
|
Vals = ParseValueList(CurRec, nullptr,
|
|
|
|
GivenListTy ? GivenListTy->getElementType() : nullptr);
|
|
|
|
if (Vals.empty()) return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
if (Lex.getCode() != tgtok::r_square) {
|
|
|
|
TokError("expected ']' at end of list value");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ']'
|
2009-06-08 20:23:18 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *GivenEltTy = nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
if (Lex.getCode() == tgtok::less) {
|
|
|
|
// Optional list element type
|
|
|
|
Lex.Lex(); // eat the '<'
|
|
|
|
|
|
|
|
GivenEltTy = ParseType();
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!GivenEltTy) {
|
2009-06-08 20:23:18 +00:00
|
|
|
// Couldn't parse element type
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::greater) {
|
|
|
|
TokError("expected '>' at end of list element type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '>'
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check elements
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *EltTy = nullptr;
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Init *V : Vals) {
|
|
|
|
TypedInit *TArg = dyn_cast<TypedInit>(V);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!TArg) {
|
2009-06-08 20:23:18 +00:00
|
|
|
TokError("Untyped list element");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
2014-04-09 04:50:04 +00:00
|
|
|
if (EltTy) {
|
2009-06-08 20:23:18 +00:00
|
|
|
EltTy = resolveTypes(EltTy, TArg->getType());
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!EltTy) {
|
2009-06-08 20:23:18 +00:00
|
|
|
TokError("Incompatible types in list elements");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-06-08 20:23:18 +00:00
|
|
|
EltTy = TArg->getType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (GivenEltTy) {
|
|
|
|
if (EltTy) {
|
2009-06-08 20:23:18 +00:00
|
|
|
// Verify consistency
|
|
|
|
if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
|
|
|
|
TokError("Incompatible types in list elements");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
EltTy = GivenEltTy;
|
|
|
|
}
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!EltTy) {
|
|
|
|
if (!ItemType) {
|
2009-06-08 20:23:18 +00:00
|
|
|
TokError("No type for list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
DeducedEltTy = GivenListTy->getElementType();
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-06-08 20:23:18 +00:00
|
|
|
// Make sure the deduced type is compatible with the given type
|
|
|
|
if (GivenListTy) {
|
|
|
|
if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
|
|
|
|
TokError("Element type mismatch for list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
DeducedEltTy = EltTy;
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return ListInit::get(Vals, DeducedEltTy);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
|
|
|
|
Lex.Lex(); // eat the '('
|
2010-10-06 00:19:21 +00:00
|
|
|
if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) {
|
2008-04-10 04:48:34 +00:00
|
|
|
TokError("expected identifier in dag init");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2008-04-10 04:48:34 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Operator = ParseValue(CurRec);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Operator) return nullptr;
|
2009-04-22 20:18:10 +00:00
|
|
|
|
2009-03-19 05:21:56 +00:00
|
|
|
// If the operator name is present, parse it.
|
|
|
|
std::string OperatorName;
|
|
|
|
if (Lex.getCode() == tgtok::colon) {
|
|
|
|
if (Lex.Lex() != tgtok::VarName) { // eat the ':'
|
|
|
|
TokError("expected variable name in dag operator");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-03-19 05:21:56 +00:00
|
|
|
}
|
|
|
|
OperatorName = Lex.getCurStrVal();
|
|
|
|
Lex.Lex(); // eat the VarName.
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<std::pair<llvm::Init*, std::string> > DagArgs;
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_paren) {
|
|
|
|
DagArgs = ParseDagArgList(CurRec);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (DagArgs.empty()) return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_paren) {
|
|
|
|
TokError("expected ')' in dag init");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the ')'
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return DagInit::get(Operator, OperatorName, DagArgs);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-01-07 17:05:37 +00:00
|
|
|
case tgtok::XHead:
|
|
|
|
case tgtok::XTail:
|
|
|
|
case tgtok::XEmpty:
|
2009-05-14 21:22:49 +00:00
|
|
|
case tgtok::XCast: // Value ::= !unop '(' Value ')'
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::XConcat:
|
2013-01-25 14:49:08 +00:00
|
|
|
case tgtok::XADD:
|
2014-08-05 09:43:25 +00:00
|
|
|
case tgtok::XAND:
|
2009-11-22 04:24:42 +00:00
|
|
|
case tgtok::XSRA:
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::XSRL:
|
|
|
|
case tgtok::XSHL:
|
2010-01-05 19:11:42 +00:00
|
|
|
case tgtok::XEq:
|
2014-05-07 10:13:19 +00:00
|
|
|
case tgtok::XListConcat:
|
2010-10-06 00:19:21 +00:00
|
|
|
case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
|
2009-05-14 23:26:46 +00:00
|
|
|
case tgtok::XIf:
|
2009-05-14 22:23:47 +00:00
|
|
|
case tgtok::XForEach:
|
2009-05-14 21:54:42 +00:00
|
|
|
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
|
2014-06-10 20:10:08 +00:00
|
|
|
return ParseOperation(CurRec, ItemType);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseValue - Parse a tblgen value. This returns null on error.
|
|
|
|
///
|
|
|
|
/// Value ::= SimpleValue ValueSuffix*
|
|
|
|
/// ValueSuffix ::= '{' BitList '}'
|
|
|
|
/// ValueSuffix ::= '[' BitList ']'
|
|
|
|
/// ValueSuffix ::= '.' ID
|
|
|
|
///
|
2011-10-19 13:04:20 +00:00
|
|
|
Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
|
|
|
Init *Result = ParseSimpleValue(CurRec, ItemType, Mode);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result) return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Parse the suffixes now if present.
|
|
|
|
while (1) {
|
|
|
|
switch (Lex.getCode()) {
|
|
|
|
default: return Result;
|
|
|
|
case tgtok::l_brace: {
|
2012-02-22 16:09:41 +00:00
|
|
|
if (Mode == ParseNameMode || Mode == ParseForeachMode)
|
2011-10-19 13:04:26 +00:00
|
|
|
// This is the beginning of the object body.
|
|
|
|
return Result;
|
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc CurlyLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // eat the '{'
|
|
|
|
std::vector<unsigned> Ranges = ParseRangeList();
|
2014-04-09 04:50:04 +00:00
|
|
|
if (Ranges.empty()) return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Reverse the bitlist.
|
|
|
|
std::reverse(Ranges.begin(), Ranges.end());
|
|
|
|
Result = Result->convertInitializerBitRange(Ranges);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result) {
|
2007-11-22 20:49:04 +00:00
|
|
|
Error(CurlyLoc, "Invalid bit range for value");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Eat the '}'.
|
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
TokError("expected '}' at end of bit range list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case tgtok::l_square: {
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc SquareLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // eat the '['
|
|
|
|
std::vector<unsigned> Ranges = ParseRangeList();
|
2014-04-09 04:50:04 +00:00
|
|
|
if (Ranges.empty()) return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
Result = Result->convertInitListSlice(Ranges);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result) {
|
2007-11-22 20:49:04 +00:00
|
|
|
Error(SquareLoc, "Invalid range for list slice");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Eat the ']'.
|
|
|
|
if (Lex.getCode() != tgtok::r_square) {
|
|
|
|
TokError("expected ']' at end of list slice");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case tgtok::period:
|
|
|
|
if (Lex.Lex() != tgtok::Id) { // eat the .
|
|
|
|
TokError("expected field identifier after '.'");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
if (!Result->getFieldType(Lex.getCurStrVal())) {
|
|
|
|
TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
|
2007-11-22 21:06:59 +00:00
|
|
|
Result->getAsString() + "'");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
Result = FieldInit::get(Result, Lex.getCurStrVal());
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // eat field name
|
|
|
|
break;
|
2011-10-19 13:04:43 +00:00
|
|
|
|
|
|
|
case tgtok::paste:
|
|
|
|
SMLoc PasteLoc = Lex.getLoc();
|
|
|
|
|
|
|
|
// Create a !strconcat() operation, first casting each operand to
|
|
|
|
// a string if necessary.
|
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *LHS = dyn_cast<TypedInit>(Result);
|
2011-10-19 13:04:43 +00:00
|
|
|
if (!LHS) {
|
|
|
|
Error(PasteLoc, "LHS of paste is not typed!");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-10-19 13:04:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (LHS->getType() != StringRecTy::get()) {
|
|
|
|
LHS = UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get());
|
|
|
|
}
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
TypedInit *RHS = nullptr;
|
2011-10-19 13:04:43 +00:00
|
|
|
|
|
|
|
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);
|
2012-10-10 20:24:43 +00:00
|
|
|
RHS = dyn_cast<TypedInit>(RHSResult);
|
2011-10-19 13:04:43 +00:00
|
|
|
if (!RHS) {
|
|
|
|
Error(PasteLoc, "RHS of paste is not typed!");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-10-19 13:04:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseDagArgList - Parse the argument list for a dag literal expression.
|
|
|
|
///
|
Allow TableGen DAG arguments to be just a name.
DAG arguments can optionally be named:
(dag node, node:$name)
With this change, the node is also optional:
(dag node, node:$name, $name)
The missing node is treated as an UnsetInit, so the above is equivalent
to:
(dag node, node:$name, ?:$name)
This syntax is useful in output patterns where we currently require the
types of variables to be repeated:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr i32:$b, i32:$c)>;
This is preferable:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr $b, $c)>;
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177843 91177308-0d34-0410-b5e6-96231b3b80d8
2013-03-24 19:36:51 +00:00
|
|
|
/// DagArg ::= Value (':' VARNAME)?
|
|
|
|
/// DagArg ::= VARNAME
|
|
|
|
/// DagArgList ::= DagArg
|
|
|
|
/// DagArgList ::= DagArgList ',' DagArg
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<std::pair<llvm::Init*, std::string> >
|
2007-11-22 20:49:04 +00:00
|
|
|
TGParser::ParseDagArgList(Record *CurRec) {
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<std::pair<llvm::Init*, std::string> > Result;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
while (1) {
|
Allow TableGen DAG arguments to be just a name.
DAG arguments can optionally be named:
(dag node, node:$name)
With this change, the node is also optional:
(dag node, node:$name, $name)
The missing node is treated as an UnsetInit, so the above is equivalent
to:
(dag node, node:$name, ?:$name)
This syntax is useful in output patterns where we currently require the
types of variables to be repeated:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr i32:$b, i32:$c)>;
This is preferable:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr $b, $c)>;
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177843 91177308-0d34-0410-b5e6-96231b3b80d8
2013-03-24 19:36:51 +00:00
|
|
|
// DagArg ::= VARNAME
|
|
|
|
if (Lex.getCode() == tgtok::VarName) {
|
|
|
|
// A missing value is treated like '?'.
|
|
|
|
Result.push_back(std::make_pair(UnsetInit::get(), Lex.getCurStrVal()));
|
|
|
|
Lex.Lex();
|
|
|
|
} else {
|
|
|
|
// DagArg ::= Value (':' VARNAME)?
|
|
|
|
Init *Val = ParseValue(CurRec);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Val)
|
2011-07-29 22:43:06 +00:00
|
|
|
return std::vector<std::pair<llvm::Init*, std::string> >();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
Allow TableGen DAG arguments to be just a name.
DAG arguments can optionally be named:
(dag node, node:$name)
With this change, the node is also optional:
(dag node, node:$name, $name)
The missing node is treated as an UnsetInit, so the above is equivalent
to:
(dag node, node:$name, ?:$name)
This syntax is useful in output patterns where we currently require the
types of variables to be repeated:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr i32:$b, i32:$c)>;
This is preferable:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr $b, $c)>;
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177843 91177308-0d34-0410-b5e6-96231b3b80d8
2013-03-24 19:36:51 +00:00
|
|
|
// If the variable name is present, add it.
|
|
|
|
std::string VarName;
|
|
|
|
if (Lex.getCode() == tgtok::colon) {
|
|
|
|
if (Lex.Lex() != tgtok::VarName) { // eat the ':'
|
|
|
|
TokError("expected variable name in dag literal");
|
|
|
|
return std::vector<std::pair<llvm::Init*, std::string> >();
|
|
|
|
}
|
|
|
|
VarName = Lex.getCurStrVal();
|
|
|
|
Lex.Lex(); // eat the VarName.
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
Allow TableGen DAG arguments to be just a name.
DAG arguments can optionally be named:
(dag node, node:$name)
With this change, the node is also optional:
(dag node, node:$name, $name)
The missing node is treated as an UnsetInit, so the above is equivalent
to:
(dag node, node:$name, ?:$name)
This syntax is useful in output patterns where we currently require the
types of variables to be repeated:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr i32:$b, i32:$c)>;
This is preferable:
def : Pat<(subc i32:$b, i32:$c), (SUBCCrr $b, $c)>;
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177843 91177308-0d34-0410-b5e6-96231b3b80d8
2013-03-24 19:36:51 +00:00
|
|
|
Result.push_back(std::make_pair(Val, VarName));
|
|
|
|
}
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::comma) break;
|
2009-11-22 04:24:42 +00:00
|
|
|
Lex.Lex(); // eat the ','
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ParseValueList - Parse a comma separated list of values, returning them as a
|
|
|
|
/// vector. Note that this always expects to be able to parse at least one
|
|
|
|
/// value. It returns an empty list if this is not possible.
|
|
|
|
///
|
|
|
|
/// ValueList ::= Value (',' Value)
|
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec,
|
2011-07-11 23:06:52 +00:00
|
|
|
RecTy *EltTy) {
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> Result;
|
2009-06-08 20:23:18 +00:00
|
|
|
RecTy *ItemType = EltTy;
|
2009-06-29 19:59:52 +00:00
|
|
|
unsigned int ArgN = 0;
|
2014-04-09 04:50:04 +00:00
|
|
|
if (ArgsRec && !EltTy) {
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs();
|
2015-01-15 11:41:30 +00:00
|
|
|
if (TArgs.empty()) {
|
2012-01-20 20:02:39 +00:00
|
|
|
TokError("template argument provided to non-template class");
|
|
|
|
return std::vector<Init*>();
|
|
|
|
}
|
2009-06-08 20:23:18 +00:00
|
|
|
const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
|
2011-09-19 18:26:07 +00:00
|
|
|
if (!RV) {
|
|
|
|
errs() << "Cannot find template arg " << ArgN << " (" << TArgs[ArgN]
|
|
|
|
<< ")\n";
|
|
|
|
}
|
2009-06-08 20:23:18 +00:00
|
|
|
assert(RV && "Template argument record not found??");
|
|
|
|
ItemType = RV->getType();
|
|
|
|
++ArgN;
|
|
|
|
}
|
|
|
|
Result.push_back(ParseValue(CurRec, ItemType));
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result.back()) return std::vector<Init*>();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
while (Lex.getCode() == tgtok::comma) {
|
|
|
|
Lex.Lex(); // Eat the comma
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (ArgsRec && !EltTy) {
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &TArgs = ArgsRec->getTemplateArgs();
|
2009-06-29 19:59:52 +00:00
|
|
|
if (ArgN >= TArgs.size()) {
|
|
|
|
TokError("too many template arguments");
|
2011-07-29 22:43:06 +00:00
|
|
|
return std::vector<Init*>();
|
2009-11-22 04:24:42 +00:00
|
|
|
}
|
2009-06-08 20:23:18 +00:00
|
|
|
const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
|
|
|
|
assert(RV && "Template argument record not found??");
|
|
|
|
ItemType = RV->getType();
|
|
|
|
++ArgN;
|
|
|
|
}
|
|
|
|
Result.push_back(ParseValue(CurRec, ItemType));
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Result.back()) return std::vector<Init*>();
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ParseDeclaration - Read a declaration, returning the name of field ID, or an
|
|
|
|
/// empty string on error. This can happen in a number of different context's,
|
|
|
|
/// including within a def or in the template args for a def (which which case
|
|
|
|
/// CurRec will be non-null) and within the template args for a multiclass (in
|
|
|
|
/// which case CurRec will be null, but CurMultiClass will be set). This can
|
|
|
|
/// also happen within a def that is within a multiclass, which will set both
|
|
|
|
/// CurRec and CurMultiClass.
|
|
|
|
///
|
|
|
|
/// Declaration ::= FIELD? Type ID ('=' Value)?
|
|
|
|
///
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *TGParser::ParseDeclaration(Record *CurRec,
|
2007-11-22 20:49:04 +00:00
|
|
|
bool ParsingTemplateArgs) {
|
|
|
|
// Read the field prefix if present.
|
|
|
|
bool HasField = Lex.getCode() == tgtok::Field;
|
|
|
|
if (HasField) Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
RecTy *Type = ParseType();
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Type) return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::Id) {
|
|
|
|
TokError("Expected identifier in declaration");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc IdLoc = Lex.getLoc();
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *DeclName = StringInit::get(Lex.getCurStrVal());
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (ParsingTemplateArgs) {
|
|
|
|
if (CurRec) {
|
2011-10-19 13:02:42 +00:00
|
|
|
DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
|
2007-11-22 20:49:04 +00:00
|
|
|
} else {
|
|
|
|
assert(CurMultiClass);
|
|
|
|
}
|
|
|
|
if (CurMultiClass)
|
2011-10-19 13:02:42 +00:00
|
|
|
DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName,
|
|
|
|
"::");
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Add the value.
|
|
|
|
if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField)))
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If a value is present, parse it.
|
|
|
|
if (Lex.getCode() == tgtok::equal) {
|
|
|
|
Lex.Lex();
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc ValLoc = Lex.getLoc();
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Val = ParseValue(CurRec, Type);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Val ||
|
2007-11-22 20:49:04 +00:00
|
|
|
SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
|
2014-07-31 01:44:00 +00:00
|
|
|
// 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;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return DeclName;
|
|
|
|
}
|
|
|
|
|
2012-02-22 16:09:41 +00:00
|
|
|
/// ParseForeachDeclaration - Read a foreach declaration, returning
|
|
|
|
/// the name of the declared object or a NULL Init on error. Return
|
|
|
|
/// the name of the parsed initializer list through ForeachListName.
|
|
|
|
///
|
2012-05-24 22:17:39 +00:00
|
|
|
/// ForeachDeclaration ::= ID '=' '[' ValueList ']'
|
|
|
|
/// ForeachDeclaration ::= ID '=' '{' RangeList '}'
|
|
|
|
/// ForeachDeclaration ::= ID '=' RangePiece
|
2012-02-22 16:09:41 +00:00
|
|
|
///
|
2012-05-24 22:17:33 +00:00
|
|
|
VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
2012-02-22 16:09:41 +00:00
|
|
|
if (Lex.getCode() != tgtok::Id) {
|
|
|
|
TokError("Expected identifier in foreach declaration");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Init *DeclName = StringInit::get(Lex.getCurStrVal());
|
|
|
|
Lex.Lex();
|
|
|
|
|
|
|
|
// If a value is present, parse it.
|
|
|
|
if (Lex.getCode() != tgtok::equal) {
|
|
|
|
TokError("Expected '=' in foreach declaration");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // Eat the '='
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
RecTy *IterType = nullptr;
|
2012-05-24 22:17:39 +00:00
|
|
|
std::vector<unsigned> Ranges;
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:39 +00:00
|
|
|
switch (Lex.getCode()) {
|
2014-04-09 04:50:04 +00:00
|
|
|
default: TokError("Unknown token when expecting a range list"); return nullptr;
|
2012-05-24 22:17:39 +00:00
|
|
|
case tgtok::l_square: { // '[' ValueList ']'
|
2014-04-09 04:50:04 +00:00
|
|
|
Init *List = ParseSimpleValue(nullptr, nullptr, ParseForeachMode);
|
2012-10-10 20:24:43 +00:00
|
|
|
ForeachListValue = dyn_cast<ListInit>(List);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!ForeachListValue) {
|
2012-05-24 22:17:39 +00:00
|
|
|
TokError("Expected a Value list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-05-24 22:17:39 +00:00
|
|
|
}
|
|
|
|
RecTy *ValueType = ForeachListValue->getType();
|
2012-10-05 03:31:58 +00:00
|
|
|
ListRecTy *ListType = dyn_cast<ListRecTy>(ValueType);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!ListType) {
|
2012-05-24 22:17:39 +00:00
|
|
|
TokError("Value list is not of list type");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-05-24 22:17:39 +00:00
|
|
|
}
|
|
|
|
IterType = ListType->getElementType();
|
|
|
|
break;
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
|
2012-05-24 22:17:39 +00:00
|
|
|
case tgtok::IntVal: { // RangePiece.
|
|
|
|
if (ParseRangePiece(Ranges))
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-05-24 22:17:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case tgtok::l_brace: { // '{' RangeList '}'
|
|
|
|
Lex.Lex(); // eat the '{'
|
|
|
|
Ranges = ParseRangeList();
|
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
TokError("expected '}' at end of bit range list");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-05-24 22:17:39 +00:00
|
|
|
}
|
|
|
|
Lex.Lex();
|
|
|
|
break;
|
|
|
|
}
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
|
2012-05-24 22:17:39 +00:00
|
|
|
if (!Ranges.empty()) {
|
|
|
|
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]));
|
|
|
|
ForeachListValue = ListInit::get(Values, IterType);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IterType)
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2012-02-22 16:09:41 +00:00
|
|
|
|
2012-05-24 22:17:39 +00:00
|
|
|
return VarInit::get(DeclName, IterType);
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseTemplateArgList - Read a template argument list, which is a non-empty
|
|
|
|
/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
|
|
|
|
/// template args for a def, which may or may not be in a multiclass. If null,
|
|
|
|
/// these are the template args for a multiclass.
|
|
|
|
///
|
|
|
|
/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
|
2009-11-22 04:24:42 +00:00
|
|
|
///
|
2007-11-22 20:49:04 +00:00
|
|
|
bool TGParser::ParseTemplateArgList(Record *CurRec) {
|
|
|
|
assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
|
|
|
|
Lex.Lex(); // eat the '<'
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Read the first declaration.
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!TemplArg)
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
TheRecToAddTo->addTemplateArg(TemplArg);
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
while (Lex.getCode() == tgtok::comma) {
|
|
|
|
Lex.Lex(); // eat the ','
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Read the following declarations.
|
|
|
|
TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!TemplArg)
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
|
|
|
TheRecToAddTo->addTemplateArg(TemplArg);
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::greater)
|
|
|
|
return TokError("expected '>' at end of template argument list");
|
|
|
|
Lex.Lex(); // eat the '>'.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ParseBodyItem - Parse a single item at within the body of a def or class.
|
|
|
|
///
|
|
|
|
/// BodyItem ::= Declaration ';'
|
|
|
|
/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
|
|
|
|
bool TGParser::ParseBodyItem(Record *CurRec) {
|
|
|
|
if (Lex.getCode() != tgtok::Let) {
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!ParseDeclaration(CurRec, false))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::semi)
|
|
|
|
return TokError("expected ';' after declaration");
|
|
|
|
Lex.Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// LET ID OptionalRangeList '=' Value ';'
|
|
|
|
if (Lex.Lex() != tgtok::Id)
|
|
|
|
return TokError("expected field identifier after let");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc IdLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
std::string FieldName = Lex.getCurStrVal();
|
|
|
|
Lex.Lex(); // eat the field name.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
std::vector<unsigned> BitList;
|
2009-11-22 04:24:42 +00:00
|
|
|
if (ParseOptionalBitList(BitList))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
|
|
|
std::reverse(BitList.begin(), BitList.end());
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::equal)
|
|
|
|
return TokError("expected '=' in let expression");
|
|
|
|
Lex.Lex(); // eat the '='.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-06-08 20:23:18 +00:00
|
|
|
RecordVal *Field = CurRec->getValue(FieldName);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Field)
|
2009-06-08 20:23:18 +00:00
|
|
|
return TokError("Value '" + FieldName + "' unknown!");
|
|
|
|
|
|
|
|
RecTy *Type = Field->getType();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Val = ParseValue(CurRec, Type);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Val) return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::semi)
|
|
|
|
return TokError("expected ';' after let expression");
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseBody - Read the body of a class or def. Return true on error, false on
|
|
|
|
/// success.
|
|
|
|
///
|
|
|
|
/// Body ::= ';'
|
|
|
|
/// Body ::= '{' BodyList '}'
|
|
|
|
/// BodyList BodyItem*
|
|
|
|
///
|
|
|
|
bool TGParser::ParseBody(Record *CurRec) {
|
|
|
|
// If this is a null definition, just eat the semi and return.
|
|
|
|
if (Lex.getCode() == tgtok::semi) {
|
|
|
|
Lex.Lex();
|
|
|
|
return false;
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::l_brace)
|
|
|
|
return TokError("Expected ';' or '{' to start body");
|
|
|
|
// Eat the '{'.
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
while (Lex.getCode() != tgtok::r_brace)
|
|
|
|
if (ParseBodyItem(CurRec))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Eat the '}'.
|
|
|
|
Lex.Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-09 04:49:14 +00:00
|
|
|
/// \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))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseObjectBody - Parse the body of a def or class. This consists of an
|
|
|
|
/// optional ClassList followed by a Body. CurRec is the current def or class
|
|
|
|
/// that is being parsed.
|
|
|
|
///
|
|
|
|
/// ObjectBody ::= BaseClassList Body
|
|
|
|
/// BaseClassList ::= /*empty*/
|
|
|
|
/// BaseClassList ::= ':' BaseClassListNE
|
|
|
|
/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
|
|
|
|
///
|
|
|
|
bool TGParser::ParseObjectBody(Record *CurRec) {
|
|
|
|
// If there is a baseclass list, read it.
|
|
|
|
if (Lex.getCode() == tgtok::colon) {
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Read all of the subclasses.
|
|
|
|
SubClassReference SubClass = ParseSubClassReference(CurRec, false);
|
|
|
|
while (1) {
|
|
|
|
// Check for error.
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!SubClass.Rec) return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Add it.
|
|
|
|
if (AddSubClass(CurRec, SubClass))
|
|
|
|
return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::comma) break;
|
|
|
|
Lex.Lex(); // eat ','.
|
|
|
|
SubClass = ParseSubClassReference(CurRec, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-09 04:49:14 +00:00
|
|
|
if (ApplyLetStack(CurRec))
|
|
|
|
return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return ParseBody(CurRec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseDef - Parse and return a top level or multiclass def, return the record
|
|
|
|
/// corresponding to it. This returns null on error.
|
|
|
|
///
|
|
|
|
/// DefInst ::= DEF ObjectName ObjectBody
|
|
|
|
///
|
2010-06-10 02:42:59 +00:00
|
|
|
bool TGParser::ParseDef(MultiClass *CurMultiClass) {
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc DefLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
|
2009-11-22 04:24:42 +00:00
|
|
|
Lex.Lex(); // Eat the 'def' token.
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
// Parse ObjectName and make a record for it.
|
2014-11-29 05:31:10 +00:00
|
|
|
std::unique_ptr<Record> CurRecOwner;
|
2013-01-10 18:50:05 +00:00
|
|
|
Init *Name = ParseObjectName(CurMultiClass);
|
|
|
|
if (Name)
|
2014-11-29 05:31:10 +00:00
|
|
|
CurRecOwner = make_unique<Record>(Name, DefLoc, Records);
|
2013-01-10 18:50:05 +00:00
|
|
|
else
|
Speculatively qualify some llvm::make_unique calls trying to please MSVC
It was failing with this kind of error:
C:\b\build\slave\CrWinClang\build\src\third_party\llvm\lib\TableGen\TGParser.cpp(1243) : error C2668: 'llvm::make_unique' : ambiguous call to overloaded function
C:\b\build\slave\CrWinClang\build\src\third_party\llvm\include\llvm/ADT/STLExtras.h(408): could be 'std::unique_ptr<llvm::Record,std::default_delete<_Ty>> llvm::make_unique<llvm::Record,std::string,llvm::SMLoc&,llvm::RecordKeeper&,bool>(std::string &&,llvm::SMLoc &,llvm::RecordKeeper &,bool &&)'
with
[
_Ty=llvm::Record
]
C:\b\depot_tools\win_toolchain\vs2013_files\win8sdk\bin\..\..\VC\include\memory(1637): or 'std::unique_ptr<llvm::Record,std::default_delete<_Ty>> std::make_unique<llvm::Record,std::string,llvm::SMLoc&,llvm::RecordKeeper&,bool>(std::string &&,llvm::SMLoc &,llvm::RecordKeeper &,bool &&)' [found using argument-dependent lookup]
with
[
_Ty=llvm::Record
]
while trying to match the argument list '(std::string, llvm::SMLoc, llvm::RecordKeeper, bool)'
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222967 91177308-0d34-0410-b5e6-96231b3b80d8
2014-11-30 00:24:43 +00:00
|
|
|
CurRecOwner = llvm::make_unique<Record>(GetNewAnonymousName(), DefLoc,
|
|
|
|
Records, /*IsAnonymous=*/true);
|
2014-11-29 05:31:10 +00:00
|
|
|
Record *CurRec = CurRecOwner.get(); // Keep a copy since we may release.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2012-05-24 22:17:36 +00:00
|
|
|
if (!CurMultiClass && Loops.empty()) {
|
2007-11-22 20:49:04 +00:00
|
|
|
// Top-level def definition.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Ensure redefinition doesn't happen.
|
2014-11-29 05:31:10 +00:00
|
|
|
if (Records.getDef(CurRec->getNameInitAsString()))
|
|
|
|
return Error(DefLoc, "def '" + CurRec->getNameInitAsString()+
|
|
|
|
"' already defined");
|
2014-11-29 05:52:51 +00:00
|
|
|
Records.addDef(std::move(CurRecOwner));
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
|
|
|
|
if (ParseObjectBody(CurRec))
|
|
|
|
return true;
|
2012-05-24 22:17:36 +00:00
|
|
|
} else if (CurMultiClass) {
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
// Parse the body before adding this prototype to the DefPrototypes vector.
|
|
|
|
// That way implicit definitions will be added to the DefPrototypes vector
|
|
|
|
// before this object, instantiated prior to defs derived from this object,
|
|
|
|
// and this available for indirect name resolution when defs derived from
|
|
|
|
// this object are instantiated.
|
2014-11-29 05:31:10 +00:00
|
|
|
if (ParseObjectBody(CurRec))
|
[TableGen] Correctly generate implicit anonymous prototype defs in multiclasses
Even within a multiclass, we had been generating concrete implicit anonymous
defs when parsing values (generally in value lists). This behavior was
incorrect, and led to errors when multiclass parameters were used in the
parameter list of the implicit anonymous def.
If we had some multiclass:
multiclass mc<string n> {
... : SomeClass<SomeOtherClass<n> >
The capture of the multiclass parameter 'n' would not work correctly, and
depending on how the implicit SomeOtherClass was used, either TableGen would
ignore something it shouldn't, or would crash.
To fix this problem, when inside a multiclass, we generate prototype anonymous
defs for implicit anonymous defs (just as we do for explicit anonymous defs).
Within the multiclass, the current record prototype is populated with a node
that is essentially: !cast<SomeOtherClass>(!strconcat(NAME, anon_value_name)).
This is then resolved to the correct concrete anonymous def, in the usual way,
when NAME is resolved during multiclass instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198348 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-02 20:47:09 +00:00
|
|
|
return true;
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Otherwise, a def inside a multiclass, add it to the multiclass.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const auto &Proto : CurMultiClass->DefPrototypes)
|
|
|
|
if (Proto->getNameInit() == CurRec->getNameInit())
|
2014-11-29 05:31:10 +00:00
|
|
|
return Error(DefLoc, "def '" + CurRec->getNameInitAsString() +
|
|
|
|
"' already defined in this multiclass!");
|
2014-12-11 05:25:33 +00:00
|
|
|
CurMultiClass->DefPrototypes.push_back(std::move(CurRecOwner));
|
2014-08-08 00:29:54 +00:00
|
|
|
} else if (ParseObjectBody(CurRec)) {
|
2010-06-10 02:42:59 +00:00
|
|
|
return true;
|
2014-08-08 00:29:54 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!CurMultiClass) // Def's in multiclasses aren't really defs.
|
2011-08-10 18:27:46 +00:00
|
|
|
// 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.
|
2007-11-22 20:49:04 +00:00
|
|
|
CurRec->resolveReferences();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If ObjectBody has template arguments, it's an error.
|
|
|
|
assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
|
2010-06-10 02:42:59 +00:00
|
|
|
|
|
|
|
if (CurMultiClass) {
|
|
|
|
// Copy the template arguments for the multiclass into the def.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) {
|
|
|
|
const RecordVal *RV = CurMultiClass->Rec.getValue(TArg);
|
2010-06-10 02:42:59 +00:00
|
|
|
assert(RV && "Template arg doesn't exist?");
|
|
|
|
CurRec->addValue(*RV);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-24 22:17:33 +00:00
|
|
|
if (ProcessForeachDefs(CurRec, DefLoc)) {
|
2014-11-29 05:31:10 +00:00
|
|
|
return Error(DefLoc, "Could not process loops for def" +
|
|
|
|
CurRec->getNameInitAsString());
|
2012-02-22 16:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseForeach - Parse a for statement. Return the record corresponding
|
|
|
|
/// to it. This returns true on error.
|
|
|
|
///
|
|
|
|
/// Foreach ::= FOREACH Declaration IN '{ ObjectList '}'
|
|
|
|
/// Foreach ::= FOREACH Declaration IN Object
|
|
|
|
///
|
|
|
|
bool TGParser::ParseForeach(MultiClass *CurMultiClass) {
|
|
|
|
assert(Lex.getCode() == tgtok::Foreach && "Unknown tok");
|
|
|
|
Lex.Lex(); // Eat the 'for' token.
|
|
|
|
|
|
|
|
// Make a temporary object to record items associated with the for
|
|
|
|
// loop.
|
2014-04-09 04:50:04 +00:00
|
|
|
ListInit *ListValue = nullptr;
|
2012-05-24 22:17:33 +00:00
|
|
|
VarInit *IterName = ParseForeachDeclaration(ListValue);
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!IterName)
|
2012-02-22 16:09:41 +00:00
|
|
|
return TokError("expected declaration in for");
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::In)
|
|
|
|
return TokError("Unknown tok");
|
|
|
|
Lex.Lex(); // Eat the in
|
|
|
|
|
|
|
|
// Create a loop object and remember it.
|
|
|
|
Loops.push_back(ForeachLoop(IterName, ListValue));
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::l_brace) {
|
|
|
|
// FOREACH Declaration IN Object
|
|
|
|
if (ParseObject(CurMultiClass))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SMLoc BraceLoc = Lex.getLoc();
|
|
|
|
// Otherwise, this is a group foreach.
|
|
|
|
Lex.Lex(); // eat the '{'.
|
|
|
|
|
|
|
|
// Parse the object list.
|
|
|
|
if (ParseObjectList(CurMultiClass))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
TokError("expected '}' at end of foreach command");
|
|
|
|
return Error(BraceLoc, "to match this '{'");
|
|
|
|
}
|
|
|
|
Lex.Lex(); // Eat the }
|
|
|
|
}
|
|
|
|
|
|
|
|
// We've processed everything in this loop.
|
|
|
|
Loops.pop_back();
|
|
|
|
|
2010-06-10 02:42:59 +00:00
|
|
|
return false;
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseClass - Parse a tblgen class definition.
|
|
|
|
///
|
|
|
|
/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
|
|
|
|
///
|
|
|
|
bool TGParser::ParseClass() {
|
|
|
|
assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::Id)
|
|
|
|
return TokError("expected class name after 'class' keyword");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
Record *CurRec = Records.getClass(Lex.getCurStrVal());
|
|
|
|
if (CurRec) {
|
|
|
|
// If the body was previously defined, this is an error.
|
2011-10-19 13:04:13 +00:00
|
|
|
if (CurRec->getValues().size() > 1 || // Account for NAME.
|
2007-11-22 20:49:04 +00:00
|
|
|
!CurRec->getSuperClasses().empty() ||
|
|
|
|
!CurRec->getTemplateArgs().empty())
|
2015-04-30 05:54:22 +00:00
|
|
|
return TokError("Class '" + CurRec->getNameInitAsString() +
|
|
|
|
"' already defined");
|
2007-11-22 20:49:04 +00:00
|
|
|
} else {
|
|
|
|
// If this is the first reference to this class, create and add it.
|
2014-11-30 00:31:49 +00:00
|
|
|
auto NewRec =
|
|
|
|
llvm::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records);
|
2014-11-29 05:52:51 +00:00
|
|
|
CurRec = NewRec.get();
|
|
|
|
Records.addClass(std::move(NewRec));
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the name.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If there are template args, parse them.
|
|
|
|
if (Lex.getCode() == tgtok::less)
|
|
|
|
if (ParseTemplateArgList(CurRec))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Finally, parse the object body.
|
|
|
|
return ParseObjectBody(CurRec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseLetList - Parse a non-empty list of assignment expressions into a list
|
|
|
|
/// of LetRecords.
|
|
|
|
///
|
|
|
|
/// LetList ::= LetItem (',' LetItem)*
|
|
|
|
/// LetItem ::= ID OptionalRangeList '=' Value
|
|
|
|
///
|
|
|
|
std::vector<LetRecord> TGParser::ParseLetList() {
|
|
|
|
std::vector<LetRecord> Result;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
while (1) {
|
|
|
|
if (Lex.getCode() != tgtok::Id) {
|
|
|
|
TokError("expected identifier in let definition");
|
|
|
|
return std::vector<LetRecord>();
|
|
|
|
}
|
|
|
|
std::string Name = Lex.getCurStrVal();
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc NameLoc = Lex.getLoc();
|
2009-11-22 04:24:42 +00:00
|
|
|
Lex.Lex(); // Eat the identifier.
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
// Check for an optional RangeList.
|
|
|
|
std::vector<unsigned> Bits;
|
2009-11-22 04:24:42 +00:00
|
|
|
if (ParseOptionalRangeList(Bits))
|
2007-11-22 20:49:04 +00:00
|
|
|
return std::vector<LetRecord>();
|
|
|
|
std::reverse(Bits.begin(), Bits.end());
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::equal) {
|
|
|
|
TokError("expected '=' in let expression");
|
|
|
|
return std::vector<LetRecord>();
|
|
|
|
}
|
|
|
|
Lex.Lex(); // eat the '='.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
Init *Val = ParseValue(nullptr);
|
|
|
|
if (!Val) return std::vector<LetRecord>();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Now that we have everything, add the record.
|
|
|
|
Result.push_back(LetRecord(Name, Bits, Val, NameLoc));
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::comma)
|
|
|
|
return Result;
|
2009-11-22 04:24:42 +00:00
|
|
|
Lex.Lex(); // eat the comma.
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
|
2010-06-10 02:42:59 +00:00
|
|
|
/// different related productions. This works inside multiclasses too.
|
2007-11-22 20:49:04 +00:00
|
|
|
///
|
|
|
|
/// Object ::= LET LetList IN '{' ObjectList '}'
|
|
|
|
/// Object ::= LET LetList IN Object
|
|
|
|
///
|
2010-06-10 02:42:59 +00:00
|
|
|
bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
|
2007-11-22 20:49:04 +00:00
|
|
|
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Add this entry to the let stack.
|
|
|
|
std::vector<LetRecord> LetInfo = ParseLetList();
|
|
|
|
if (LetInfo.empty()) return true;
|
2014-10-03 18:33:16 +00:00
|
|
|
LetStack.push_back(std::move(LetInfo));
|
2007-11-22 20:49:04 +00:00
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::In)
|
|
|
|
return TokError("expected 'in' at end of top-level 'let'");
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If this is a scalar let, just handle it now
|
|
|
|
if (Lex.getCode() != tgtok::l_brace) {
|
|
|
|
// LET LetList IN Object
|
2010-06-10 02:42:59 +00:00
|
|
|
if (ParseObject(CurMultiClass))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
|
|
|
} else { // Object ::= LETCommand '{' ObjectList '}'
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc BraceLoc = Lex.getLoc();
|
2007-11-22 20:49:04 +00:00
|
|
|
// Otherwise, this is a group let.
|
|
|
|
Lex.Lex(); // eat the '{'.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Parse the object list.
|
2010-06-10 02:42:59 +00:00
|
|
|
if (ParseObjectList(CurMultiClass))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
if (Lex.getCode() != tgtok::r_brace) {
|
|
|
|
TokError("expected '}' at end of top level let command");
|
|
|
|
return Error(BraceLoc, "to match this '{'");
|
|
|
|
}
|
|
|
|
Lex.Lex();
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// Outside this let scope, this let block is not active.
|
|
|
|
LetStack.pop_back();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseMultiClass - Parse a multiclass definition.
|
|
|
|
///
|
2009-04-28 19:41:44 +00:00
|
|
|
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
|
2013-01-09 02:11:55 +00:00
|
|
|
/// ':' BaseMultiClassList '{' MultiClassObject+ '}'
|
|
|
|
/// MultiClassObject ::= DefInst
|
|
|
|
/// MultiClassObject ::= MultiClassInst
|
|
|
|
/// MultiClassObject ::= DefMInst
|
|
|
|
/// MultiClassObject ::= LETCommand '{' ObjectList '}'
|
|
|
|
/// MultiClassObject ::= LETCommand Object
|
2007-11-22 20:49:04 +00:00
|
|
|
///
|
|
|
|
bool TGParser::ParseMultiClass() {
|
|
|
|
assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
|
|
|
|
Lex.Lex(); // Eat the multiclass token.
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::Id)
|
|
|
|
return TokError("expected identifier after multiclass for name");
|
|
|
|
std::string Name = Lex.getCurStrVal();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-12-11 05:25:30 +00:00
|
|
|
auto Result =
|
|
|
|
MultiClasses.insert(std::make_pair(Name,
|
|
|
|
llvm::make_unique<MultiClass>(Name, Lex.getLoc(),Records)));
|
|
|
|
|
|
|
|
if (!Result.second)
|
2007-11-22 20:49:04 +00:00
|
|
|
return TokError("multiclass '" + Name + "' already defined");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-12-11 05:25:30 +00:00
|
|
|
CurMultiClass = Result.first->second.get();
|
2007-11-22 20:49:04 +00:00
|
|
|
Lex.Lex(); // Eat the identifier.
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If there are template args, parse them.
|
|
|
|
if (Lex.getCode() == tgtok::less)
|
2014-04-09 04:50:04 +00:00
|
|
|
if (ParseTemplateArgList(nullptr))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
|
|
|
|
2009-04-24 16:55:41 +00:00
|
|
|
bool inherits = false;
|
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// If there are submulticlasses, parse them.
|
|
|
|
if (Lex.getCode() == tgtok::colon) {
|
2009-04-24 16:55:41 +00:00
|
|
|
inherits = true;
|
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
Lex.Lex();
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// Read all of the submulticlasses.
|
2009-04-28 19:41:44 +00:00
|
|
|
SubMultiClassReference SubMultiClass =
|
|
|
|
ParseSubMultiClassReference(CurMultiClass);
|
2009-04-22 16:42:54 +00:00
|
|
|
while (1) {
|
|
|
|
// Check for error.
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!SubMultiClass.MC) return true;
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
// Add it.
|
|
|
|
if (AddSubMultiClass(CurMultiClass, SubMultiClass))
|
|
|
|
return true;
|
2009-04-28 19:41:44 +00:00
|
|
|
|
2009-04-22 16:42:54 +00:00
|
|
|
if (Lex.getCode() != tgtok::comma) break;
|
|
|
|
Lex.Lex(); // eat ','.
|
|
|
|
SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-24 16:55:41 +00:00
|
|
|
if (Lex.getCode() != tgtok::l_brace) {
|
|
|
|
if (!inherits)
|
|
|
|
return TokError("expected '{' in multiclass definition");
|
2014-11-29 16:05:27 +00:00
|
|
|
if (Lex.getCode() != tgtok::semi)
|
2009-11-22 04:24:42 +00:00
|
|
|
return TokError("expected ';' in multiclass definition");
|
2014-11-29 16:05:27 +00:00
|
|
|
Lex.Lex(); // eat the ';'.
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-04-24 16:55:41 +00:00
|
|
|
if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
|
|
|
|
return TokError("multiclass must contain at least one def");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2010-06-05 02:11:52 +00:00
|
|
|
while (Lex.getCode() != tgtok::r_brace) {
|
2010-06-10 02:42:59 +00:00
|
|
|
switch (Lex.getCode()) {
|
2014-11-29 16:05:27 +00:00
|
|
|
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;
|
2010-06-10 02:42:59 +00:00
|
|
|
}
|
2010-06-05 02:11:52 +00:00
|
|
|
}
|
2009-04-24 16:55:41 +00:00
|
|
|
Lex.Lex(); // eat the '}'.
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
CurMultiClass = nullptr;
|
2007-11-22 20:49:04 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-10-05 22:42:07 +00:00
|
|
|
Record *TGParser::
|
|
|
|
InstantiateMulticlassDef(MultiClass &MC,
|
|
|
|
Record *DefProto,
|
2014-01-02 19:35:33 +00:00
|
|
|
Init *&DefmPrefix,
|
2013-01-10 18:50:11 +00:00
|
|
|
SMRange DefmPrefixRange) {
|
2011-10-19 13:04:31 +00:00
|
|
|
// We need to preserve DefProto so it can be reused for later
|
|
|
|
// instantiations, so create a new Record to inherit from it.
|
|
|
|
|
2011-10-05 22:42:07 +00:00
|
|
|
// 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.
|
|
|
|
|
2013-01-10 18:50:05 +00:00
|
|
|
bool IsAnonymous = false;
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!DefmPrefix) {
|
2011-10-19 13:04:31 +00:00
|
|
|
DefmPrefix = StringInit::get(GetNewAnonymousName());
|
2013-01-10 18:50:05 +00:00
|
|
|
IsAnonymous = true;
|
|
|
|
}
|
2011-10-19 13:04:31 +00:00
|
|
|
|
|
|
|
Init *DefName = DefProto->getNameInit();
|
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
StringInit *DefNameString = dyn_cast<StringInit>(DefName);
|
2011-10-19 13:04:31 +00:00
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
if (DefNameString) {
|
2011-10-19 13:04:43 +00:00
|
|
|
// We have a fully expanded string so there are no operators to
|
|
|
|
// resolve. We should concatenate the given prefix and name.
|
2011-10-19 13:04:31 +00:00
|
|
|
DefName =
|
|
|
|
BinOpInit::get(BinOpInit::STRCONCAT,
|
|
|
|
UnOpInit::get(UnOpInit::CAST, DefmPrefix,
|
|
|
|
StringRecTy::get())->Fold(DefProto, &MC),
|
|
|
|
DefName, StringRecTy::get())->Fold(DefProto, &MC);
|
|
|
|
}
|
|
|
|
|
Print out the location of expanded multiclass defs in TableGen errors.
When reporting an error for a defm, we would previously only report the
location of the outer defm, which is not always where the error is.
Now we also print the location of the expanded multiclass defs:
lib/Target/X86/X86InstrSSE.td:2902:12: error: foo
defm ADD : basic_sse12_fp_binop_s<0x58, "add", fadd, SSE_ALU_ITINS_S>,
^
lib/Target/X86/X86InstrSSE.td:2801:11: note: instantiated from multiclass
defm PD : sse12_fp_packed<opc, !strconcat(OpcodeStr, "pd"), OpNode, VR128,
^
lib/Target/X86/X86InstrSSE.td:194:5: note: instantiated from multiclass
def rm : PI<opc, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
^
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162409 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-22 23:33:58 +00:00
|
|
|
// Make a trail of SMLocs from the multiclass instantiations.
|
2013-01-10 18:50:11 +00:00
|
|
|
SmallVector<SMLoc, 4> Locs(1, DefmPrefixRange.Start);
|
Print out the location of expanded multiclass defs in TableGen errors.
When reporting an error for a defm, we would previously only report the
location of the outer defm, which is not always where the error is.
Now we also print the location of the expanded multiclass defs:
lib/Target/X86/X86InstrSSE.td:2902:12: error: foo
defm ADD : basic_sse12_fp_binop_s<0x58, "add", fadd, SSE_ALU_ITINS_S>,
^
lib/Target/X86/X86InstrSSE.td:2801:11: note: instantiated from multiclass
defm PD : sse12_fp_packed<opc, !strconcat(OpcodeStr, "pd"), OpNode, VR128,
^
lib/Target/X86/X86InstrSSE.td:194:5: note: instantiated from multiclass
def rm : PI<opc, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
^
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162409 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-22 23:33:58 +00:00
|
|
|
Locs.append(DefProto->getLoc().begin(), DefProto->getLoc().end());
|
2014-11-29 05:31:10 +00:00
|
|
|
auto CurRec = make_unique<Record>(DefName, Locs, Records, IsAnonymous);
|
2011-10-05 22:42:07 +00:00
|
|
|
|
|
|
|
SubClassReference Ref;
|
2013-01-10 18:50:11 +00:00
|
|
|
Ref.RefRange = DefmPrefixRange;
|
2011-10-05 22:42:07 +00:00
|
|
|
Ref.Rec = DefProto;
|
2014-11-29 05:31:10 +00:00
|
|
|
AddSubClass(CurRec.get(), Ref);
|
2011-10-05 22:42:07 +00:00
|
|
|
|
TableGen: Allow use of #NAME# outside of 'def' names.
Previously, def NAME values were only populated, and references to NAME
resolved, when NAME was referenced in the 'def' entry of the multiclass
sub-entry. e.g.,
multiclass foo<...> {
def prefix_#NAME : ...
}
It's useful, however, to be able to reference NAME even when the default
def name is used. For example, when a multiclass has 'def : Pat<...>'
or 'def : InstAlias<...>' entries which refer to earlier instruction
definitions in the same multiclass. e.g.,
multiclass myMulti<RegisterClass rc> {
def _r : myI<(outs rc:$d), (ins rc:$r), "r $d, $r", []>;
def : InstAlias<\"wilma $r\", (!cast<Instruction>(NAME#\"_r\") rc:$r, rc:$r)>;
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161198 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-02 18:46:42 +00:00
|
|
|
// 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.
|
2014-11-29 05:31:10 +00:00
|
|
|
if (SetValue(CurRec.get(), Ref.RefRange.Start, "NAME",
|
|
|
|
std::vector<unsigned>(), DefmPrefix)) {
|
2015-04-30 05:54:22 +00:00
|
|
|
Error(DefmPrefixRange.Start, "Could not resolve " +
|
|
|
|
CurRec->getNameInitAsString() + ":NAME to '" +
|
|
|
|
DefmPrefix->getAsUnquotedString() + "'");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
TableGen: Allow use of #NAME# outside of 'def' names.
Previously, def NAME values were only populated, and references to NAME
resolved, when NAME was referenced in the 'def' entry of the multiclass
sub-entry. e.g.,
multiclass foo<...> {
def prefix_#NAME : ...
}
It's useful, however, to be able to reference NAME even when the default
def name is used. For example, when a multiclass has 'def : Pat<...>'
or 'def : InstAlias<...>' entries which refer to earlier instruction
definitions in the same multiclass. e.g.,
multiclass myMulti<RegisterClass rc> {
def _r : myI<(outs rc:$d), (ins rc:$r), "r $d, $r", []>;
def : InstAlias<\"wilma $r\", (!cast<Instruction>(NAME#\"_r\") rc:$r, rc:$r)>;
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161198 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-02 18:46:42 +00:00
|
|
|
}
|
2011-10-19 13:04:35 +00:00
|
|
|
|
TableGen: Allow use of #NAME# outside of 'def' names.
Previously, def NAME values were only populated, and references to NAME
resolved, when NAME was referenced in the 'def' entry of the multiclass
sub-entry. e.g.,
multiclass foo<...> {
def prefix_#NAME : ...
}
It's useful, however, to be able to reference NAME even when the default
def name is used. For example, when a multiclass has 'def : Pat<...>'
or 'def : InstAlias<...>' entries which refer to earlier instruction
definitions in the same multiclass. e.g.,
multiclass myMulti<RegisterClass rc> {
def _r : myI<(outs rc:$d), (ins rc:$r), "r $d, $r", []>;
def : InstAlias<\"wilma $r\", (!cast<Instruction>(NAME#\"_r\") rc:$r, rc:$r)>;
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161198 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-02 18:46:42 +00:00
|
|
|
// If the DefNameString didn't resolve, we probably have a reference to
|
|
|
|
// NAME and need to replace it. We need to do at least this much greedily,
|
|
|
|
// otherwise nested multiclasses will end up with incorrect NAME expansions.
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!DefNameString) {
|
2011-10-19 13:04:35 +00:00
|
|
|
RecordVal *DefNameRV = CurRec->getValue("NAME");
|
|
|
|
CurRec->resolveReferencesTo(DefNameRV);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!CurMultiClass) {
|
TableGen: Allow use of #NAME# outside of 'def' names.
Previously, def NAME values were only populated, and references to NAME
resolved, when NAME was referenced in the 'def' entry of the multiclass
sub-entry. e.g.,
multiclass foo<...> {
def prefix_#NAME : ...
}
It's useful, however, to be able to reference NAME even when the default
def name is used. For example, when a multiclass has 'def : Pat<...>'
or 'def : InstAlias<...>' entries which refer to earlier instruction
definitions in the same multiclass. e.g.,
multiclass myMulti<RegisterClass rc> {
def _r : myI<(outs rc:$d), (ins rc:$r), "r $d, $r", []>;
def : InstAlias<\"wilma $r\", (!cast<Instruction>(NAME#\"_r\") rc:$r, rc:$r)>;
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161198 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-02 18:46:42 +00:00
|
|
|
// Now that we're at the top level, resolve all NAME references
|
|
|
|
// in the resultant defs that weren't in the def names themselves.
|
|
|
|
RecordVal *DefNameRV = CurRec->getValue("NAME");
|
|
|
|
CurRec->resolveReferencesTo(DefNameRV);
|
|
|
|
|
|
|
|
// 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
|
2011-10-19 13:04:35 +00:00
|
|
|
// 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())) {
|
2013-01-10 18:50:11 +00:00
|
|
|
Error(DefmPrefixRange.Start, "def '" + CurRec->getNameInitAsString() +
|
2011-10-19 13:04:35 +00:00
|
|
|
"' already defined, instantiating defm with subdef '" +
|
|
|
|
DefProto->getNameInitAsString() + "'");
|
2014-04-09 04:50:04 +00:00
|
|
|
return nullptr;
|
2011-10-19 13:04:35 +00:00
|
|
|
}
|
|
|
|
|
2014-11-29 05:31:10 +00:00
|
|
|
Record *CurRecSave = CurRec.get(); // Keep a copy before we release.
|
2014-11-29 05:52:51 +00:00
|
|
|
Records.addDef(std::move(CurRec));
|
2014-11-29 05:31:10 +00:00
|
|
|
return CurRecSave;
|
2011-10-19 13:04:35 +00:00
|
|
|
}
|
|
|
|
|
2014-11-29 05:31:10 +00:00
|
|
|
// 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();
|
2011-10-05 22:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC,
|
|
|
|
Record *CurRec,
|
|
|
|
SMLoc DefmPrefixLoc,
|
|
|
|
SMLoc SubClassLoc,
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &TArgs,
|
2011-10-05 22:42:07 +00:00
|
|
|
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()) {
|
2015-04-30 05:54:22 +00:00
|
|
|
return Error(SubClassLoc, "value not specified for template argument #" +
|
|
|
|
utostr(i) + " (" + TArgs[i]->getAsUnquotedString() +
|
|
|
|
") of multiclassclass '" + MC.Rec.getNameInitAsString() +
|
|
|
|
"'");
|
2011-10-05 22:42:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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.
|
2013-01-09 04:49:14 +00:00
|
|
|
if (ApplyLetStack(CurRec))
|
|
|
|
return Error(DefmPrefixLoc, "when instantiating this defm");
|
2011-10-05 22:42:07 +00:00
|
|
|
|
|
|
|
// 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.
|
2013-01-09 05:28:12 +00:00
|
|
|
if (!CurMultiClass)
|
|
|
|
return false;
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const auto &Proto : CurMultiClass->DefPrototypes)
|
|
|
|
if (Proto->getNameInit() == CurRec->getNameInit())
|
2013-01-09 05:28:12 +00:00
|
|
|
return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() +
|
|
|
|
"' already defined in this multiclass!");
|
2014-12-11 05:25:33 +00:00
|
|
|
CurMultiClass->DefPrototypes.push_back(std::unique_ptr<Record>(CurRec));
|
2013-01-09 05:28:12 +00:00
|
|
|
|
|
|
|
// Copy the template arguments for the multiclass into the new def.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Init * TA : CurMultiClass->Rec.getTemplateArgs()) {
|
|
|
|
const RecordVal *RV = CurMultiClass->Rec.getValue(TA);
|
2013-01-09 05:28:12 +00:00
|
|
|
assert(RV && "Template arg doesn't exist?");
|
|
|
|
CurRec->addValue(*RV);
|
2011-10-05 22:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
/// ParseDefm - Parse the instantiation of a multiclass.
|
|
|
|
///
|
|
|
|
/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
|
|
|
|
///
|
2010-06-05 02:11:52 +00:00
|
|
|
bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
|
2007-11-22 20:49:04 +00:00
|
|
|
assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
|
2013-01-10 18:50:11 +00:00
|
|
|
SMLoc DefmLoc = Lex.getLoc();
|
2014-04-09 04:50:04 +00:00
|
|
|
Init *DefmPrefix = nullptr;
|
2011-10-19 13:04:29 +00:00
|
|
|
|
2013-01-07 05:09:33 +00:00
|
|
|
if (Lex.Lex() == tgtok::Id) { // eat the defm.
|
2011-10-19 13:04:29 +00:00
|
|
|
DefmPrefix = ParseObjectName(CurMultiClass);
|
2010-10-05 22:51:56 +00:00
|
|
|
}
|
2010-10-23 07:32:37 +00:00
|
|
|
|
2013-01-10 18:50:11 +00:00
|
|
|
SMLoc DefmPrefixEndLoc = Lex.getLoc();
|
2010-10-05 22:51:56 +00:00
|
|
|
if (Lex.getCode() != tgtok::colon)
|
2007-11-22 20:49:04 +00:00
|
|
|
return TokError("expected ':' after defm identifier");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2010-06-18 19:53:41 +00:00
|
|
|
// Keep track of the new generated record definitions.
|
|
|
|
std::vector<Record*> NewRecDefs;
|
|
|
|
|
|
|
|
// This record also inherits from a regular class (non-multiclass)?
|
|
|
|
bool InheritFromClass = false;
|
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// eat the colon.
|
|
|
|
Lex.Lex();
|
|
|
|
|
2009-06-21 03:39:35 +00:00
|
|
|
SMLoc SubClassLoc = Lex.getLoc();
|
2014-04-09 04:50:04 +00:00
|
|
|
SubClassReference Ref = ParseSubClassReference(nullptr, true);
|
2009-04-22 22:17:51 +00:00
|
|
|
|
|
|
|
while (1) {
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!Ref.Rec) return true;
|
2009-04-22 22:17:51 +00:00
|
|
|
|
|
|
|
// To instantiate a multiclass, we need to first get the multiclass, then
|
|
|
|
// instantiate each def contained in the multiclass with the SubClassRef
|
|
|
|
// template parameters.
|
2014-12-11 05:25:30 +00:00
|
|
|
MultiClass *MC = MultiClasses[Ref.Rec->getName()].get();
|
2014-11-30 01:20:17 +00:00
|
|
|
assert(MC && "Didn't lookup multiclass correctly?");
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
|
2009-04-22 22:17:51 +00:00
|
|
|
|
|
|
|
// Verify that the correct number of template arguments were specified.
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &TArgs = MC->Rec.getTemplateArgs();
|
2009-04-22 22:17:51 +00:00
|
|
|
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.
|
2015-04-29 04:43:36 +00:00
|
|
|
for (const std::unique_ptr<Record> &DefProto : MC->DefPrototypes) {
|
|
|
|
Record *CurRec = InstantiateMulticlassDef(*MC, DefProto.get(), DefmPrefix,
|
2013-01-10 18:50:11 +00:00
|
|
|
SMRange(DefmLoc,
|
|
|
|
DefmPrefixEndLoc));
|
2011-12-02 18:33:03 +00:00
|
|
|
if (!CurRec)
|
|
|
|
return true;
|
2010-06-05 02:11:52 +00:00
|
|
|
|
2013-01-10 18:50:11 +00:00
|
|
|
if (ResolveMulticlassDefArgs(*MC, CurRec, DefmLoc, SubClassLoc,
|
2011-10-05 22:42:07 +00:00
|
|
|
TArgs, TemplateVals, true/*Delete args*/))
|
|
|
|
return Error(SubClassLoc, "could not instantiate def");
|
2010-06-05 02:11:52 +00:00
|
|
|
|
2015-04-29 04:43:36 +00:00
|
|
|
if (ResolveMulticlassDef(*MC, CurRec, DefProto.get(), DefmLoc))
|
2011-10-05 22:42:07 +00:00
|
|
|
return Error(SubClassLoc, "could not instantiate def");
|
2010-06-18 19:53:41 +00:00
|
|
|
|
2014-09-16 17:14:13 +00:00
|
|
|
// Defs that can be used by other definitions should be fully resolved
|
|
|
|
// before any use.
|
|
|
|
if (DefProto->isResolveFirst() && !CurMultiClass) {
|
|
|
|
CurRec->resolveReferences();
|
|
|
|
CurRec->setResolveFirst(false);
|
|
|
|
}
|
2010-06-18 19:53:41 +00:00
|
|
|
NewRecDefs.push_back(CurRec);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-04-22 22:17:51 +00:00
|
|
|
|
2011-10-05 22:42:07 +00:00
|
|
|
|
2009-04-22 22:17:51 +00:00
|
|
|
if (Lex.getCode() != tgtok::comma) break;
|
|
|
|
Lex.Lex(); // eat ','.
|
|
|
|
|
2013-08-20 04:22:09 +00:00
|
|
|
if (Lex.getCode() != tgtok::Id)
|
|
|
|
return TokError("expected identifier");
|
|
|
|
|
2009-04-22 22:17:51 +00:00
|
|
|
SubClassLoc = Lex.getLoc();
|
2010-06-18 19:53:41 +00:00
|
|
|
|
|
|
|
// A defm can inherit from regular classes (non-multiclass) as
|
|
|
|
// long as they come in the end of the inheritance list.
|
2014-04-09 04:50:04 +00:00
|
|
|
InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != nullptr);
|
2010-06-18 19:53:41 +00:00
|
|
|
|
|
|
|
if (InheritFromClass)
|
|
|
|
break;
|
|
|
|
|
2014-04-09 04:50:04 +00:00
|
|
|
Ref = ParseSubClassReference(nullptr, true);
|
2007-11-22 20:49:04 +00:00
|
|
|
}
|
2009-04-22 22:17:51 +00:00
|
|
|
|
2010-06-18 19:53:41 +00:00
|
|
|
if (InheritFromClass) {
|
|
|
|
// Process all the classes to inherit as if they were part of a
|
|
|
|
// regular 'def' and inherit all record values.
|
2014-04-09 04:50:04 +00:00
|
|
|
SubClassReference SubClass = ParseSubClassReference(nullptr, false);
|
2010-06-18 19:53:41 +00:00
|
|
|
while (1) {
|
|
|
|
// Check for error.
|
2014-04-09 04:50:04 +00:00
|
|
|
if (!SubClass.Rec) return true;
|
2010-06-18 19:53:41 +00:00
|
|
|
|
|
|
|
// Get the expanded definition prototypes and teach them about
|
|
|
|
// the record values the current class to inherit has
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Record *CurRec : NewRecDefs) {
|
2010-06-18 19:53:41 +00:00
|
|
|
// Add it.
|
|
|
|
if (AddSubClass(CurRec, SubClass))
|
|
|
|
return true;
|
|
|
|
|
2013-01-09 04:49:14 +00:00
|
|
|
if (ApplyLetStack(CurRec))
|
|
|
|
return true;
|
2010-06-18 19:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Lex.getCode() != tgtok::comma) break;
|
|
|
|
Lex.Lex(); // eat ','.
|
2014-04-09 04:50:04 +00:00
|
|
|
SubClass = ParseSubClassReference(nullptr, false);
|
2010-06-18 19:53:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 20:30:50 +00:00
|
|
|
if (!CurMultiClass)
|
2015-04-29 04:43:36 +00:00
|
|
|
for (Record *CurRec : NewRecDefs)
|
2011-08-10 18:27:46 +00:00
|
|
|
// 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.
|
2015-04-29 04:43:36 +00:00
|
|
|
CurRec->resolveReferences();
|
2010-06-22 20:30:50 +00:00
|
|
|
|
2009-04-22 22:17:51 +00:00
|
|
|
if (Lex.getCode() != tgtok::semi)
|
|
|
|
return TokError("expected ';' at end of defm");
|
|
|
|
Lex.Lex();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseObject
|
|
|
|
/// Object ::= ClassInst
|
|
|
|
/// Object ::= DefInst
|
|
|
|
/// Object ::= MultiClassInst
|
|
|
|
/// Object ::= DefMInst
|
|
|
|
/// Object ::= LETCommand '{' ObjectList '}'
|
|
|
|
/// Object ::= LETCommand Object
|
2010-06-10 02:42:59 +00:00
|
|
|
bool TGParser::ParseObject(MultiClass *MC) {
|
2007-11-22 20:49:04 +00:00
|
|
|
switch (Lex.getCode()) {
|
2010-10-31 19:27:15 +00:00
|
|
|
default:
|
|
|
|
return TokError("Expected class, def, defm, multiclass or let definition");
|
2010-06-10 02:42:59 +00:00
|
|
|
case tgtok::Let: return ParseTopLevelLet(MC);
|
|
|
|
case tgtok::Def: return ParseDef(MC);
|
2012-02-22 16:09:41 +00:00
|
|
|
case tgtok::Foreach: return ParseForeach(MC);
|
2010-06-10 02:42:59 +00:00
|
|
|
case tgtok::Defm: return ParseDefm(MC);
|
2007-11-22 20:49:04 +00:00
|
|
|
case tgtok::Class: return ParseClass();
|
|
|
|
case tgtok::MultiClass: return ParseMultiClass();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseObjectList
|
|
|
|
/// ObjectList :== Object*
|
2010-06-10 02:42:59 +00:00
|
|
|
bool TGParser::ParseObjectList(MultiClass *MC) {
|
2007-11-22 20:49:04 +00:00
|
|
|
while (isObjectStart(Lex.getCode())) {
|
2010-06-10 02:42:59 +00:00
|
|
|
if (ParseObject(MC))
|
2007-11-22 20:49:04 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TGParser::ParseFile() {
|
|
|
|
Lex.Lex(); // Prime the lexer.
|
|
|
|
if (ParseObjectList()) return true;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
// If we have unread input at the end of the file, report it.
|
|
|
|
if (Lex.getCode() == tgtok::Eof)
|
|
|
|
return false;
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2007-11-22 20:49:04 +00:00
|
|
|
return TokError("Unexpected input at top level");
|
|
|
|
}
|
|
|
|
|