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.
This commit is contained in:
Michael Matz 2012-04-15 19:29:45 +02:00
parent 86ac6b9bee
commit 1d0a5c2515
2 changed files with 31 additions and 1 deletions

View File

@ -85,6 +85,7 @@ void statement_expr_test(void);
void asm_test(void); void asm_test(void);
void builtin_test(void); void builtin_test(void);
void weak_test(void); void weak_test(void);
void global_data_test(void);
int fib(int n); int fib(int n);
void num(int n); void num(int n);
@ -583,6 +584,7 @@ int main(int argc, char **argv)
asm_test(); asm_test();
builtin_test(); builtin_test();
weak_test(); weak_test();
global_data_test();
return 0; return 0;
} }
@ -2509,3 +2511,31 @@ int getme (struct condstruct *s, int i)
int i4 = (i == 0 ? s : (void*)0)->i; int i4 = (i == 0 ? s : (void*)0)->i;
return i1 + i2 + i3 + i4; 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]);
}

View File

@ -414,7 +414,7 @@ void load(int r, SValue *sv)
} else { } else {
orex(1,0,r,0x8b); orex(1,0,r,0x8b);
o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */ o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */
gen_gotpcrel(fr, sv->sym, fc); gen_gotpcrel(r, sv->sym, fc);
} }
#endif #endif
} else if (is64_type(ft)) { } else if (is64_type(ft)) {