mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
implemented thiscall by copying logic from fastcall
implemented improved thiscall by using mov ecx instead of pop ecx include __thiscall and __thiscall__ as aliases remove fake line in test
This commit is contained in:
parent
8cd21e91cc
commit
3b943bec5d
26
i386-gen.c
26
i386-gen.c
@ -410,6 +410,8 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
{
|
||||
int size, align, r, args_size, i, func_call;
|
||||
Sym *func_sym;
|
||||
// Look ahead to the function on the stack to get the function call type
|
||||
int func_call2 = ((vtop - nb_args)->type.ref)->f.func_call;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
@ -418,6 +420,12 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
|
||||
args_size = 0;
|
||||
for(i = 0;i < nb_args; i++) {
|
||||
if (func_call2 == FUNC_THISCALL && i == (nb_args - 1)) {
|
||||
// If thiscall, zap the last push, as it is `this`. Instead, mov into ecx
|
||||
size = 0;
|
||||
load(get_reg(RC_ECX), vtop);
|
||||
}
|
||||
else
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
size = type_size(&vtop->type, &align);
|
||||
/* align to stack align size */
|
||||
@ -503,7 +511,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
|
||||
gcall_or_jmp(0);
|
||||
|
||||
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
|
||||
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_THISCALL && func_call != FUNC_FASTCALLW)
|
||||
gadd_sp(args_size);
|
||||
vtop--;
|
||||
}
|
||||
@ -523,6 +531,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
const uint8_t *fastcall_regs_ptr;
|
||||
Sym *sym;
|
||||
CType *type;
|
||||
int thiscall_nb_regs;
|
||||
|
||||
sym = func_type->ref;
|
||||
func_call = sym->f.func_call;
|
||||
@ -540,6 +549,11 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
fastcall_nb_regs = 0;
|
||||
fastcall_regs_ptr = NULL;
|
||||
}
|
||||
|
||||
if (func_call == FUNC_THISCALL) {
|
||||
thiscall_nb_regs = 1;
|
||||
}
|
||||
|
||||
param_index = 0;
|
||||
|
||||
ind += FUNC_PROLOG_SIZE;
|
||||
@ -575,6 +589,14 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
o(0x89); /* movl */
|
||||
gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
|
||||
param_addr = loc;
|
||||
}
|
||||
else if(param_index < thiscall_nb_regs) {
|
||||
/* Why ? */
|
||||
/* save THISCALL register; ECX */
|
||||
loc -= 4;
|
||||
o(0x89); /* movl */
|
||||
gen_modrm(TREG_ECX, VT_LOCAL, NULL, loc);
|
||||
param_addr = loc;
|
||||
} else {
|
||||
param_addr = addr;
|
||||
addr += size;
|
||||
@ -585,7 +607,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
}
|
||||
func_ret_sub = 0;
|
||||
/* pascal type call or fastcall ? */
|
||||
if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW)
|
||||
if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW || func_call == FUNC_THISCALL)
|
||||
func_ret_sub = addr - 8;
|
||||
#if !defined(TCC_TARGET_PE) && !TARGETOS_FreeBSD || TARGETOS_OpenBSD
|
||||
else if (func_vc)
|
||||
|
1
tcc.h
1
tcc.h
@ -634,6 +634,7 @@ typedef struct DLLReference {
|
||||
#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
|
||||
#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
|
||||
#define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
|
||||
#define FUNC_THISCALL 6 /* first param in %ecx */
|
||||
|
||||
/* field 'Sym.t' for macros */
|
||||
#define MACRO_OBJ 0 /* object like macro */
|
||||
|
7
tccgen.c
7
tccgen.c
@ -3974,7 +3974,12 @@ redo:
|
||||
case TOK_FASTCALL2:
|
||||
case TOK_FASTCALL3:
|
||||
ad->f.func_call = FUNC_FASTCALLW;
|
||||
break;
|
||||
break;
|
||||
case TOK_THISCALL1:
|
||||
case TOK_THISCALL2:
|
||||
case TOK_THISCALL3:
|
||||
ad->f.func_call = FUNC_THISCALL;
|
||||
break;
|
||||
#endif
|
||||
case TOK_MODE:
|
||||
skip('(');
|
||||
|
3
tcctok.h
3
tcctok.h
@ -135,6 +135,9 @@
|
||||
DEF(TOK_FASTCALL1, "fastcall")
|
||||
DEF(TOK_FASTCALL2, "__fastcall")
|
||||
DEF(TOK_FASTCALL3, "__fastcall__")
|
||||
DEF(TOK_THISCALL1, "thiscall")
|
||||
DEF(TOK_THISCALL2, "__thiscall")
|
||||
DEF(TOK_THISCALL3, "__thiscall__")
|
||||
DEF(TOK_REGPARM1, "regparm")
|
||||
DEF(TOK_REGPARM2, "__regparm__")
|
||||
DEF(TOK_CLEANUP1, "cleanup")
|
||||
|
17
tests/thiscall/thiscall-test.c
Normal file
17
tests/thiscall/thiscall-test.c
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __thiscall
|
||||
#define __thiscall __attribute__((thiscall))
|
||||
#endif
|
||||
#ifndef __cdecl
|
||||
#define __cdecl __attribute__((cdecl))
|
||||
#endif
|
||||
#ifndef __stdcall
|
||||
#define __stdcall __attribute__((stdcall))
|
||||
#endif
|
||||
|
||||
void ( __thiscall * const thisCall1 ) ( void * _this, int a ) = ( void ( __thiscall * ) ( void * _this, int a ) ) 0x4788a0;
|
||||
|
||||
int main() {
|
||||
thisCall1((void*) 0xDEADBEEF, 1000);
|
||||
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user