mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01: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::
|
.. productionlist::
|
||||||
Foreach: "foreach" `Declaration` "in" "{" `Object`* "}"
|
Foreach: "foreach" `ForeachDeclaration` "in" "{" `Object`* "}"
|
||||||
:| "foreach" `Declaration` "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 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
|
the object or object list is reevaluated with the variable set at each
|
||||||
iterated value.
|
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``
|
Top-Level ``let``
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
@ -1203,6 +1203,7 @@ public:
|
|||||||
Init *getBit(unsigned Bit) const override;
|
Init *getBit(unsigned Bit) const override;
|
||||||
|
|
||||||
Init *resolveReferences(Resolver &R) const override;
|
Init *resolveReferences(Resolver &R) const override;
|
||||||
|
Init *Fold() const;
|
||||||
|
|
||||||
std::string getAsString() const override {
|
std::string getAsString() const override {
|
||||||
return Rec->getAsString() + "." + FieldName->getValue().str();
|
return Rec->getAsString() + "." + FieldName->getValue().str();
|
||||||
|
@ -1633,16 +1633,17 @@ Init *FieldInit::getBit(unsigned Bit) const {
|
|||||||
|
|
||||||
Init *FieldInit::resolveReferences(Resolver &R) const {
|
Init *FieldInit::resolveReferences(Resolver &R) const {
|
||||||
Init *NewRec = Rec->resolveReferences(R);
|
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)
|
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);
|
return const_cast<FieldInit *>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1819,7 +1819,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
|||||||
Result->getAsString() + "'");
|
Result->getAsString() + "'");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Result = FieldInit::get(Result, FieldName);
|
Result = FieldInit::get(Result, FieldName)->Fold();
|
||||||
Lex.Lex(); // eat field name
|
Lex.Lex(); // eat field name
|
||||||
break;
|
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 declared object or a NULL Init on error. Return
|
||||||
/// the name of the parsed initializer list through ForeachListName.
|
/// the name of the parsed initializer list through ForeachListName.
|
||||||
///
|
///
|
||||||
/// ForeachDeclaration ::= ID '=' '[' ValueList ']'
|
|
||||||
/// ForeachDeclaration ::= ID '=' '{' RangeList '}'
|
/// ForeachDeclaration ::= ID '=' '{' RangeList '}'
|
||||||
/// ForeachDeclaration ::= ID '=' RangePiece
|
/// ForeachDeclaration ::= ID '=' RangePiece
|
||||||
|
/// ForeachDeclaration ::= ID '=' Value
|
||||||
///
|
///
|
||||||
VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
||||||
if (Lex.getCode() != tgtok::Id) {
|
if (Lex.getCode() != tgtok::Id) {
|
||||||
@ -2062,24 +2062,6 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
|||||||
SmallVector<unsigned, 16> Ranges;
|
SmallVector<unsigned, 16> Ranges;
|
||||||
|
|
||||||
switch (Lex.getCode()) {
|
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.
|
case tgtok::IntVal: { // RangePiece.
|
||||||
if (ParseRangePiece(Ranges))
|
if (ParseRangePiece(Ranges))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -2096,6 +2078,21 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
|
|||||||
Lex.Lex();
|
Lex.Lex();
|
||||||
break;
|
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()) {
|
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 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: def F0
|
||||||
// CHECK: string Name = "F0";
|
// CHECK: string Name = "F0";
|
||||||
// CHECK: int Index = 0;
|
// CHECK: int Index = 0;
|
||||||
@ -73,3 +85,10 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in {
|
|||||||
// CHECK: def R7
|
// CHECK: def R7
|
||||||
// CHECK: string Name = "R7";
|
// CHECK: string Name = "R7";
|
||||||
// CHECK: int Index = 7;
|
// CHECK: int Index = 7;
|
||||||
|
|
||||||
|
// CHECK: def X0
|
||||||
|
// CHECK: def X1
|
||||||
|
// CHECK: def Y0
|
||||||
|
// CHECK: def Y1
|
||||||
|
// CHECK: def Y2
|
||||||
|
// CHECK: def Y3
|
||||||
|
Loading…
x
Reference in New Issue
Block a user