mirror of
https://github.com/frida/tinycc
synced 2024-11-28 10:33:07 +03:00
first stage for structure assign - added more generic function call code generation
This commit is contained in:
parent
f22a32342b
commit
cb1c8c892c
125
tcc.c
125
tcc.c
@ -270,7 +270,7 @@ void expr();
|
|||||||
void decl();
|
void decl();
|
||||||
void decl_initializer(int t, int c, int first, int size_only);
|
void decl_initializer(int t, int c, int first, int size_only);
|
||||||
int decl_initializer_alloc(int t, int has_init);
|
int decl_initializer_alloc(int t, int has_init);
|
||||||
int gv();
|
int gv(void);
|
||||||
void move_reg();
|
void move_reg();
|
||||||
void save_reg();
|
void save_reg();
|
||||||
void macro_subst(int **tok_str, int *tok_len,
|
void macro_subst(int **tok_str, int *tok_len,
|
||||||
@ -1436,6 +1436,10 @@ void vset(t, v)
|
|||||||
/******************************************************/
|
/******************************************************/
|
||||||
/* X86 code generator */
|
/* X86 code generator */
|
||||||
|
|
||||||
|
typedef struct GFuncContext {
|
||||||
|
int nb_args;
|
||||||
|
} GFuncContext;
|
||||||
|
|
||||||
void g(c)
|
void g(c)
|
||||||
{
|
{
|
||||||
*(char *)ind++ = c;
|
*(char *)ind++ = c;
|
||||||
@ -1555,12 +1559,42 @@ void store(r, ft, fc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfunc_param(void)
|
/* start function call and return function call context */
|
||||||
|
void gfunc_start(GFuncContext *c)
|
||||||
{
|
{
|
||||||
o(0x50 + gv()); /* push r */
|
c->nb_args = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gjmp(t)
|
/* push function parameter which is in (vt, vc) */
|
||||||
|
void gfunc_param(GFuncContext *c)
|
||||||
|
{
|
||||||
|
o(0x50 + gv()); /* push r */
|
||||||
|
c->nb_args++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate function call with address in (ft, fc) and free function */
|
||||||
|
void gfunc_call(GFuncContext *c, int ft, int fc)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = ft & VT_VALMASK;
|
||||||
|
if (r == VT_CONST) {
|
||||||
|
/* forward reference */
|
||||||
|
if (ft & VT_FORWARD) {
|
||||||
|
*(int *)fc = psym(0xe8, *(int *)fc);
|
||||||
|
} else
|
||||||
|
oad(0xe8, fc - ind - 5);
|
||||||
|
} else if (r == VT_LOCAL) {
|
||||||
|
oad(0x95ff, fc); /* call *xxx(%ebp) */
|
||||||
|
} else {
|
||||||
|
/* not actually used */
|
||||||
|
o(0xff); /* call *reg */
|
||||||
|
o(0xd0 + r);
|
||||||
|
}
|
||||||
|
if (c->nb_args)
|
||||||
|
oad(0xc481, c->nb_args * 4); /* addl $xxx, %esp */
|
||||||
|
}
|
||||||
|
|
||||||
|
int gjmp(int t)
|
||||||
{
|
{
|
||||||
return psym(0xe9, t);
|
return psym(0xe9, t);
|
||||||
}
|
}
|
||||||
@ -1758,13 +1792,16 @@ void move_reg(r, s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert a stack entry in register */
|
/* convert a stack entry in register. lvalues are converted as
|
||||||
|
values. Cannot be used if cannot be converted to register value
|
||||||
|
(such as structures). */
|
||||||
int gvp(int *p)
|
int gvp(int *p)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
r = p[0] & VT_VALMASK;
|
r = p[0] & VT_VALMASK;
|
||||||
if (r >= VT_CONST || (p[0] & VT_LVAL))
|
if (r >= VT_CONST || (p[0] & VT_LVAL))
|
||||||
r = get_reg();
|
r = get_reg();
|
||||||
|
/* NOTE: get_reg can modify p[] */
|
||||||
load(r, p[0], p[1]);
|
load(r, p[0], p[1]);
|
||||||
p[0] = (p[0] & VT_TYPE) | r;
|
p[0] = (p[0] & VT_TYPE) | r;
|
||||||
return r;
|
return r;
|
||||||
@ -1788,7 +1825,7 @@ void vpop(int *ft, int *fc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* generate a value in a register from vt and vc */
|
/* generate a value in a register from vt and vc */
|
||||||
int gv()
|
int gv(void)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
vpush();
|
vpush();
|
||||||
@ -1997,12 +2034,42 @@ int mk_pointer(int t)
|
|||||||
/* store value in lvalue pushed on stack */
|
/* store value in lvalue pushed on stack */
|
||||||
void vstore()
|
void vstore()
|
||||||
{
|
{
|
||||||
int ft, fc, r, t;
|
int ft, fc, r, t, size, align;
|
||||||
|
GFuncContext gf;
|
||||||
|
|
||||||
|
if (vt & VT_STRUCT) {
|
||||||
|
/* if structure, only generate pointer */
|
||||||
|
/* structure assignment : generate memcpy */
|
||||||
|
/* XXX: optimize if small size */
|
||||||
|
|
||||||
|
gfunc_start(&gf);
|
||||||
|
/* type size */
|
||||||
|
ft = vt;
|
||||||
|
fc = vc;
|
||||||
|
size = type_size(vt, &align);
|
||||||
|
vset(VT_CONST, size);
|
||||||
|
gfunc_param(&gf);
|
||||||
|
/* source */
|
||||||
|
vt = ft & ~VT_LVAL;
|
||||||
|
vc = fc;
|
||||||
|
gfunc_param(&gf);
|
||||||
|
/* destination */
|
||||||
|
vpop(&vt, &vc);
|
||||||
|
vt &= ~VT_LVAL;
|
||||||
|
gfunc_param(&gf);
|
||||||
|
|
||||||
|
save_regs();
|
||||||
|
gfunc_call(&gf, VT_CONST, (int)&memcpy);
|
||||||
|
|
||||||
|
/* generate again current type */
|
||||||
|
vt = ft;
|
||||||
|
vc = fc;
|
||||||
|
} else {
|
||||||
r = gv(); /* generate value */
|
r = gv(); /* generate value */
|
||||||
vpush();
|
vpush();
|
||||||
ft = vstack_ptr[-4];
|
ft = vstack_ptr[-4];
|
||||||
fc = vstack_ptr[-3];
|
fc = vstack_ptr[-3];
|
||||||
|
/* if lvalue was saved on stack, must read it */
|
||||||
if ((ft & VT_VALMASK) == VT_LLOCAL) {
|
if ((ft & VT_VALMASK) == VT_LLOCAL) {
|
||||||
t = get_reg();
|
t = get_reg();
|
||||||
load(t, VT_LOCAL | VT_LVAL, fc);
|
load(t, VT_LOCAL | VT_LVAL, fc);
|
||||||
@ -2010,6 +2077,7 @@ void vstore()
|
|||||||
}
|
}
|
||||||
store(r, ft, fc);
|
store(r, ft, fc);
|
||||||
vstack_ptr -= 4;
|
vstack_ptr -= 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* post defines POST/PRE add. c is the token ++ or -- */
|
/* post defines POST/PRE add. c is the token ++ or -- */
|
||||||
@ -2330,8 +2398,9 @@ void indir()
|
|||||||
|
|
||||||
void unary()
|
void unary()
|
||||||
{
|
{
|
||||||
int n, t, ft, fc, p, r, align;
|
int n, t, ft, fc, p, align;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
GFuncContext gf;
|
||||||
|
|
||||||
if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
|
if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
|
||||||
vset(VT_CONST, tokc);
|
vset(VT_CONST, tokc);
|
||||||
@ -2498,16 +2567,10 @@ void unary()
|
|||||||
skip(']');
|
skip(']');
|
||||||
} else if (tok == '(') {
|
} else if (tok == '(') {
|
||||||
/* function call */
|
/* function call */
|
||||||
|
vt &= ~VT_LVAL; /* no lvalue */
|
||||||
|
vpush(); /* push function address */
|
||||||
save_regs(); /* save used temporary registers */
|
save_regs(); /* save used temporary registers */
|
||||||
/* lvalue is implied */
|
gfunc_start(&gf);
|
||||||
vt = vt & VT_LVALN;
|
|
||||||
if ((vt & VT_VALMASK) != VT_CONST) {
|
|
||||||
/* evaluate function address */
|
|
||||||
r = gv();
|
|
||||||
o(0x50 + r); /* push r */
|
|
||||||
}
|
|
||||||
ft = vt;
|
|
||||||
fc = vc;
|
|
||||||
next();
|
next();
|
||||||
#ifdef INVERT_FUNC_PARAMS
|
#ifdef INVERT_FUNC_PARAMS
|
||||||
{
|
{
|
||||||
@ -2542,13 +2605,11 @@ void unary()
|
|||||||
|
|
||||||
/* now generate code in reverse order by reading the stack */
|
/* now generate code in reverse order by reading the stack */
|
||||||
saved_macro_ptr = macro_ptr;
|
saved_macro_ptr = macro_ptr;
|
||||||
t = 0;
|
|
||||||
while (args) {
|
while (args) {
|
||||||
t += 4;
|
|
||||||
macro_ptr = (int *)args->c;
|
macro_ptr = (int *)args->c;
|
||||||
next();
|
next();
|
||||||
expr_eq();
|
expr_eq();
|
||||||
gfunc_param();
|
gfunc_param(&gf);
|
||||||
s1 = args->prev;
|
s1 = args->prev;
|
||||||
free((int *)args->c);
|
free((int *)args->c);
|
||||||
free(args);
|
free(args);
|
||||||
@ -2559,16 +2620,17 @@ void unary()
|
|||||||
tok = ')';
|
tok = ')';
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
t = 0;
|
|
||||||
while (tok != ')') {
|
while (tok != ')') {
|
||||||
t += 4;
|
|
||||||
expr_eq();
|
expr_eq();
|
||||||
gfunc_param();
|
gfunc_param(&gf);
|
||||||
if (tok == ',')
|
if (tok == ',')
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
skip(')');
|
skip(')');
|
||||||
|
vpop(&ft, &fc);
|
||||||
|
gfunc_call(&gf, ft, fc);
|
||||||
|
#if 0
|
||||||
if ((ft & VT_VALMASK) == VT_CONST) {
|
if ((ft & VT_VALMASK) == VT_CONST) {
|
||||||
/* forward reference */
|
/* forward reference */
|
||||||
if (ft & VT_FORWARD) {
|
if (ft & VT_FORWARD) {
|
||||||
@ -2581,6 +2643,7 @@ void unary()
|
|||||||
}
|
}
|
||||||
if (t)
|
if (t)
|
||||||
oad(0xc481, t);
|
oad(0xc481, t);
|
||||||
|
#endif
|
||||||
/* get return type */
|
/* get return type */
|
||||||
s = sym_find((unsigned)ft >> VT_STRUCT_SHIFT);
|
s = sym_find((unsigned)ft >> VT_STRUCT_SHIFT);
|
||||||
vt = s->t | 0; /* return register is eax */
|
vt = s->t | 0; /* return register is eax */
|
||||||
@ -3041,23 +3104,19 @@ void init_putv(int t, int c, int v, int is_expr)
|
|||||||
/* put zeros for variable based init */
|
/* put zeros for variable based init */
|
||||||
void init_putz(int t, int c, int size)
|
void init_putz(int t, int c, int size)
|
||||||
{
|
{
|
||||||
int memset_addr, r;
|
GFuncContext gf;
|
||||||
|
|
||||||
if ((t & VT_VALMASK) == VT_CONST) {
|
if ((t & VT_VALMASK) == VT_CONST) {
|
||||||
/* nothing to do because global are already set to zero */
|
/* nothing to do because global are already set to zero */
|
||||||
} else {
|
} else {
|
||||||
|
gfunc_start(&gf);
|
||||||
vset(VT_CONST, size);
|
vset(VT_CONST, size);
|
||||||
r = gv();
|
gfunc_param(&gf);
|
||||||
o(0x50 + r);
|
|
||||||
vset(VT_CONST, 0);
|
vset(VT_CONST, 0);
|
||||||
r = gv();
|
gfunc_param(&gf);
|
||||||
o(0x50 + r);
|
|
||||||
vset(VT_LOCAL, c);
|
vset(VT_LOCAL, c);
|
||||||
r = gv();
|
gfunc_param(&gf);
|
||||||
o(0x50 + r);
|
gfunc_call(&gf, VT_CONST, (int)&memset);
|
||||||
memset_addr = (int)&memset;
|
|
||||||
oad(0xe8, memset_addr - ind - 5);
|
|
||||||
oad(0xc481, 3 * 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user