diff --git a/arm64-gen.c b/arm64-gen.c index 26cf5d1..efe4246 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -580,8 +580,8 @@ ST_FUNC void store(int r, SValue *sv) static void arm64_gen_bl_or_b(int b) { - if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { - assert(!b && (vtop->r & VT_SYM)); + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { + assert(!b); greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0); o(0x94000000); // bl . } diff --git a/tests/tests2/07_function.c b/tests/tests2/07_function.c index 0477ce1..bfb0974 100644 --- a/tests/tests2/07_function.c +++ b/tests/tests2/07_function.c @@ -15,6 +15,11 @@ void qfunc() printf("qfunc()\n"); } +void zfunc() +{ + ((void (*)(void))0) (); +} + int main() { printf("%d\n", myfunc(3)); diff --git a/x86_64-gen.c b/x86_64-gen.c index 2672e13..045dd2c 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -623,20 +623,13 @@ static void gcall_or_jmp(int is_jmp) { int r; if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && - ((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) { - /* constant case */ - if (vtop->r & VT_SYM) { - /* relocation case */ + ((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) { + /* constant symbolic case -> simple relocation */ #ifdef TCC_TARGET_PE - greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); + greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); #else - greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4)); + greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4)); #endif - } else { - /* put an empty PC32 relocation */ - put_elf_reloca(symtab_section, cur_text_section, - ind + 1, R_X86_64_PC32, 0, (int)(vtop->c.i-4)); - } oad(0xe8 + is_jmp, 0); /* call/jmp im */ } else { /* otherwise, indirect call */