OLD | NEW |
(Empty) | |
| 1 GT2 patch as found in ragel-6-gt2 branch. |
| 2 |
| 3 More info: http://www.complang.org/pipermail/ragel-users/2012-May/002831.html |
| 4 |
| 5 --- ragel/cdgoto.cpp |
| 6 +++ ragel/cdgoto.cpp |
| 7 @@ -34,6 +34,11 @@ |
| 8 return out; |
| 9 } |
| 10 |
| 11 +int GotoCodeGen::TRANS_NR( RedTransAp *trans ) |
| 12 +{ |
| 13 + return trans->id; |
| 14 +} |
| 15 + |
| 16 std::ostream &GotoCodeGen::TO_STATE_ACTION_SWITCH() |
| 17 { |
| 18 /* Walk the list of functions, printing the cases. */ |
| 19 @@ -109,6 +114,86 @@ |
| 20 } |
| 21 |
| 22 |
| 23 +void GotoCodeGen::emitTableSwitch( RedStateAp *state ) |
| 24 +{ |
| 25 + /* Load up the singles. */ |
| 26 + int numSingles = state->outSingle.length(); |
| 27 + RedTransEl *sdata = state->outSingle.data; |
| 28 + |
| 29 + /* Load up the ranges. */ |
| 30 + int numRanges = state->outRange.length(); |
| 31 + RedTransEl *rdata = state->outRange.data; |
| 32 + |
| 33 + int minId = INT_MAX; |
| 34 + int maxId = INT_MIN; |
| 35 + |
| 36 + for ( Key i = keyOps->minKey; i <= keyOps->maxKey; i.increment() ) { |
| 37 + RedTransAp *trans = state->defTrans; |
| 38 + for ( int j = 0; j < numRanges; j++ ) |
| 39 + if ( ( rdata[j].lowKey.getVal() <= i ) && ( i <= rdata[j
].highKey.getVal() ) ) |
| 40 + trans = rdata[j].value; |
| 41 + for ( int j = 0; j < numSingles; j++ ) |
| 42 + if ( i == sdata[j].lowKey.getVal() ) |
| 43 + trans = sdata[j].value; |
| 44 + if ( minId > TRANS_NR(trans) ) |
| 45 + minId = TRANS_NR(trans); |
| 46 + if ( maxId < TRANS_NR(trans) ) |
| 47 + maxId = TRANS_NR(trans); |
| 48 + } |
| 49 + |
| 50 + if ( (maxId - minId) <= UCHAR_MAX ) |
| 51 + out << "\t{\n" << |
| 52 + "\t\tstatic const unsigned char jump_table[] = "; |
| 53 + else if ( (maxId - minId) <= USHRT_MAX ) |
| 54 + out << "\t{\n" << |
| 55 + "\t\tstatic const unsigned short jump_table[] = "; |
| 56 + else |
| 57 + out << "\t{\n" << |
| 58 + "\t\tstatic const int jump_table[] = "; |
| 59 + |
| 60 + char delimiter = '{'; |
| 61 + for ( Key i = keyOps->minKey; i <= keyOps->maxKey; i.increment() ) { |
| 62 + RedTransAp *trans = state->defTrans; |
| 63 + for ( int j = 0; j < numRanges; j++ ) |
| 64 + if ( ( rdata[j].lowKey.getVal() <= i ) && ( i <= rdata[j
].highKey.getVal() ) ) |
| 65 + trans = rdata[j].value; |
| 66 + for ( int j = 0; j < numSingles; j++ ) |
| 67 + if ( i == sdata[j].lowKey.getVal() ) |
| 68 + trans = sdata[j].value; |
| 69 + if ( minId >= 0 && maxId <= UCHAR_MAX ) |
| 70 + out << delimiter << " " << TRANS_NR(trans); |
| 71 + else if ( (maxId - minId) <= UCHAR_MAX ) |
| 72 + out << delimiter << " " << (TRANS_NR(trans) - minId); |
| 73 + else if ( minId >= 0 && maxId <= USHRT_MAX ) |
| 74 + out << delimiter << " " << TRANS_NR(trans); |
| 75 + else if ( (maxId - minId) <= USHRT_MAX ) |
| 76 + out << delimiter << " " << (TRANS_NR(trans) - minId); |
| 77 + else |
| 78 + out << delimiter << " " << TRANS_NR(trans); |
| 79 + delimiter = ','; |
| 80 + } |
| 81 + out << " };\n"; |
| 82 + |
| 83 + if (keyOps->minKey != 0 ) |
| 84 + out << "\t\t" << vCS() << " = jump_table[" << GET_WIDE_KEY(state
) << "-" << |
| 85 + WIDE_KEY(state, keyOps->minKey) << "]"; |
| 86 + else |
| 87 + out << "\t\t" << vCS() << " = jump_table[" << GET_WIDE_KEY(state
) << "]"; |
| 88 + if ( minId >= 0 && maxId <= UCHAR_MAX ) |
| 89 + out << ";\n"; |
| 90 + else if ( (maxId - minId) <= UCHAR_MAX ) |
| 91 + out << " + " << minId << ";\n"; |
| 92 + else if ( minId >= 0 && maxId <= USHRT_MAX ) |
| 93 + out << ";\n"; |
| 94 + else if ( (maxId - minId) <= USHRT_MAX ) |
| 95 + out << " + " << minId << ";\n"; |
| 96 + else |
| 97 + out << ";\n"; |
| 98 + |
| 99 + out << "\t\tgoto _again;\n" |
| 100 + "\t}\n"; |
| 101 +} |
| 102 + |
| 103 void GotoCodeGen::emitSingleSwitch( RedStateAp *state ) |
| 104 { |
| 105 /* Load up the singles. */ |
| 106 @@ -361,16 +446,24 @@ |
| 107 emitCondBSearch( st, 1, 0, st->stateCondVect.len
gth() - 1 ); |
| 108 } |
| 109 |
| 110 - /* Try singles. */ |
| 111 - if ( st->outSingle.length() > 0 ) |
| 112 - emitSingleSwitch( st ); |
| 113 - |
| 114 - /* Default case is to binary search for the ranges, if t
hat fails then */ |
| 115 - if ( st->outRange.length() > 0 ) |
| 116 - emitRangeBSearch( st, 1, 0, st->outRange.length(
) - 1 ); |
| 117 + if ( (st->outSingle.length() + st->outRange.length() * 2
) > maxTransitions) { |
| 118 + |
| 119 + emitTableSwitch( st ); |
| 120 + |
| 121 + } else { |
| 122 |
| 123 - /* Write the default transition. */ |
| 124 - TRANS_GOTO( st->defTrans, 1 ) << "\n"; |
| 125 + /* Try singles. */ |
| 126 + if ( st->outSingle.length() > 0 ) |
| 127 + emitSingleSwitch( st ); |
| 128 + |
| 129 + /* Default case is to binary search for the rang
es, if that fails then */ |
| 130 + if ( st->outRange.length() > 0 ) |
| 131 + emitRangeBSearch( st, 1, 0, st->outRange
.length() - 1 ); |
| 132 + |
| 133 + /* Write the default transition. */ |
| 134 + TRANS_GOTO( st->defTrans, 1 ) << "\n"; |
| 135 + |
| 136 + } |
| 137 } |
| 138 } |
| 139 return out; |
| 140 --- ragel/cdgoto.h |
| 141 +++ ragel/cdgoto.h |
| 142 @@ -74,7 +74,9 @@ |
| 143 void STATE_CONDS( RedStateAp *state, bool genDefault ); |
| 144 |
| 145 virtual std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); |
| 146 + virtual int TRANS_NR( RedTransAp *trans ); |
| 147 |
| 148 + void emitTableSwitch( RedStateAp *state ); |
| 149 void emitSingleSwitch( RedStateAp *state ); |
| 150 void emitRangeBSearch( RedStateAp *state, int level, int low, int high )
; |
| 151 |
| 152 --- ragel/cdipgoto.cpp 2011-02-11 07:14:43.000000000 +0300 |
| 153 +++ ragel/cdipgoto.cpp 2012-05-13 15:20:11.433272943 +0400 |
| 154 @@ -27,9 +27,20 @@ |
| 155 #include "gendata.h" |
| 156 #include "bstmap.h" |
| 157 |
| 158 +bool IpGotoCodeGen::useTransInAgainLabel() |
| 159 +{ |
| 160 + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) |
| 161 + if ( st == redFsm->errState ) |
| 162 + continue; |
| 163 + else if ( (st->outSingle.length() + st->outRange.length() * 2) >
maxTransitions) |
| 164 + return true; |
| 165 + return false; |
| 166 +} |
| 167 + |
| 168 bool IpGotoCodeGen::useAgainLabel() |
| 169 { |
| 170 - return redFsm->anyRegActionRets() || |
| 171 + return useTransInAgainLabel() || |
| 172 + redFsm->anyRegActionRets() || |
| 173 redFsm->anyRegActionByValControl() || |
| 174 redFsm->anyRegNextStmt(); |
| 175 } |
| 176 @@ -243,6 +254,18 @@ |
| 177 return out; |
| 178 } |
| 179 |
| 180 +int IpGotoCodeGen::TRANS_NR( RedTransAp *trans ) |
| 181 +{ |
| 182 + if ( trans->action != 0 ) { |
| 183 + /* Go to the transition which will go to the state. */ |
| 184 + return trans->id + redFsm->stateList.length(); |
| 185 + } |
| 186 + else { |
| 187 + /* Go directly to the target state. */ |
| 188 + return trans->targ->id; |
| 189 + } |
| 190 +} |
| 191 + |
| 192 std::ostream &IpGotoCodeGen::EXIT_STATES() |
| 193 { |
| 194 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { |
| 195 @@ -258,6 +281,13 @@ |
| 196 std::ostream &IpGotoCodeGen::AGAIN_CASES() |
| 197 { |
| 198 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { |
| 199 + if ( useTransInAgainLabel() ) |
| 200 + for ( int it = 0; it < st->numInTrans; it++ ) { |
| 201 + RedTransAp *trans = st->inTrans[it]; |
| 202 + if ( trans->action != 0 && trans->labelNeeded ) |
| 203 + out << |
| 204 + "\t\tcase " << (trans->id + redF
sm->stateList.length()) << ": goto tr" << trans->id << ";\n"; |
| 205 + } |
| 206 out << |
| 207 " case " << st->id << ": goto st" << st->i
d << ";\n"; |
| 208 } |
| 209 @@ -409,7 +439,6 @@ |
| 210 out << |
| 211 " " << P() << " += 1;\n"; |
| 212 } |
| 213 - |
| 214 out << "_resume:\n"; |
| 215 } |
| 216 |
| 217 --- ragel/cdipgoto.h |
| 218 +++ ragel/cdipgoto.h |
| 219 @@ -40,6 +40,7 @@ |
| 220 |
| 221 std::ostream &EXIT_STATES(); |
| 222 std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); |
| 223 + int TRANS_NR( RedTransAp *trans ); |
| 224 std::ostream &FINISH_CASES(); |
| 225 std::ostream &AGAIN_CASES(); |
| 226 |
| 227 @@ -58,6 +59,7 @@ |
| 228 virtual void writeExec(); |
| 229 |
| 230 protected: |
| 231 + bool useTransInAgainLabel(); |
| 232 bool useAgainLabel(); |
| 233 |
| 234 /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos fo
r |
| 235 --- ragel/main.cpp |
| 236 +++ ragel/main.cpp |
| 237 @@ -83,6 +83,8 @@ |
| 238 /* Target language and output style. */ |
| 239 CodeStyle codeStyle = GenTables; |
| 240 |
| 241 +long maxTransitions = LONG_MAX; |
| 242 + |
| 243 int numSplitPartitions = 0; |
| 244 bool noLineDirectives = false; |
| 245 |
| 246 @@ -139,6 +140,7 @@ |
| 247 " -G1 Faster goto-driven FSM\n" |
| 248 "code style: (C/D)\n" |
| 249 " -G2 Really fast goto-driven FSM\n" |
| 250 +" -GT2 Really fast goto-driven FSM with table-driven fallback
\n" |
| 251 " -P<N> N-Way Split really fast goto-driven FSM\n" |
| 252 ; |
| 253 |
| 254 @@ -407,7 +409,10 @@ |
| 255 codeStyle = GenFGoto; |
| 256 else if ( pc.paramArg[0] == '2' ) |
| 257 codeStyle = GenIpGoto; |
| 258 - else { |
| 259 + else if ( pc.paramArg[0] == 'T' && pc.paramArg[1
] == '2' ) { |
| 260 + codeStyle = GenIpGoto; |
| 261 + maxTransitions = 32; |
| 262 + } else { |
| 263 error() << "-G" << pc.paramArg[0] << |
| 264 " is an invalid argument
" << endl; |
| 265 exit(1); |
| 266 --- ragel/ragel.h |
| 267 +++ ragel/ragel.h |
| 268 @@ -109,6 +109,8 @@ |
| 269 extern int numSplitPartitions; |
| 270 extern bool noLineDirectives; |
| 271 |
| 272 +extern long maxTransitions; |
| 273 + |
| 274 std::ostream &error(); |
| 275 |
| 276 /* Target language and output style. */ |
OLD | NEW |