mirror of
https://github.com/frida/tinycc
synced 2024-12-25 06:26:49 +03:00
short_call_convention patch from tcc bugzilla
BUGZILLA: interfacing with other compilers extend the return value to the whole register if necessary. visual studio and gcc do not always set the whole eax register when assigning the return value of a function. We've encountered wrong execution results on i386 platforms with an application that uses both code compiled with TCC and code compiled with other compilers (namely: Visual Studio on Windows, and GCC on Linux). When calling a function that returns an integer value shorter than 32 bits, TCC reads the return value from the whole EAX register, although the code generated by the other compilers can only sets AL for 8 bit values or AX for 16 bits values, and the rest of EAX can be anything. We worked around this with the attached patch on i386 for the version 0.9.26, but we did not look at other platforms to find if there are similar issues.
This commit is contained in:
parent
9d679e3916
commit
a37f8cfc80
25
i386-gen.c
25
i386-gen.c
@ -354,6 +354,7 @@ static void gcall_or_jmp(int is_jmp)
|
||||
{
|
||||
int r;
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
int rt;
|
||||
/* constant case */
|
||||
if (vtop->r & VT_SYM) {
|
||||
/* relocation case */
|
||||
@ -365,6 +366,30 @@ static void gcall_or_jmp(int is_jmp)
|
||||
ind + 1, R_386_PC32, 0);
|
||||
}
|
||||
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||
/* extend the return value to the whole register if necessary
|
||||
visual studio and gcc do not always set the whole eax register
|
||||
when assigning the return value of a function */
|
||||
rt = vtop->type.ref->type.t;
|
||||
switch (rt & VT_BTYPE) {
|
||||
case VT_BYTE:
|
||||
if (rt & VT_UNSIGNED) {
|
||||
o(0xc0b60f); /* movzx %al, %eax */
|
||||
}
|
||||
else {
|
||||
o(0xc0be0f); /* movsx %al, %eax */
|
||||
}
|
||||
break;
|
||||
case VT_SHORT:
|
||||
if (rt & VT_UNSIGNED) {
|
||||
o(0xc0b70f); /* movzx %ax, %eax */
|
||||
}
|
||||
else {
|
||||
o(0xc0bf0f); /* movsx %ax, %eax */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
r = gv(RC_INT);
|
||||
|
Loading…
Reference in New Issue
Block a user