mirror of
https://github.com/frida/tinycc
synced 2024-12-25 14:36:49 +03:00
Fix sub-int returns on x86-64 and i386
the ABIs (and other compilers) extend sub-int return values in the caller. TCC extends them in the callee. For compatibility with those other compilers we have extend them in the caller as well. That introduces a useless double extension in pure TCC-compiled code, but fixing that generally requires that the code generator of TCC would understand sub-int types. For the time being bite the bullet.
This commit is contained in:
parent
5f737fb4d3
commit
749d19d70b
@ -369,6 +369,7 @@ static void gcall_or_jmp(int is_jmp)
|
||||
rt = vtop->type.ref->type.t;
|
||||
switch (rt & VT_BTYPE) {
|
||||
case VT_BYTE:
|
||||
case VT_BOOL:
|
||||
if (rt & VT_UNSIGNED) {
|
||||
o(0xc0b60f); /* movzx %al, %eax */
|
||||
}
|
||||
|
19
x86_64-gen.c
19
x86_64-gen.c
@ -920,7 +920,7 @@ void gfunc_call(int nb_args)
|
||||
|
||||
/* other compilers don't clear the upper bits when returning char/short */
|
||||
bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED);
|
||||
if (bt == (VT_BYTE | VT_UNSIGNED))
|
||||
if (bt == (VT_BYTE | VT_UNSIGNED) || (bt & VT_TYPE) == VT_BOOL)
|
||||
o(0xc0b60f); /* movzbl %al, %eax */
|
||||
else if (bt == VT_BYTE)
|
||||
o(0xc0be0f); /* movsbl %al, %eax */
|
||||
@ -1230,7 +1230,7 @@ void gfunc_call(int nb_args)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
CType type;
|
||||
int size, align, r, args_size, stack_adjust, i, reg_count;
|
||||
int size, align, r, args_size, stack_adjust, i, reg_count, bt;
|
||||
int nb_reg_args = 0;
|
||||
int nb_sse_args = 0;
|
||||
int sse_reg, gen_reg;
|
||||
@ -1413,6 +1413,21 @@ void gfunc_call(int nb_args)
|
||||
gcall_or_jmp(0);
|
||||
if (args_size)
|
||||
gadd_sp(args_size);
|
||||
/* other compilers don't clear the upper bits when returning char/short,
|
||||
TCC does so for convenience. When we'd stay purely within TCC compiled
|
||||
code we wouldn't need this, but for compatibility we have to extend.
|
||||
Ideally TCC wouldn't extend at return statements to not do double
|
||||
extensions, or would understand sub-int types during expression
|
||||
evaluation. */
|
||||
bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED);
|
||||
if (bt == (VT_BYTE | VT_UNSIGNED) || (bt & VT_TYPE) == VT_BOOL)
|
||||
o(0xc0b60f); /* movzbl %al, %eax */
|
||||
else if (bt == VT_BYTE)
|
||||
o(0xc0be0f); /* movsbl %al, %eax */
|
||||
else if (bt == VT_SHORT)
|
||||
o(0x98); /* cwtl */
|
||||
else if (bt == (VT_SHORT | VT_UNSIGNED))
|
||||
o(0xc0b70f); /* movzwl %al, %eax */
|
||||
vtop--;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user