[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] [PATCH] tcc: remove buggy nodata_wanted optimization
From: |
Mikulas Patocka |
Subject: |
[Tinycc-devel] [PATCH] tcc: remove buggy nodata_wanted optimization |
Date: |
Thu, 22 Feb 2018 18:46:53 +0100 (CET) |
User-agent: |
Alpine 2.02 (DEB 1266 2009-07-14) |
Hi
The commit 7f1ab9b1e111b9ea9261eec4b7c6fb0f42591eef ("tccgen:
nodata_wanted") breaks tcc, it generates incorrect code where different
local variables are aliasing each other.
It can be tested with this program, if you compile it with broken tcc, it
prints "2".
#include <stdio.h>
int main(void)
{
goto there;
if (0) {
int a, b;
there:
a = 1;
b = 2;
printf("%d\n", a);
}
return 0;
}
I think that that nodata_wanted misoptimization should be removed at all -
in the C language, you can jump to any location in the function with goto
or switch-case statement - thus reasoning such as "all the variables
behind if (0) are unreachable" is incorrect.
If you wanted to do that optimization correctly, you'd need to build
control flow graph, and tcc is just too simple to do that.
Mikulas
Signed-off-by: Mikulas Patocka <address@hidden>
---
tccgen.c | 31 ++++---------------
tests/tests2/96_nodata_wanted.c | 56 -----------------------------------
tests/tests2/96_nodata_wanted.expect | 11 ------
3 files changed, 7 insertions(+), 91 deletions(-)
Index: tinycc/tccgen.c
===================================================================
--- tinycc.orig/tccgen.c 2018-02-22 01:42:11.000000000 +0100
+++ tinycc/tccgen.c 2018-02-22 18:32:33.000000000 +0100
@@ -51,8 +51,7 @@ ST_DATA SValue __vstack[1+VSTACK_SIZE],
ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* no code generation wanted */
-#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted
either */
-#define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data
output */
+#define STATIC_DATA_WANTED (nocode_wanted & 0x80000000) /* only static data
output */
ST_DATA int global_expr; /* true if compound literals must be allocated
globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return
instruction) */
ST_DATA int func_var; /* true if current function is variadic (used by return
instruction) */
@@ -1296,8 +1295,6 @@ ST_FUNC int gv(int rc)
/* CPUs usually cannot use float constants, so we store them
generically in data segment */
size = type_size(&vtop->type, &align);
- if (NODATA_WANTED)
- size = 0, align = 1;
offset = section_add(data_section, size, align);
vpush_ref(&vtop->type, data_section, offset, size);
vswap();
@@ -4662,10 +4659,8 @@ ST_FUNC void unary(void)
type.t |= VT_ARRAY;
type.ref->c = len;
vpush_ref(&type, data_section, data_section->data_offset, len);
- if (!NODATA_WANTED) {
- ptr = section_ptr_add(data_section, len);
- memcpy(ptr, funcname, len);
- }
+ ptr = section_ptr_add(data_section, len);
+ memcpy(ptr, funcname, len);
next();
}
break;
@@ -6423,7 +6418,7 @@ static int decl_designator(CType *type,
vstore();
}
vpop();
- } else if (!NODATA_WANTED) {
+ } else {
c_end = c + nb_elems * elem_size;
if (c_end > sec->data_allocated)
section_realloc(sec, c_end);
@@ -6467,11 +6462,6 @@ static void init_putv(CType *type, Secti
)
tcc_error("initializer element is not computable at load time");
- if (NODATA_WANTED) {
- vtop--;
- return;
- }
-
size = type_size(type, &align);
section_reserve(sec, c + size);
ptr = sec->data + c;
@@ -6711,8 +6701,7 @@ static void decl_initializer(CType *type
string in global variable, we handle it
specifically */
if (sec && tok == TOK_STR && size1 == 1) {
- if (!NODATA_WANTED)
- memcpy(sec->data + c + len, tokc.str.data, nb);
+ memcpy(sec->data + c + len, tokc.str.data, nb);
} else {
for(i=0;i<nb;i++) {
if (tok == TOK_STR)
@@ -6830,11 +6819,11 @@ static void decl_initializer_alloc(CType
Sym *sym = NULL;
int saved_nocode_wanted = nocode_wanted;
#ifdef CONFIG_TCC_BCHECK
- int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
+ int bcheck = tcc_state->do_bounds_check;
#endif
if (type->t & VT_STATIC)
- nocode_wanted |= NODATA_WANTED ? 0x40000000 : 0x80000000;
+ nocode_wanted |= 0x80000000;
flexible_array = NULL;
if ((type->t & VT_BTYPE) == VT_STRUCT) {
@@ -6900,9 +6889,6 @@ static void decl_initializer_alloc(CType
align = 1;
}
- if (NODATA_WANTED)
- size = 0, align = 1;
-
if ((r & VT_VALMASK) == VT_LOCAL) {
sec = NULL;
#ifdef CONFIG_TCC_BCHECK
@@ -7009,9 +6995,6 @@ static void decl_initializer_alloc(CType
if (type->t & VT_VLA) {
int a;
- if (NODATA_WANTED)
- goto no_alloc;
-
/* save current stack pointer */
if (vlas_in_scope == 0) {
if (vla_sp_root_loc == -1)
Index: tinycc/tests/tests2/96_nodata_wanted.c
===================================================================
--- tinycc.orig/tests/tests2/96_nodata_wanted.c 2018-02-22 01:42:11.000000000
+0100
+++ tinycc/tests/tests2/96_nodata_wanted.c 2018-02-22 01:42:11.000000000
+0100
@@ -25,60 +25,4 @@ void foo() {
short w = &foo; /* 2 cast warnings */
}
-#elif defined test_data_suppression_off || defined test_data_suppression_on
-
-#if defined test_data_suppression_on
-# define SKIP 1
-#else
-# define SKIP 0
-#endif
-
-#include <stdio.h>
-/* some gcc headers #define __attribute__ to empty if it's not gcc */
-#undef __attribute__
-
-int main()
-{
- __label__ ts0, te0, ts1, te1;
- int tl, dl;
-
- static char ds0 = 0;
- static char de0 = 0;
- /* get reference size of empty jmp */
-ts0:;
- if (!SKIP) {}
-te0:;
- dl = -(&de0 - &ds0);
- tl = -(&&te0 - &&ts0);
-
- /* test data and code suppression */
- static char ds1 = 0;
-ts1:;
- if (!SKIP) {
- static void *p = (void*)&main;
- static char cc[] = "static string";
- static double d = 8.0;
-
- static struct __attribute__((packed)) {
- unsigned x : 12;
- unsigned char y : 7;
- unsigned z : 28, a: 4, b: 5;
- } s = { 0x333,0x44,0x555555,6,7 };
-
- printf("data:\n");
- printf(" %d - %.1f - %.1f - %s - %s\n",
- sizeof 8.0, 8.0, d, __FUNCTION__, cc);
- printf(" %x %x %x %x %x\n",
- s.x, s.y, s.z, s.a, s.b);
- }
-te1:;
- static char de1 = 0;
-
- dl += &de1 - &ds1;
- tl += &&te1 - &&ts1;
- printf("size of data/text:\n %s/%s\n",
- dl ? "non-zero":"zero", tl ? "non-zero":"zero");
- /*printf("# %d/%d\n", dl, tl);*/
-}
-
#endif
Index: tinycc/tests/tests2/96_nodata_wanted.expect
===================================================================
--- tinycc.orig/tests/tests2/96_nodata_wanted.expect 2018-02-22
01:42:11.000000000 +0100
+++ tinycc/tests/tests2/96_nodata_wanted.expect 2018-02-22 01:42:11.000000000
+0100
@@ -10,14 +10,3 @@
[test_local_data_noerror]
96_nodata_wanted.c:25: warning: assignment makes integer from pointer without
a cast
96_nodata_wanted.c:25: warning: nonportable conversion from pointer to
char/short
-
-[test_data_suppression_off]
-data:
- 8 - 8.0 - 8.0 - main - static string
- 333 44 555555 6 7
-size of data/text:
- non-zero/non-zero
-
-[test_data_suppression_on]
-size of data/text:
- zero/zero
- [Tinycc-devel] [PATCH] tcc: remove buggy nodata_wanted optimization,
Mikulas Patocka <=