316 changes: 209 additions & 107 deletions llvm/lib/TableGen/TGParser.cpp

Large diffs are not rendered by default.

62 changes: 43 additions & 19 deletions llvm/lib/TableGen/TGParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace llvm {
class RecordKeeper;
class RecTy;
class Init;
struct ForeachLoop;
struct MultiClass;
struct SubClassReference;
struct SubMultiClassReference;
Expand All @@ -41,14 +42,31 @@ namespace llvm {
}
};

/// RecordsEntry - Can be either a record or a foreach loop.
struct RecordsEntry {
std::unique_ptr<Record> Rec;
std::unique_ptr<ForeachLoop> Loop;

void dump() const;

RecordsEntry() {}
RecordsEntry(std::unique_ptr<Record> Rec) : Rec(std::move(Rec)) {}
RecordsEntry(std::unique_ptr<ForeachLoop> Loop)
: Loop(std::move(Loop)) {}
};

/// ForeachLoop - Record the iteration state associated with a for loop.
/// This is used to instantiate items in the loop body.
struct ForeachLoop {
SMLoc Loc;
VarInit *IterVar;
ListInit *ListValue;
Init *ListValue;
std::vector<RecordsEntry> Entries;

void dump() const;

ForeachLoop(VarInit *IVar, ListInit *LValue)
: IterVar(IVar), ListValue(LValue) {}
ForeachLoop(SMLoc Loc, VarInit *IVar, Init *LValue)
: Loc(Loc), IterVar(IVar), ListValue(LValue) {}
};

struct DefsetRecord {
Expand All @@ -57,15 +75,24 @@ namespace llvm {
SmallVector<Init *, 16> Elements;
};

struct MultiClass {
Record Rec; // Placeholder for template args and Name.
std::vector<RecordsEntry> Entries;

void dump() const;

MultiClass(StringRef Name, SMLoc Loc, RecordKeeper &Records) :
Rec(Name, Loc, Records) {}
};

class TGParser {
TGLexer Lex;
std::vector<SmallVector<LetRecord, 4>> LetStack;
std::map<std::string, std::unique_ptr<MultiClass>> MultiClasses;

/// Loops - Keep track of any foreach loops we are within.
///
typedef std::vector<ForeachLoop> LoopVector;
LoopVector Loops;
std::vector<std::unique_ptr<ForeachLoop>> Loops;

SmallVector<DefsetRecord *, 2> Defsets;

Expand Down Expand Up @@ -112,23 +139,19 @@ class TGParser {
ArrayRef<unsigned> BitList, Init *V,
bool AllowSelfAssignment = false);
bool AddSubClass(Record *Rec, SubClassReference &SubClass);
bool AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass);
bool AddSubMultiClass(MultiClass *CurMC,
SubMultiClassReference &SubMultiClass);

// IterRecord: Map an iterator name to a value.
struct IterRecord {
VarInit *IterVar;
Init *IterValue;
IterRecord(VarInit *Var, Init *Val) : IterVar(Var), IterValue(Val) {}
};

// IterSet: The set of all iterator values at some point in the
// iteration space.
typedef std::vector<IterRecord> IterSet;
using SubstStack = SmallVector<std::pair<Init *, Init *>, 8>;

bool addDefOne(std::unique_ptr<Record> Rec, IterSet &IterVals);
bool addDefForeach(Record *Rec, IterSet &IterVals);
bool addDef(std::unique_ptr<Record> Rec);
bool addEntry(RecordsEntry E);
bool resolve(const ForeachLoop &Loop, SubstStack &Stack, bool Final,
std::vector<RecordsEntry> *Dest, SMLoc *Loc = nullptr);
bool resolve(const std::vector<RecordsEntry> &Source, SubstStack &Substs,
bool Final, std::vector<RecordsEntry> *Dest,
SMLoc *Loc = nullptr);
bool addDefOne(std::unique_ptr<Record> Rec);

private: // Parser methods.
bool ParseObjectList(MultiClass *MC = nullptr);
Expand All @@ -148,7 +171,7 @@ class TGParser {

bool ParseTemplateArgList(Record *CurRec);
Init *ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
VarInit *ParseForeachDeclaration(ListInit *&ForeachListValue);
VarInit *ParseForeachDeclaration(Init *&ForeachListValue);

SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
Expand All @@ -175,6 +198,7 @@ class TGParser {
Record *ParseClassID();
MultiClass *ParseMultiClassID();
bool ApplyLetStack(Record *CurRec);
bool ApplyLetStack(RecordsEntry &Entry);
};

} // end namespace llvm
Expand Down
9 changes: 9 additions & 0 deletions llvm/test/TableGen/NestedForeach.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ foreach S = ["R", "C"] in {
}
}

