From 1d0a5c251553d8d9199ad18d4780bf356f456298 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sun, 15 Apr 2012 19:29:45 +0200 Subject: [PATCH 4/9] x86_64: Fix segfault for global data When offsetted addresses of global non-static data are computed multiple times in the same statement the x86_64 backend uses gen_gotpcrel with offset, which implements an add insn on the register given. load() uses the R member of the to-be-loaded value, which doesn't yet have a reg assigned in all cases. So use the register we're supposed to load the value into as that register. --- tests/tcctest.c | 30 ++++++++++++++++++++++++++++++ x86_64-gen.c | 2 +- 2 files changed, 31 insertions(+), 1 deletions(-) diff --git a/tests/tcctest.c b/tests/tcctest.c index fcd9822..03be501 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -85,6 +85,7 @@ void statement_expr_test(void); void asm_test(void); void builtin_test(void); void weak_test(void); +void global_data_test(void); int fib(int n); void num(int n); @@ -583,6 +584,7 @@ int main(int argc, char **argv) asm_test(); builtin_test(); weak_test(); + global_data_test(); return 0; } @@ -2509,3 +2511,31 @@ int getme (struct condstruct *s, int i) int i4 = (i == 0 ? s : (void*)0)->i; return i1 + i2 + i3 + i4; } + +struct global_data +{ + int a[40]; + int *b[40]; +}; + +struct global_data global_data; + +int global_data_getstuff (int *, int); + +void global_data_callit (int i) +{ + *global_data.b[i] = global_data_getstuff (global_data.b[i], 1); +} + +int global_data_getstuff (int *p, int i) +{ + return *p + i; +} + +void global_data_test (void) +{ + global_data.a[0] = 42; + global_data.b[0] = &global_data.a[0]; + global_data_callit (0); + printf ("%d\n", global_data.a[0]); +} diff --git a/x86_64-gen.c b/x86_64-gen.c index 49cfdd1..0f86b3a 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -414,7 +414,7 @@ void load(int r, SValue *sv) } else { orex(1,0,r,0x8b); o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */ - gen_gotpcrel(fr, sv->sym, fc); + gen_gotpcrel(r, sv->sym, fc); } #endif } else if (is64_type(ft)) { -- 1.7.3.4