we activate code (CODE_ON) only when the target labels are used, which doesn't happen during nocode_wanted regions. So, we cannot just switch off code either during nocode_wanted regions, nothing would switch it on again (except in the happy coincidences when we outright save/restore nocode_wanted). See the testcase for one example, reduced from code generated by yarpgen: in ext = (xxx || 1) // #1 || ((xxx && 1) || 1) // #2 code is first suppressed in #1 normally, then (before this commit) was suppressed via CODE_OFF during #2 (via indirect gjmp), then the suppression from #1 was undone, but nothing undoes the suppression from #2 anymore as everything therein was generated while nocode_wanted was active. So, we would either need to save/restore nocode_wanted around some more expressions, activate CODE_ON also with unused labels (breaks some optimizations we want), or deactivate CODE_OFF only when not already in nocode_wanted state. This does the latter.
Unified · Split
| @@ -56,7 +56,7 @@ ST_DATA int nocode_wanted; /* no code generation wanted */ · 55 unmodified lines | |||
| 56 | #define unevalmask 0xffff /* unevaluated subexpression */ | 56 | #define unevalmask 0xffff /* unevaluated subexpression */ |
| 57 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ | 57 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ |
| 58 | #define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */ | 58 | #define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */ |
| 59 | #define CODE_OFF() (nocode_wanted |= 0x20000000) | 59 | #define CODE_OFF() if(!nocode_wanted)(nocode_wanted |= 0x20000000) |
| 60 | #define CODE_ON() (nocode_wanted &= ~0x20000000) | 60 | #define CODE_ON() (nocode_wanted &= ~0x20000000) |
| 61 | 61 | ||
| 62 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ | 62 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ |
| @@ -44,6 +44,16 @@ void bla(void) · 43 unmodified lines | |||
| 44 | get_args(!!__ret, sizeof(__ret)); | 44 | get_args(!!__ret, sizeof(__ret)); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | int ext; | ||
| 48 | |||
| 49 | void broken_jumpopt (int xxx) | ||
| 50 | { | ||
| 51 | /* This was broken in 8227db3a2 by code suppression during suppressed | ||
| 52 | code :) */ | ||
| 53 | ext = (xxx || 1) || ((xxx && 1) || 1); | ||
| 54 | printf("okay: %d %d\n", xxx, ext); | ||
| 55 | } | ||
| 56 | |||
| 47 | _Bool chk(unsigned long addr, unsigned long limit, unsigned long size) | 57 | _Bool chk(unsigned long addr, unsigned long limit, unsigned long size) |
| 48 | { | 58 | { |
| 49 | _Bool ret; | 59 | _Bool ret; |
| @@ -65,5 +75,6 @@ int main() · 15 unmodified lines | |||
| 65 | else | 75 | else |
| 66 | printf("okay\n"); | 76 | printf("okay\n"); |
| 67 | bla(); | 77 | bla(); |
| 78 | broken_jumpopt(42); | ||
| 68 | return 0; | 79 | return 0; |
| 69 | } | 80 | } |
| @@ -1,2 +1,3 @@ | |||
| 1 | okay | 1 | okay |
| 2 | okay | 2 | okay |
| 3 | okay: 42 1 | ||