Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 1 | include "llvm/TableGen/Automaton.td" |
| 2 | include "llvm/TableGen/SearchableTable.td" |
| 3 | |
| 4 | // Define a set of input token symbols. |
| 5 | class SymKindTy; |
| 6 | def SK_a : SymKindTy; |
| 7 | def SK_b : SymKindTy; |
| 8 | def SK_c : SymKindTy; |
| 9 | def SK_d : SymKindTy; |
| 10 | |
| 11 | // Emit those as a C++ enum using SearchableTables. |
| 12 | def SymKind : GenericEnum { |
| 13 | let FilterClass = "SymKindTy"; |
| 14 | } |
| 15 | |
| 16 | // Define a transition implementation. |
| 17 | class SimpleTransition<bits<2> State, SymKindTy A> : Transition { |
Chris Wailes | e3116c4 | 2021-07-13 14:40:48 -0700 | [diff] [blame] | 18 | let NewState{1...0} = State; |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 19 | SymKindTy ActionSym = A; |
| 20 | } |
| 21 | |
| 22 | // Token SK_a sets bit 0b01. |
| 23 | def : SimpleTransition<0b01, SK_a>; |
| 24 | // Token SK_b sets bits 0b10. |
| 25 | def : SimpleTransition<0b10, SK_b>; |
| 26 | // Token SK_c sets both bits 0b11. |
| 27 | def : SimpleTransition<0b11, SK_c>; |
| 28 | |
| 29 | def SimpleAutomaton : GenericAutomaton { |
| 30 | let TransitionClass = "SimpleTransition"; |
| 31 | let SymbolFields = ["ActionSym"]; |
| 32 | // Override the type of ActionSym from SymKindTy to the C++ type SymKind. |
| 33 | string TypeOf_ActionSym = "SymKind"; |
| 34 | } |
| 35 | |
| 36 | //===----------------------------------------------------------------------===// |
| 37 | // TupleActionAutomaton test implementation |
| 38 | |
| 39 | // Define a transition implementation. |
| 40 | class TupleTransition<bits<2> State, SymKindTy s1, SymKindTy s2, string s3> : Transition { |
Chris Wailes | e3116c4 | 2021-07-13 14:40:48 -0700 | [diff] [blame] | 41 | let NewState{1...0} = State; |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 42 | SymKindTy S1 = s1; |
| 43 | SymKindTy S2 = s2; |
| 44 | string S3 = s3; |
| 45 | } |
| 46 | |
| 47 | def : TupleTransition<0b01, SK_a, SK_b, "yeet">; |
| 48 | def : TupleTransition<0b10, SK_b, SK_b, "foo">; |
| 49 | def : TupleTransition<0b10, SK_c, SK_a, "foo">; |
| 50 | |
| 51 | def TupleAutomaton : GenericAutomaton { |
| 52 | let TransitionClass = "TupleTransition"; |
| 53 | let SymbolFields = ["S1", "S2", "S3"]; |
| 54 | string TypeOf_S1 = "SymKind"; |
| 55 | string TypeOf_S2 = "SymKind"; |
| 56 | } |
| 57 | |
| 58 | //===----------------------------------------------------------------------===// |
| 59 | // NfaAutomaton test implementation |
| 60 | |
| 61 | class NfaTransition<bits<2> State, SymKindTy S> : Transition { |
Chris Wailes | e3116c4 | 2021-07-13 14:40:48 -0700 | [diff] [blame] | 62 | let NewState{1...0} = State; |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 63 | SymKindTy A = S; |
| 64 | } |
| 65 | |
| 66 | // Symbols a and b can transition to 0b01 or 0b11 (sets bit 0). |
| 67 | def : NfaTransition<0b01, SK_a>; |
| 68 | def : NfaTransition<0b01, SK_b>; |
| 69 | // Symbols a and b can also transition to 0b10 or 0b11 (sets bit 1). |
| 70 | def : NfaTransition<0b10, SK_a>; |
| 71 | def : NfaTransition<0b10, SK_b>; |
| 72 | |
| 73 | def NfaAutomaton : GenericAutomaton { |
| 74 | let TransitionClass = "NfaTransition"; |
| 75 | let SymbolFields = ["A"]; |
| 76 | string TypeOf_A = "SymKind"; |
| 77 | } |
| 78 | |
| 79 | //===----------------------------------------------------------------------===// |
| 80 | // BinPacker test implementation |
| 81 | //===----------------------------------------------------------------------===// |
| 82 | // This test generates an automaton that can pack values into bins subject to |
| 83 | // constraints. There are 6 possible bins, and the input tokens are constraint |
| 84 | // types. Some input types span two bins. |
| 85 | |
| 86 | // The symbol type for a bin constraint. We use lists of ints as a tblgen hack |
| 87 | // to conditionally generate defs within multiclasses based on record |
| 88 | // information. A bin is nonempty (has a dummy one-element value) if enabled. |
| 89 | class BinRequirementKind { |
| 90 | list<int> Bin0 = []; |
| 91 | list<int> Bin1 = []; |
| 92 | list<int> Bin2 = []; |
| 93 | list<int> Bin3 = []; |
| 94 | list<int> Bin4 = []; |
| 95 | list<int> Bin5 = []; |
| 96 | } |
| 97 | // Can use bins {0-3} |
| 98 | def BRK_0_to_4 : BinRequirementKind { let Bin0 = [1]; let Bin1 = [1]; let Bin2 = [1]; let Bin3 = [1]; } |
| 99 | // Can use bins {0-3} but only evens (0 and 2). |
| 100 | def BRK_0_to_4_lo : BinRequirementKind { let Bin0 = [1]; let Bin2 = [1]; } |
| 101 | // Can use bins {0-3} but only odds (1 and 3). |
| 102 | def BRK_0_to_4_hi : BinRequirementKind { let Bin1 = [1]; let Bin3 = [1]; } |
| 103 | // Can use bins {0-3} but only even-odd pairs (0+1 or 1+2). |
| 104 | def BRK_0_to_4_dbl : BinRequirementKind { let Bin0 = [1]; let Bin2 = [1]; } |
| 105 | def BRK_0_to_6 : BinRequirementKind { let Bin0 = [1]; let Bin1 = [1]; let Bin2 = [1]; |
| 106 | let Bin3 = [1]; let Bin4 = [1]; let Bin5 = [1]; } |
| 107 | def BRK_0_to_6_lo : BinRequirementKind { let Bin0 = [1]; let Bin2 = [1]; let Bin4 = [1]; } |
| 108 | def BRK_0_to_6_hi : BinRequirementKind { let Bin1 = [1]; let Bin3 = [1]; let Bin5 = [1]; } |
| 109 | def BRK_0_to_6_dbl : BinRequirementKind { let Bin0 = [1]; let Bin2 = [1]; let Bin4 = [1]; } |
| 110 | def BRK_2_to_6 : BinRequirementKind { let Bin2 = [1]; |
| 111 | let Bin3 = [1]; let Bin4 = [1]; let Bin5 = [1]; } |
| 112 | def BRK_2_to_6_lo : BinRequirementKind { let Bin2 = [1]; let Bin4 = [1]; } |
| 113 | def BRK_2_to_6_hi : BinRequirementKind { let Bin3 = [1]; let Bin5 = [1];} |
| 114 | def BRK_2_to_6_dbl : BinRequirementKind { let Bin2 = [1]; let Bin4 = [1]; } |
| 115 | def BRK_2_to_4 : BinRequirementKind { let Bin2 = [1]; let Bin3 = [1]; } |
| 116 | def BRK_2_to_4_lo : BinRequirementKind { let Bin2 = [1]; } |
| 117 | def BRK_2_to_4_hi : BinRequirementKind { let Bin3 = [1]; } |
| 118 | def BRK_2_to_4_dbl : BinRequirementKind { let Bin2 = [1]; } |
| 119 | |
| 120 | def BinRequirementKindEnum : GenericEnum { |
| 121 | let FilterClass = "BinRequirementKind"; |
| 122 | } |
| 123 | |
| 124 | // The transition class is trivial; it just contains the constraint symbol. |
| 125 | class BinTransition : Transition { |
| 126 | BinRequirementKind Sym; |
| 127 | } |
| 128 | |
| 129 | // Mixin that occupies a single bin. |
| 130 | class Bin0 : BinTransition { let NewState{0} = 1; } |
| 131 | class Bin1 : BinTransition { let NewState{1} = 1; } |
| 132 | class Bin2 : BinTransition { let NewState{2} = 1;} |
| 133 | class Bin3 : BinTransition { let NewState{3} = 1; } |
| 134 | class Bin4 : BinTransition { let NewState{4} = 1;} |
| 135 | class Bin5 : BinTransition { let NewState{5} = 1; } |
| 136 | // Mixin that occupies a pair of bins (even-odd pairs). |
| 137 | class Bin01 : BinTransition { let NewState{0,1} = 0b11; } |
| 138 | class Bin23 : BinTransition { let NewState{2,3} = 0b11; } |
| 139 | class Bin45 : BinTransition { let NewState{4,5} = 0b11; } |
| 140 | |
| 141 | // Instantiate all possible bin assignments for E. |
| 142 | multiclass BinAssignments<BinRequirementKind E> { |
| 143 | let Sym = E in { |
| 144 | // Note the tablegen hack to conditionally instantiate a def based on E. |
| 145 | foreach x = E.Bin0 in { def : Bin0; } |
| 146 | foreach x = E.Bin1 in { def : Bin1; } |
| 147 | foreach x = E.Bin2 in { def : Bin2; } |
| 148 | foreach x = E.Bin3 in { def : Bin3; } |
| 149 | foreach x = E.Bin4 in { def : Bin4; } |
| 150 | foreach x = E.Bin5 in { def : Bin5; } |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // Instantiate all possible bin assignments for E, which spans even-odd pairs. |
| 155 | multiclass DblBinAssignments<BinRequirementKind E> { |
| 156 | let Sym = E in { |
| 157 | foreach x = E.Bin0 in { def : Bin01; } |
| 158 | foreach x = E.Bin2 in { def : Bin23; } |
| 159 | foreach x = E.Bin4 in { def : Bin45; } |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | defm : BinAssignments<BRK_0_to_4>; |
| 164 | defm : DblBinAssignments<BRK_0_to_4_dbl>; |
| 165 | defm : BinAssignments<BRK_0_to_4_lo>; |
| 166 | defm : BinAssignments<BRK_0_to_4_hi>; |
| 167 | defm : BinAssignments<BRK_0_to_6>; |
| 168 | defm : DblBinAssignments<BRK_0_to_6_dbl>; |
| 169 | defm : BinAssignments<BRK_0_to_6_lo>; |
| 170 | defm : BinAssignments<BRK_0_to_6_hi>; |
| 171 | defm : BinAssignments<BRK_2_to_6>; |
| 172 | defm : DblBinAssignments<BRK_2_to_6_dbl>; |
| 173 | defm : BinAssignments<BRK_2_to_6_lo>; |
| 174 | defm : BinAssignments<BRK_2_to_6_hi>; |
| 175 | defm : BinAssignments<BRK_2_to_4>; |
| 176 | defm : DblBinAssignments<BRK_2_to_4_dbl>; |
| 177 | defm : BinAssignments<BRK_2_to_4_lo>; |
| 178 | defm : BinAssignments<BRK_2_to_4_hi>; |
| 179 | |
| 180 | def BinPackerAutomaton : GenericAutomaton { |
| 181 | let TransitionClass = "BinTransition"; |
| 182 | let SymbolFields = ["Sym"]; |
| 183 | string TypeOf_Sym = "BinRequirementKindEnum"; |
| 184 | } |
| 185 | |
| 186 | |