mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-29 14:20:29 +00:00
TableGen: Allow arbitrary list values as ranges of foreach
The changes to FieldInit are required to make field references (Def.field) work inside a ForeachDeclaration: previously, Def.field wasn't resolved immediately when Def was already a fully resolved DefInit. Change-Id: I9875baec2fc5aac8c2b249e45b9cf18c65ae699b llvm-svn: 327120
This commit is contained in:
parent
c8e80dc722
commit
1ebb6681e2
@ -360,13 +360,17 @@ precede any ``class``'s that appear.
|
||||
-----------
|
||||
|
||||
.. productionlist::
|
||||
Foreach: "foreach" `Declaration` "in" "{" `Object`* "}"
|
||||
:| "foreach" `Declaration` "in" `Object`
|
||||
Foreach: "foreach" `ForeachDeclaration` "in" "{" `Object`* "}"
|
||||
:| "foreach" `ForeachDeclaration` "in" `Object`
|
||||
ForeachDeclaration: ID "=" ( "{" `RangeList` "}" | `RangePiece` | `Value` )
|
||||
|
||||
The value assigned to the variable in the declaration is iterated over and
|
||||
the object or object list is reevaluated with the variable set at each
|
||||
iterated value.
|
||||
|
||||
Note that the productions involving RangeList and RangePiece have precedence
|
||||
over the more generic value parsing based on the first token.
|
||||
|
||||
Top-Level ``let``
|
||||
-----------------
|
||||
|
||||
|
@ -1203,6 +1203,7 @@ public:
|
||||
Init *getBit(unsigned Bit) const override;
|
||||
|
||||
Init *resolveReferences(Resolver &R) const override;
|
||||
Init *Fold() const;
|
||||
|
||||
std::string getAsString() const override {
|
||||
return Rec->getAsString() + "." + FieldName->getValue().str();
|
||||
|
@ -1633,16 +1633,17 @@ Init *FieldInit::getBit(unsigned Bit) const {
|
||||
|
||||
Init *FieldInit::resolveReferences(Resolver &R) const {
|
||||
Init *NewRec = Rec->resolveReferences(R);
|
||||
|
||||
if (DefInit *DI = dyn_cast<DefInit>(NewRec)) {
|
||||
Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
|
||||
Init *BVR = FieldVal->resolveReferences(R);
|
||||
if (BVR->isComplete())
|
||||
return BVR;
|
||||
}
|
||||
|
||||
if (NewRec != Rec)
|
||||
return FieldInit::get(NewRec, FieldName);
|
||||
return FieldInit::get(NewRec, FieldName)->Fold();
|
||||
return const_cast<FieldInit *>(this);
|
||||
}
|
||||
|
||||
Init *FieldInit::Fold() const {
|
||||
if (DefInit *DI = dyn_cast<DefInit>(Rec)) {
|
||||
Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
|
||||
if (FieldVal->isComplete())
|
||||
return FieldVal;
|
||||
}
|
||||
return const_cast<FieldInit *>(this);
|
||||
}
|
||||
|
||||
|
@ -1819,7 +1819,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
||||
Result->getAsString() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
Result = FieldInit::get(Result, FieldName);
|
||||
Result = FieldInit::get(Result, FieldName)->Fold();
|
||||
Lex.Lex(); // eat field name
|
||||
break;
|
||||
}
|
||||
@ -2038,9 +2038,9 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
|
||||
/// the name of the declared object or a NULL Init on error. Return
|
||||
/// the name of the parsed initializer list through ForeachListName.
|
||||
///
|
||||
/// ForeachDeclaration ::= ID '=' '[' ValueList ']'
|
||||
/// ForeachDeclaration ::= ID '=' '{' RangeList '}'
|
||||
/// ForeachDeclaration ::= ID '=' RangePiece
|
||||
/// ForeachDeclaration ::= ID '=' Value
|
||||
///
|
||||
VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
||||
if (Lex.getCode() != tgtok::Id) {
|
||||
@ -2062,24 +2062,6 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
||||
SmallVector<unsigned, 16> Ranges;
|
||||
|
||||
switch (Lex.getCode()) {
|
||||
default: TokError("Unknown token when expecting a range list"); return nullptr;
|
||||
case tgtok::l_square: { // '[' ValueList ']'
|
||||
Init *List = ParseSimpleValue(nullptr);
|
||||
ForeachListValue = dyn_cast<ListInit>(List);
|
||||
if (!ForeachListValue) {
|
||||
TokError("Expected a Value list");
|
||||
return nullptr;
|
||||
}
|
||||
RecTy *ValueType = ForeachListValue->getType();
|
||||
ListRecTy *ListType = dyn_cast<ListRecTy>(ValueType);
|
||||
if (!ListType) {
|
||||
TokError("Value list is not of list type");
|
||||
return nullptr;
|
||||
}
|
||||
IterType = ListType->getElementType();
|
||||
break;
|
||||
}
|
||||
|
||||
case tgtok::IntVal: { // RangePiece.
|
||||
if (ParseRangePiece(Ranges))
|
||||
return nullptr;
|
||||
@ -2096,6 +2078,21 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
||||
Lex.Lex();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
SMLoc ValueLoc = Lex.getLoc();
|
||||
Init *I = ParseValue(nullptr);
|
||||
if (!isa<ListInit>(I)) {
|
||||
std::string Type;
|
||||
if (TypedInit *TI = dyn_cast<TypedInit>(I))
|
||||
Type = (Twine("' of type '") + TI->getType()->getAsString()).str();
|
||||
Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'");
|
||||
return nullptr;
|
||||
}
|
||||
ForeachListValue = dyn_cast<ListInit>(I);
|
||||
IterType = ForeachListValue->getElementType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Ranges.empty()) {
|
||||
|
@ -10,6 +10,18 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in {
|
||||
def F#i : Register<"F"#i, i>;
|
||||
}
|
||||
|
||||
def Defs {
|
||||
list<int> a = [0, 1];
|
||||
list<int> b = [2, 3];
|
||||
}
|
||||
|
||||
foreach i = Defs.a in {
|
||||
def X#i;
|
||||
}
|
||||
|
||||
foreach i = !listconcat(Defs.a, Defs.b) in
|
||||
def Y#i;
|
||||
|
||||
// CHECK: def F0
|
||||
// CHECK: string Name = "F0";
|
||||
// CHECK: int Index = 0;
|
||||
@ -73,3 +85,10 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in {
|
||||
// CHECK: def R7
|
||||
// CHECK: string Name = "R7";
|
||||
// CHECK: int Index = 7;
|
||||
|
||||
// CHECK: def X0
|
||||
// CHECK: def X1
|
||||
// CHECK: def Y0
|
||||
// CHECK: def Y1
|
||||
// CHECK: def Y2
|
||||
// CHECK: def Y3
|
||||
|
Loading…
Reference in New Issue
Block a user