From ef3502b09c491ecc6d9d5ddeba3020c0315947d8 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Tue, 25 Aug 2015 11:33:29 +0100 Subject: [PATCH] Fixed bug #119: "-f with -b/-g generates incorrect dispatch on fill labels". Consider the following example 1.re: /*!re2c "" {} */ With -if, re2c would generate correct dispatch: $ re2c -if 1.re /* Generated by re2c 0.14.3 on Tue Aug 25 10:41:45 2015 */ switch (YYGETSTATE()) { default: goto yy0; case 0: goto yyFillLabel0; } yy0: YYSETSTATE(0); yyFillLabel0: {} With -bif all positive YYGETSTATE() values will lead to yyFillLabel0, which is clearly an error: values that are greater than 0 should lead to yy0: $ re2c -bif 1.re /* Generated by re2c 0.14.3 on Tue Aug 25 10:40:32 2015 */ if (YYGETSTATE() < 0) { goto yy0; } else { goto yyFillLabel0; } yy0: YYSETSTATE(0); yyFillLabel0: {} With -gif the error is different: all values greater than 0 now cause undefined behaviour (access to memory not within array bounds): $ re2c -gif 1.re /* Generated by re2c 0.14.3 on Tue Aug 25 10:47:41 2015 */ { static void *yystable[] = { &&yyFillLabel0, }; if (YYGETSTATE() < 0) { goto yy0; } goto *yystable[YYGETSTATE()]; yy0: YYSETSTATE(0); yyFillLabel0: {} } The situation gets even more tricky with re2c:state:abort configuration. Besides, YYGETSTATE() macro is called multiple times with -b and -g, which is not so good. Additional checks with -g don't help gain performance either. Fix: always generate simple switch. --- re2c/src/codegen/output.cc | 88 ++++------------------------------- re2c/src/codegen/output.h | 1 - re2c/test/bug119.bif.c | 14 ++++++ re2c/test/bug119.bif.re | 4 ++ re2c/test/bug119.gif.c | 16 +++++++ re2c/test/bug119.gif.re | 4 ++ re2c/test/bug119.if.c | 14 ++++++ re2c/test/bug119.if.re | 4 ++ re2c/test/bug119_abort.bif.c | 14 ++++++ re2c/test/bug119_abort.bif.re | 4 ++ re2c/test/bug119_abort.gif.c | 16 +++++++ re2c/test/bug119_abort.gif.re | 4 ++ re2c/test/bug119_abort.if.c | 14 ++++++ re2c/test/bug119_abort.if.re | 4 ++ re2c/test/condition_08.cbif.c | 22 +++------ re2c/test/condition_09.cbif.c | 22 +++------ re2c/test/condition_09.cgif.c | 16 +++---- re2c/test/condition_10.cgif.c | 16 +++---- re2c/test/condition_12.cgif.c | 16 +++---- re2c/test/condition_14.cbif.c | 22 +++------ re2c/test/condition_14.cgif.c | 16 +++---- re2c/test/push.fb.c | 57 ++++++++++------------- re2c/test/push.fg.c | 54 ++++++++++----------- 23 files changed, 213 insertions(+), 229 deletions(-) create mode 100644 re2c/test/bug119.bif.c create mode 100644 re2c/test/bug119.bif.re create mode 100644 re2c/test/bug119.gif.c create mode 100644 re2c/test/bug119.gif.re create mode 100644 re2c/test/bug119.if.c create mode 100644 re2c/test/bug119.if.re create mode 100644 re2c/test/bug119_abort.bif.c create mode 100644 re2c/test/bug119_abort.bif.re create mode 100644 re2c/test/bug119_abort.gif.c create mode 100644 re2c/test/bug119_abort.gif.re create mode 100644 re2c/test/bug119_abort.if.c create mode 100644 re2c/test/bug119_abort.if.re diff --git a/re2c/src/codegen/output.cc b/re2c/src/codegen/output.cc index bd5b945a..a55a5c05 100644 --- a/re2c/src/codegen/output.cc +++ b/re2c/src/codegen/output.cc @@ -360,93 +360,23 @@ Output::~Output () } } -void output_state_goto_sub (std::ostream & o, uint32_t ind, uint32_t start_label, int cMin, int cMax) -{ - if (cMin == cMax) - { - if (cMin == -1) - { - o << indent(ind) << "goto " << labelPrefix << start_label << ";\n"; - } - else - { - o << indent(ind) << "goto " << mapCodeName["yyFillLabel"] << cMin << ";\n"; - } - } - else - { - int cMid = cMin + ((cMax - cMin + 1) / 2); - - o << indent(ind) << "if (" << output_get_state() << " < " << cMid << ") {\n"; - output_state_goto_sub (o, ind + 1, start_label, cMin, cMid - 1); - o << indent(ind) << "} else {\n"; - output_state_goto_sub (o, ind + 1, start_label, cMid, cMax); - o << indent(ind) << "}\n"; - } -} - void output_state_goto (std::ostream & o, uint32_t ind, uint32_t start_label) { - if (gFlag) + o << indent(ind) << "switch (" << output_get_state() << ") {\n"; + if (bUseStateAbort) { - o << indent(ind++) << "static void *" << mapCodeName["yystable"] << "[" << "] = {\n"; - - for (size_t i=0; itok = s->cur; - if (s->state < 1) { - if (s->state < 0) { - goto yy0; - } else { - goto yyFillLabel0; - } - } else { - if (s->state < 2) { - goto yyFillLabel1; - } else { - if (s->state < 3) { - goto yyFillLabel2; - } else { - goto yyFillLabel3; - } - } + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } yy0: if (s->cond < 2) { diff --git a/re2c/test/condition_09.cbif.c b/re2c/test/condition_09.cbif.c index eb5ada80..d7a1058d 100644 --- a/re2c/test/condition_09.cbif.c +++ b/re2c/test/condition_09.cbif.c @@ -78,22 +78,12 @@ void scan(Scanner *s) { s->tok = s->cur; - if (s->state < 1) { - if (s->state < 0) { - goto yy0; - } else { - goto yyFillLabel0; - } - } else { - if (s->state < 2) { - goto yyFillLabel1; - } else { - if (s->state < 3) { - goto yyFillLabel2; - } else { - goto yyFillLabel3; - } - } + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } for(;;) { diff --git a/re2c/test/condition_09.cgif.c b/re2c/test/condition_09.cgif.c index c601babd..c383451d 100644 --- a/re2c/test/condition_09.cgif.c +++ b/re2c/test/condition_09.cgif.c @@ -78,17 +78,13 @@ void scan(Scanner *s) { s->tok = s->cur; - static void *yystable[] = { - &&yyFillLabel0, - &&yyFillLabel1, - &&yyFillLabel2, - &&yyFillLabel3, - }; - - if (s->state < 0) { - goto yy0; + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } - goto *yystable[s->state]; for(;;) { s->tok = s->cur; diff --git a/re2c/test/condition_10.cgif.c b/re2c/test/condition_10.cgif.c index 8f8c3ac7..fdca2378 100644 --- a/re2c/test/condition_10.cgif.c +++ b/re2c/test/condition_10.cgif.c @@ -78,17 +78,13 @@ void scan(Scanner *s) { s->tok = s->cur; - static void *yystable[] = { - &&yyFillLabel0, - &&yyFillLabel1, - &&yyFillLabel2, - &&yyFillLabel3, - }; - - if (s->state < 0) { - goto yy0; + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } - goto *yystable[s->state]; for(;;) { s->tok = s->cur; diff --git a/re2c/test/condition_12.cgif.c b/re2c/test/condition_12.cgif.c index d306ad42..6caad895 100644 --- a/re2c/test/condition_12.cgif.c +++ b/re2c/test/condition_12.cgif.c @@ -78,17 +78,13 @@ void scan(Scanner *s) { s->tok = s->cur; - static void *yystable[] = { - &&yyFillLabel0, - &&yyFillLabel1, - &&yyFillLabel2, - &&yyFillLabel3, - }; - - if (s->state < 0) { - goto yy0; + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } - goto *yystable[s->state]; for(;;) { s->tok = s->cur; diff --git a/re2c/test/condition_14.cbif.c b/re2c/test/condition_14.cbif.c index a67d7523..1ed99673 100644 --- a/re2c/test/condition_14.cbif.c +++ b/re2c/test/condition_14.cbif.c @@ -78,22 +78,12 @@ void scan(Scanner *s) { s->tok = s->cur; - if (s->state < 1) { - if (s->state < 0) { - goto yy0; - } else { - goto yyFillLabel0; - } - } else { - if (s->state < 2) { - goto yyFillLabel1; - } else { - if (s->state < 3) { - goto yyFillLabel2; - } else { - goto yyFillLabel3; - } - } + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } for(;;) { diff --git a/re2c/test/condition_14.cgif.c b/re2c/test/condition_14.cgif.c index 3506c071..05c62c97 100644 --- a/re2c/test/condition_14.cgif.c +++ b/re2c/test/condition_14.cgif.c @@ -78,17 +78,13 @@ void scan(Scanner *s) { s->tok = s->cur; - static void *yystable[] = { - &&yyFillLabel0, - &&yyFillLabel1, - &&yyFillLabel2, - &&yyFillLabel3, - }; - - if (s->state < 0) { - goto yy0; + switch (s->state) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; + case 3: goto yyFillLabel3; } - goto *yystable[s->state]; for(;;) { s->tok = s->cur; diff --git a/re2c/test/push.fb.c b/re2c/test/push.fb.c index 0d4e0ac7..f1a4f47a 100644 --- a/re2c/test/push.fb.c +++ b/re2c/test/push.fb.c @@ -267,18 +267,11 @@ public: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - if (YYGETSTATE() < 1) { - if (YYGETSTATE() < 0) { - goto yy0; - } else { - goto yyFillLabel0; - } - } else { - if (YYGETSTATE() < 2) { - goto yyFillLabel1; - } else { - goto yyFillLabel2; - } + switch (YYGETSTATE()) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; } yy0: YYSETSTATE(0); @@ -367,7 +360,7 @@ yyFillLabel0: yy3: #line 246 "push.fb.re" { SEND(kIdentifier); } -#line 370 "" +#line 363 "" yy4: yych = *++YYCURSOR; if (yych == 'o') goto yy64; @@ -405,62 +398,62 @@ yy12: yy13: #line 247 "push.fb.re" { SEND(kDecimalConstant);} -#line 408 "" +#line 401 "" yy14: ++YYCURSOR; #line 249 "push.fb.re" { SEND(kEqual); } -#line 413 "" +#line 406 "" yy16: ++YYCURSOR; #line 250 "push.fb.re" { SEND(kLeftParen); } -#line 418 "" +#line 411 "" yy18: ++YYCURSOR; #line 251 "push.fb.re" { SEND(kRightParen); } -#line 423 "" +#line 416 "" yy20: ++YYCURSOR; #line 252 "push.fb.re" { SEND(kMinus); } -#line 428 "" +#line 421 "" yy22: ++YYCURSOR; #line 253 "push.fb.re" { SEND(kPlus); } -#line 433 "" +#line 426 "" yy24: ++YYCURSOR; #line 254 "push.fb.re" { SEND(kStar); } -#line 438 "" +#line 431 "" yy26: ++YYCURSOR; #line 255 "push.fb.re" { SEND(kSlash); } -#line 443 "" +#line 436 "" yy28: ++YYCURSOR; #line 257 "push.fb.re" { SKIP(); } -#line 448 "" +#line 441 "" yy30: ++YYCURSOR; #line 258 "push.fb.re" { SKIP(); } -#line 453 "" +#line 446 "" yy32: ++YYCURSOR; #line 259 "push.fb.re" { send(kEOF); return 1; } -#line 458 "" +#line 451 "" yy34: ++YYCURSOR; #line 260 "push.fb.re" { SEND(kUnknown); } -#line 463 "" +#line 456 "" yy36: ++YYCURSOR; YYSETSTATE(1); @@ -498,7 +491,7 @@ yy40: } #line 245 "push.fb.re" { SEND(kReturn); } -#line 501 "" +#line 494 "" yy46: yych = *++YYCURSOR; if (yych != 'i') goto yy39; @@ -512,7 +505,7 @@ yy46: } #line 244 "push.fb.re" { SEND(kWhile); } -#line 515 "" +#line 508 "" yy51: yych = *++YYCURSOR; if (yych != 'e') goto yy39; @@ -526,7 +519,7 @@ yy51: } #line 243 "push.fb.re" { SEND(kBreak); } -#line 529 "" +#line 522 "" yy56: yych = *++YYCURSOR; if (yych != 't') goto yy39; @@ -538,7 +531,7 @@ yy56: } #line 242 "push.fb.re" { SEND(kGoto); } -#line 541 "" +#line 534 "" yy60: yych = *++YYCURSOR; if (yych != 's') goto yy39; @@ -550,7 +543,7 @@ yy60: } #line 241 "push.fb.re" { SEND(kElse); } -#line 553 "" +#line 546 "" yy64: yych = *++YYCURSOR; if (yych != 'r') goto yy39; @@ -560,7 +553,7 @@ yy64: } #line 240 "push.fb.re" { SEND(kFor); } -#line 563 "" +#line 556 "" yy67: ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 128) { @@ -568,7 +561,7 @@ yy67: } #line 239 "push.fb.re" { SEND(kIf); } -#line 571 "" +#line 564 "" } #line 261 "push.fb.re" diff --git a/re2c/test/push.fg.c b/re2c/test/push.fg.c index b685c66e..37fb0051 100644 --- a/re2c/test/push.fg.c +++ b/re2c/test/push.fg.c @@ -267,16 +267,12 @@ public: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - static void *yystable[] = { - &&yyFillLabel0, - &&yyFillLabel1, - &&yyFillLabel2, - }; - - if (YYGETSTATE() < 0) { - goto yy0; + switch (YYGETSTATE()) { + default: goto yy0; + case 0: goto yyFillLabel0; + case 1: goto yyFillLabel1; + case 2: goto yyFillLabel2; } - goto *yystable[YYGETSTATE()]; yy0: YYSETSTATE(0); if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); @@ -326,7 +322,7 @@ yy2: yy3: #line 246 "push.fg.re" { SEND(kIdentifier); } -#line 329 "" +#line 325 "" yy4: yych = *++YYCURSOR; if (yych == 'o') goto yy64; @@ -364,62 +360,62 @@ yy12: yy13: #line 247 "push.fg.re" { SEND(kDecimalConstant);} -#line 367 "" +#line 363 "" yy14: ++YYCURSOR; #line 249 "push.fg.re" { SEND(kEqual); } -#line 372 "" +#line 368 "" yy16: ++YYCURSOR; #line 250 "push.fg.re" { SEND(kLeftParen); } -#line 377 "" +#line 373 "" yy18: ++YYCURSOR; #line 251 "push.fg.re" { SEND(kRightParen); } -#line 382 "" +#line 378 "" yy20: ++YYCURSOR; #line 252 "push.fg.re" { SEND(kMinus); } -#line 387 "" +#line 383 "" yy22: ++YYCURSOR; #line 253 "push.fg.re" { SEND(kPlus); } -#line 392 "" +#line 388 "" yy24: ++YYCURSOR; #line 254 "push.fg.re" { SEND(kStar); } -#line 397 "" +#line 393 "" yy26: ++YYCURSOR; #line 255 "push.fg.re" { SEND(kSlash); } -#line 402 "" +#line 398 "" yy28: ++YYCURSOR; #line 257 "push.fg.re" { SKIP(); } -#line 407 "" +#line 403 "" yy30: ++YYCURSOR; #line 258 "push.fg.re" { SKIP(); } -#line 412 "" +#line 408 "" yy32: ++YYCURSOR; #line 259 "push.fg.re" { send(kEOF); return 1; } -#line 417 "" +#line 413 "" yy34: ++YYCURSOR; #line 260 "push.fg.re" { SEND(kUnknown); } -#line 422 "" +#line 418 "" yy36: ++YYCURSOR; YYSETSTATE(1); @@ -457,7 +453,7 @@ yy40: } #line 245 "push.fg.re" { SEND(kReturn); } -#line 460 "" +#line 456 "" yy46: yych = *++YYCURSOR; if (yych != 'i') goto yy39; @@ -471,7 +467,7 @@ yy46: } #line 244 "push.fg.re" { SEND(kWhile); } -#line 474 "" +#line 470 "" yy51: yych = *++YYCURSOR; if (yych != 'e') goto yy39; @@ -485,7 +481,7 @@ yy51: } #line 243 "push.fg.re" { SEND(kBreak); } -#line 488 "" +#line 484 "" yy56: yych = *++YYCURSOR; if (yych != 't') goto yy39; @@ -497,7 +493,7 @@ yy56: } #line 242 "push.fg.re" { SEND(kGoto); } -#line 500 "" +#line 496 "" yy60: yych = *++YYCURSOR; if (yych != 's') goto yy39; @@ -509,7 +505,7 @@ yy60: } #line 241 "push.fg.re" { SEND(kElse); } -#line 512 "" +#line 508 "" yy64: yych = *++YYCURSOR; if (yych != 'r') goto yy39; @@ -519,7 +515,7 @@ yy64: } #line 240 "push.fg.re" { SEND(kFor); } -#line 522 "" +#line 518 "" yy67: ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 128) { @@ -527,7 +523,7 @@ yy67: } #line 239 "push.fg.re" { SEND(kIf); } -#line 530 "" +#line 526 "" } #line 261 "push.fg.re" -- 2.40.0