If a symbolic reference is offsetted by a constant > 32bit the backends can't deal with that, so don't construct such values.
Unified · Split
| @@ -1775,8 +1775,13 @@ static void gen_opic(int op) · 1774 unmodified lines | ||
| 1775 | 1775 | /* symbol + constant case */ |
| 1776 | 1776 | if (op == '-') |
| 1777 | 1777 | l2 = -l2; |
| 1778 | + l2 += vtop[-1].c.i; | |
| 1779 | + /* The backends can't always deal with addends to symbols | |
| 1780 | + larger than +-1<<31. Don't construct such. */ | |
| 1781 | + if ((int)l2 != l2) | |
| 1782 | + goto general_case; | |
| 1778 | 1783 | vtop--; |
| 1779 | − vtop->c.i += l2; | |
| 1784 | + vtop->c.i = l2; | |
| 1780 | 1785 | } else { |
| 1781 | 1786 | general_case: |
| 1782 | 1787 | if (!nocode_wanted) { |
| @@ -2429,6 +2429,19 @@ void getmyaddress(void) · 2428 unmodified lines | ||
| 2429 | 2429 | { |
| 2430 | 2430 | printf("in getmyaddress\n"); |
| 2431 | 2431 | } |
| 2432 | + | |
| 2433 | +#ifdef __LP64__ | |
| 2434 | +long __pa_symbol(void) | |
| 2435 | +{ | |
| 2436 | + /* This 64bit constant was handled incorrectly, it was used as addend | |
| 2437 | + (which can hold 64bit just fine) in connection with a symbol, | |
| 2438 | + and TCC generates wrong code for that (displacements are 32bit only). | |
| 2439 | + This effectively is "+ 0x80000000", and if addresses of globals | |
| 2440 | + are below 2GB the result should be a number without high 32 bits set. */ | |
| 2441 | + return ((long)(((unsigned long)(&rel1))) - (0xffffffff80000000UL)); | |
| 2442 | +} | |
| 2443 | +#endif | |
| 2444 | + | |
| 2432 | 2445 | unsigned long theaddress = (unsigned long)getmyaddress; |
| 2433 | 2446 | void relocation_test(void) |
| 2434 | 2447 | { |
| @@ -2436,6 +2449,9 @@ void relocation_test(void) · 1 unmodified line | ||
| 2436 | 2449 | printf("*rel1=%d\n", *rel1); |
| 2437 | 2450 | printf("*rel2=%d\n", *rel2); |
| 2438 | 2451 | fptr(); |
| 2452 | +#ifdef __LP64__ | |
| 2453 | + printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63); | |
| 2454 | +#endif | |
| 2439 | 2455 | } |
| 2440 | 2456 | |
| 2441 | 2457 | void old_style_f(a,b,c) |
| @@ -349,6 +349,8 @@ void load(int r, SValue *sv) · 348 unmodified lines | ||
| 349 | 349 | fr = sv->r; |
| 350 | 350 | ft = sv->type.t & ~VT_DEFSIGN; |
| 351 | 351 | fc = sv->c.i; |
| 352 | + if (fc != sv->c.i && (fr & VT_SYM)) | |
| 353 | + tcc_error("64 bit addend in load"); | |
| 352 | 354 | |
| 353 | 355 | ft &= ~(VT_VOLATILE | VT_CONSTANT); |
| 354 | 356 | |
| @@ -528,9 +530,11 @@ void store(int r, SValue *v) · 173 unmodified lines | ||
| 528 | 530 | v = pe_getimport(v, &v2); |
| 529 | 531 | #endif |
| 530 | 532 | |
| 533 | + fr = v->r & VT_VALMASK; | |
| 531 | 534 | ft = v->type.t; |
| 532 | 535 | fc = v->c.i; |
| 533 | − fr = v->r & VT_VALMASK; | |
| 536 | + if (fc != v->c.i && (fr & VT_SYM)) | |
| 537 | + tcc_error("64 bit addend in store"); | |
| 534 | 538 | ft &= ~(VT_VOLATILE | VT_CONSTANT); |
| 535 | 539 | bt = ft & VT_BTYPE; |
| 536 | 540 | |