foreach i = [0, 1] in
foreach j = !foreach(x, [0, 2], !add(i, x)) in
def Z#i#_#j;

// CHECK: def C2D0
// CHECK: def C2D2
// CHECK: def C2D4
Expand Down Expand Up @@ -71,3 +75,8 @@ foreach S = ["R", "C"] in {
// CHECK: def R4Q0
// CHECK: def R4Q2
// CHECK: def R4Q4

// CHECK: def Z0_0
// CHECK: def Z0_2
// CHECK: def Z1_1
// CHECK: def Z1_3
98 changes: 96 additions & 2 deletions llvm/test/TableGen/foreach-multiclass.td
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,53 @@
// CHECK: int sum = 8;
// CHECK: }

// CHECK-NOT: def B0

// CHECK: def B12 {
// CHECK: int val = 9;
// CHECK: }

// CHECK: def B20 {
// CHECK: int val = 7;
// CHECK: }

// CHECK: def B24 {
// CHECK: int val = 11;
// CHECK: }

// CHECK: def B25 {
// CHECK: int val = 12;
// CHECK: }

// CHECK: def C04
// CHECK: def C05

// CHECK: def D0A
// CHECK-NOT: def D0B
// CHECK: def D1A
// CHECK: def D1B

// CHECK: def E01
// CHECK: def E02
// CHECK-NOT: def E0C

// CHECK: def E18
// CHECK: def E19
// CHECK: def E1C33
// CHECK: def E1C34
// CHECK: def E1C55
// CHECK: def E1C56

// CHECK-NOT: def F0
// CHECK-NOT: def F1
// CHECK-NOT: def F2_0_0
// CHECK: def F2_1_0
// CHECK-NOT: def F2_1_2
// CHECK: def F2_2_0
// CHECK: def F2_2_1
// CHECK-NOT: def F2_2_2

multiclass A<int x> {
// Allow foreach in multiclass as long as the list does not depend on
// template args.
foreach i = [0, 1] in {
def NAME#i {
int sum = !add(x, i);
Expand All @@ -22,3 +66,53 @@ multiclass A<int x> {
}

defm A0 : A<7>;

multiclass B<int x, list<int> lst> {
foreach i = lst in {
def NAME#i {
int val = !add(x, i);
}
}
}

defm B0 : B<7, []>;
defm B1 : B<7, [2]>;
defm B2 : B<7, [0, 4, 5]>;

multiclass C<int x> {
foreach i = [x, !add(x, 1)] in {
def NAME#i;
}
}

defm C0 : C<4>;

multiclass D<bit b> {
def A;

foreach _ = !if(b, [0], []<int>) in
def B;
}

defm D0 : D<0>;
defm D1 : D<1>;

multiclass E<list<int> lst, int x>
: C<x> {
foreach i = lst in
defm C#i : C<i>;
}

defm E0 : E<[], 1>;
defm E1 : E<[3, 5], 8>;

multiclass F<list<int> lst> {
foreach i = lst in
foreach j = !foldl([]<int>, lst, lhs, x,
!if(!lt(x, i), !listconcat(lhs, [x]), lhs)) in
def _#i#_#j;
}

defm F0 : F<[]>;
defm F1 : F<[0]>;
defm F2 : F<[0, 1, 2]>;