forked from Mirrors/tinycc
simpler function call API
parent
0d6f8021ee
commit
214ccccea7
128
i386-gen.c
128
i386-gen.c
|
@ -73,12 +73,6 @@ int reg_classes[NB_REGS] = {
|
||||||
/* relocation type for 32 bit data relocation */
|
/* relocation type for 32 bit data relocation */
|
||||||
#define R_DATA_32 R_386_32
|
#define R_DATA_32 R_386_32
|
||||||
|
|
||||||
/* function call context */
|
|
||||||
typedef struct GFuncContext {
|
|
||||||
int args_size;
|
|
||||||
int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
|
|
||||||
} GFuncContext;
|
|
||||||
|
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
|
|
||||||
static unsigned long func_sub_sp_offset;
|
static unsigned long func_sub_sp_offset;
|
||||||
|
@ -282,65 +276,6 @@ void store(int r, SValue *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start function call and return function call context */
|
|
||||||
void gfunc_start(GFuncContext *c, int func_call)
|
|
||||||
{
|
|
||||||
c->args_size = 0;
|
|
||||||
c->func_call = func_call;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* push function parameter which is in (vtop->t, vtop->c). Stack entry
|
|
||||||
is then popped. */
|
|
||||||
void gfunc_param(GFuncContext *c)
|
|
||||||
{
|
|
||||||
int size, align, r;
|
|
||||||
|
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
|
||||||
size = type_size(&vtop->type, &align);
|
|
||||||
/* align to stack align size */
|
|
||||||
size = (size + 3) & ~3;
|
|
||||||
/* allocate the necessary size on stack */
|
|
||||||
oad(0xec81, size); /* sub $xxx, %esp */
|
|
||||||
/* generate structure store */
|
|
||||||
r = get_reg(RC_INT);
|
|
||||||
o(0x89); /* mov %esp, r */
|
|
||||||
o(0xe0 + r);
|
|
||||||
vset(&vtop->type, r | VT_LVAL, 0);
|
|
||||||
vswap();
|
|
||||||
vstore();
|
|
||||||
c->args_size += size;
|
|
||||||
} else if (is_float(vtop->type.t)) {
|
|
||||||
gv(RC_FLOAT); /* only one float register */
|
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
|
|
||||||
size = 4;
|
|
||||||
else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
|
|
||||||
size = 8;
|
|
||||||
else
|
|
||||||
size = 12;
|
|
||||||
oad(0xec81, size); /* sub $xxx, %esp */
|
|
||||||
if (size == 12)
|
|
||||||
o(0x7cdb);
|
|
||||||
else
|
|
||||||
o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
|
|
||||||
g(0x24);
|
|
||||||
g(0x00);
|
|
||||||
c->args_size += size;
|
|
||||||
} else {
|
|
||||||
/* simple type (currently always same size) */
|
|
||||||
/* XXX: implicit cast ? */
|
|
||||||
r = gv(RC_INT);
|
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
|
||||||
size = 8;
|
|
||||||
o(0x50 + vtop->r2); /* push r */
|
|
||||||
} else {
|
|
||||||
size = 4;
|
|
||||||
}
|
|
||||||
o(0x50 + r); /* push r */
|
|
||||||
c->args_size += size;
|
|
||||||
}
|
|
||||||
vtop--;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gadd_sp(int val)
|
static void gadd_sp(int val)
|
||||||
{
|
{
|
||||||
if (val == (char)val) {
|
if (val == (char)val) {
|
||||||
|
@ -375,13 +310,66 @@ static void gcall_or_jmp(int is_jmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate function call with address in (vtop->t, vtop->c) and free function
|
/* Generate function call. The function address is pushed first, then
|
||||||
context. Stack entry is popped */
|
all the parameters in call order. This functions pops all the
|
||||||
void gfunc_call(GFuncContext *c)
|
parameters and the function address. */
|
||||||
|
void gfunc_call(int nb_args)
|
||||||
{
|
{
|
||||||
|
int size, align, r, args_size, i;
|
||||||
|
Sym *func_sym;
|
||||||
|
|
||||||
|
args_size = 0;
|
||||||
|
for(i = 0;i < nb_args; i++) {
|
||||||
|
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||||
|
size = type_size(&vtop->type, &align);
|
||||||
|
/* align to stack align size */
|
||||||
|
size = (size + 3) & ~3;
|
||||||
|
/* allocate the necessary size on stack */
|
||||||
|
oad(0xec81, size); /* sub $xxx, %esp */
|
||||||
|
/* generate structure store */
|
||||||
|
r = get_reg(RC_INT);
|
||||||
|
o(0x89); /* mov %esp, r */
|
||||||
|
o(0xe0 + r);
|
||||||
|
vset(&vtop->type, r | VT_LVAL, 0);
|
||||||
|
vswap();
|
||||||
|
vstore();
|
||||||
|
args_size += size;
|
||||||
|
} else if (is_float(vtop->type.t)) {
|
||||||
|
gv(RC_FLOAT); /* only one float register */
|
||||||
|
if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
|
||||||
|
size = 4;
|
||||||
|
else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
|
||||||
|
size = 8;
|
||||||
|
else
|
||||||
|
size = 12;
|
||||||
|
oad(0xec81, size); /* sub $xxx, %esp */
|
||||||
|
if (size == 12)
|
||||||
|
o(0x7cdb);
|
||||||
|
else
|
||||||
|
o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
|
||||||
|
g(0x24);
|
||||||
|
g(0x00);
|
||||||
|
args_size += size;
|
||||||
|
} else {
|
||||||
|
/* simple type (currently always same size) */
|
||||||
|
/* XXX: implicit cast ? */
|
||||||
|
r = gv(RC_INT);
|
||||||
|
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||||
|
size = 8;
|
||||||
|
o(0x50 + vtop->r2); /* push r */
|
||||||
|
} else {
|
||||||
|
size = 4;
|
||||||
|
}
|
||||||
|
o(0x50 + r); /* push r */
|
||||||
|
args_size += size;
|
||||||
|
}
|
||||||
|
vtop--;
|
||||||
|
}
|
||||||
|
save_regs(0); /* save used temporary registers */
|
||||||
|
func_sym = vtop->type.ref;
|
||||||
gcall_or_jmp(0);
|
gcall_or_jmp(0);
|
||||||
if (c->args_size && c->func_call == FUNC_CDECL)
|
if (args_size && func_sym->r == FUNC_CDECL)
|
||||||
gadd_sp(c->args_size);
|
gadd_sp(args_size);
|
||||||
vtop--;
|
vtop--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
170
tcc.c
170
tcc.c
|
@ -4589,7 +4589,9 @@ void lbuild(int t)
|
||||||
vpop();
|
vpop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rotate n first stack elements to the bottom */
|
/* rotate n first stack elements to the bottom
|
||||||
|
I1 ... In -> I2 ... In I1 [top is right]
|
||||||
|
*/
|
||||||
void vrotb(int n)
|
void vrotb(int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -4601,6 +4603,20 @@ void vrotb(int n)
|
||||||
vtop[0] = tmp;
|
vtop[0] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rotate n first stack elements to the top
|
||||||
|
I1 ... In -> In I1 ... I(n-1) [top is right]
|
||||||
|
*/
|
||||||
|
void vrott(int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
SValue tmp;
|
||||||
|
|
||||||
|
tmp = vtop[0];
|
||||||
|
for(i = 0;i < n - 1; i++)
|
||||||
|
vtop[-i] = vtop[-i - 1];
|
||||||
|
vtop[-n + 1] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
/* pop stack value */
|
/* pop stack value */
|
||||||
void vpop(void)
|
void vpop(void)
|
||||||
{
|
{
|
||||||
|
@ -4665,7 +4681,6 @@ void gen_opl(int op)
|
||||||
{
|
{
|
||||||
int t, a, b, op1, c, i;
|
int t, a, b, op1, c, i;
|
||||||
int func;
|
int func;
|
||||||
GFuncContext gf;
|
|
||||||
SValue tmp;
|
SValue tmp;
|
||||||
|
|
||||||
switch(op) {
|
switch(op) {
|
||||||
|
@ -4683,11 +4698,9 @@ void gen_opl(int op)
|
||||||
func = TOK___umoddi3;
|
func = TOK___umoddi3;
|
||||||
gen_func:
|
gen_func:
|
||||||
/* call generic long long function */
|
/* call generic long long function */
|
||||||
gfunc_start(&gf, FUNC_CDECL);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
vpush_global_sym(&func_old_type, func);
|
vpush_global_sym(&func_old_type, func);
|
||||||
gfunc_call(&gf);
|
vrott(3);
|
||||||
|
gfunc_call(2);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vtop->r = REG_IRET;
|
vtop->r = REG_IRET;
|
||||||
vtop->r2 = REG_LRET;
|
vtop->r2 = REG_LRET;
|
||||||
|
@ -5227,20 +5240,17 @@ void gen_op(int op)
|
||||||
/* generic itof for unsigned long long case */
|
/* generic itof for unsigned long long case */
|
||||||
void gen_cvt_itof1(int t)
|
void gen_cvt_itof1(int t)
|
||||||
{
|
{
|
||||||
GFuncContext gf;
|
|
||||||
|
|
||||||
if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
|
if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
|
||||||
(VT_LLONG | VT_UNSIGNED)) {
|
(VT_LLONG | VT_UNSIGNED)) {
|
||||||
|
|
||||||
gfunc_start(&gf, FUNC_CDECL);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
if (t == VT_FLOAT)
|
if (t == VT_FLOAT)
|
||||||
vpush_global_sym(&func_old_type, TOK___ulltof);
|
vpush_global_sym(&func_old_type, TOK___ulltof);
|
||||||
else if (t == VT_DOUBLE)
|
else if (t == VT_DOUBLE)
|
||||||
vpush_global_sym(&func_old_type, TOK___ulltod);
|
vpush_global_sym(&func_old_type, TOK___ulltod);
|
||||||
else
|
else
|
||||||
vpush_global_sym(&func_old_type, TOK___ulltold);
|
vpush_global_sym(&func_old_type, TOK___ulltold);
|
||||||
gfunc_call(&gf);
|
vrott(2);
|
||||||
|
gfunc_call(1);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vtop->r = REG_FRET;
|
vtop->r = REG_FRET;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5251,21 +5261,19 @@ void gen_cvt_itof1(int t)
|
||||||
/* generic ftoi for unsigned long long case */
|
/* generic ftoi for unsigned long long case */
|
||||||
void gen_cvt_ftoi1(int t)
|
void gen_cvt_ftoi1(int t)
|
||||||
{
|
{
|
||||||
GFuncContext gf;
|
|
||||||
int st;
|
int st;
|
||||||
|
|
||||||
if (t == (VT_LLONG | VT_UNSIGNED)) {
|
if (t == (VT_LLONG | VT_UNSIGNED)) {
|
||||||
/* not handled natively */
|
/* not handled natively */
|
||||||
gfunc_start(&gf, FUNC_CDECL);
|
|
||||||
st = vtop->type.t & VT_BTYPE;
|
st = vtop->type.t & VT_BTYPE;
|
||||||
gfunc_param(&gf);
|
|
||||||
if (st == VT_FLOAT)
|
if (st == VT_FLOAT)
|
||||||
vpush_global_sym(&func_old_type, TOK___fixunssfdi);
|
vpush_global_sym(&func_old_type, TOK___fixunssfdi);
|
||||||
else if (st == VT_DOUBLE)
|
else if (st == VT_DOUBLE)
|
||||||
vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
|
vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
|
||||||
else
|
else
|
||||||
vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
|
vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
|
||||||
gfunc_call(&gf);
|
vrott(2);
|
||||||
|
gfunc_call(1);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vtop->r = REG_IRET;
|
vtop->r = REG_IRET;
|
||||||
vtop->r2 = REG_LRET;
|
vtop->r2 = REG_LRET;
|
||||||
|
@ -5700,7 +5708,6 @@ static void gen_assign_cast(CType *dt)
|
||||||
void vstore(void)
|
void vstore(void)
|
||||||
{
|
{
|
||||||
int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
|
int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
|
||||||
GFuncContext gf;
|
|
||||||
|
|
||||||
ft = vtop[-1].type.t;
|
ft = vtop[-1].type.t;
|
||||||
sbt = vtop->type.t & VT_BTYPE;
|
sbt = vtop->type.t & VT_BTYPE;
|
||||||
|
@ -5720,25 +5727,24 @@ void vstore(void)
|
||||||
/* structure assignment : generate memcpy */
|
/* structure assignment : generate memcpy */
|
||||||
/* XXX: optimize if small size */
|
/* XXX: optimize if small size */
|
||||||
if (!nocode_wanted) {
|
if (!nocode_wanted) {
|
||||||
vdup();
|
|
||||||
gfunc_start(&gf, FUNC_CDECL);
|
|
||||||
/* type size */
|
|
||||||
size = type_size(&vtop->type, &align);
|
size = type_size(&vtop->type, &align);
|
||||||
vpushi(size);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
/* source */
|
|
||||||
vtop->type.t = VT_INT;
|
|
||||||
gaddrof();
|
|
||||||
gfunc_param(&gf);
|
|
||||||
/* destination */
|
|
||||||
vswap();
|
|
||||||
vtop->type.t = VT_INT;
|
|
||||||
gaddrof();
|
|
||||||
gfunc_param(&gf);
|
|
||||||
|
|
||||||
save_regs(0);
|
|
||||||
vpush_global_sym(&func_old_type, TOK_memcpy);
|
vpush_global_sym(&func_old_type, TOK_memcpy);
|
||||||
gfunc_call(&gf);
|
|
||||||
|
/* destination */
|
||||||
|
vpushv(vtop - 2);
|
||||||
|
vtop->type.t = VT_INT;
|
||||||
|
gaddrof();
|
||||||
|
/* source */
|
||||||
|
vpushv(vtop - 2);
|
||||||
|
vtop->type.t = VT_INT;
|
||||||
|
gaddrof();
|
||||||
|
/* type size */
|
||||||
|
vpushi(size);
|
||||||
|
gfunc_call(3);
|
||||||
|
|
||||||
|
vswap();
|
||||||
|
vpop();
|
||||||
} else {
|
} else {
|
||||||
vswap();
|
vswap();
|
||||||
vpop();
|
vpop();
|
||||||
|
@ -6436,7 +6442,7 @@ static void indir(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pass a parameter to a function and do type checking and casting */
|
/* pass a parameter to a function and do type checking and casting */
|
||||||
void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
|
static void gfunc_param_typed(Sym *func, Sym *arg)
|
||||||
{
|
{
|
||||||
int func_type;
|
int func_type;
|
||||||
CType type;
|
CType type;
|
||||||
|
@ -6454,11 +6460,6 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
|
||||||
} else {
|
} else {
|
||||||
gen_assign_cast(&arg->type);
|
gen_assign_cast(&arg->type);
|
||||||
}
|
}
|
||||||
if (!nocode_wanted) {
|
|
||||||
gfunc_param(gf);
|
|
||||||
} else {
|
|
||||||
vpop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse an expression of the form '(type)' or '(expr)' and return its
|
/* parse an expression of the form '(type)' or '(expr)' and return its
|
||||||
|
@ -6489,7 +6490,6 @@ static void unary(void)
|
||||||
int n, t, align, size, r;
|
int n, t, align, size, r;
|
||||||
CType type;
|
CType type;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
GFuncContext gf;
|
|
||||||
AttributeDef ad;
|
AttributeDef ad;
|
||||||
|
|
||||||
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
||||||
|
@ -6764,6 +6764,7 @@ static void unary(void)
|
||||||
} else if (tok == '(') {
|
} else if (tok == '(') {
|
||||||
SValue ret;
|
SValue ret;
|
||||||
Sym *sa;
|
Sym *sa;
|
||||||
|
int nb_args;
|
||||||
|
|
||||||
/* function call */
|
/* function call */
|
||||||
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
||||||
|
@ -6781,63 +6782,9 @@ static void unary(void)
|
||||||
}
|
}
|
||||||
/* get return type */
|
/* get return type */
|
||||||
s = vtop->type.ref;
|
s = vtop->type.ref;
|
||||||
if (!nocode_wanted) {
|
|
||||||
save_regs(0); /* save used temporary registers */
|
|
||||||
gfunc_start(&gf, s->r);
|
|
||||||
}
|
|
||||||
next();
|
next();
|
||||||
sa = s->next; /* first parameter */
|
sa = s->next; /* first parameter */
|
||||||
#ifdef INVERT_FUNC_PARAMS
|
nb_args = 0;
|
||||||
{
|
|
||||||
int parlevel;
|
|
||||||
Sym *args, *s1;
|
|
||||||
ParseState saved_parse_state;
|
|
||||||
TokenString str;
|
|
||||||
|
|
||||||
/* read each argument and store it on a stack */
|
|
||||||
args = NULL;
|
|
||||||
if (tok != ')') {
|
|
||||||
for(;;) {
|
|
||||||
tok_str_new(&str);
|
|
||||||
parlevel = 0;
|
|
||||||
while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
|
|
||||||
tok != TOK_EOF) {
|
|
||||||
if (tok == '(')
|
|
||||||
parlevel++;
|
|
||||||
else if (tok == ')')
|
|
||||||
parlevel--;
|
|
||||||
tok_str_add_tok(&str);
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
tok_str_add(&str, -1); /* end of file added */
|
|
||||||
tok_str_add(&str, 0);
|
|
||||||
s1 = sym_push2(&args, 0, 0, (int)str.str);
|
|
||||||
s1->next = sa; /* add reference to argument */
|
|
||||||
if (sa)
|
|
||||||
sa = sa->next;
|
|
||||||
if (tok == ')')
|
|
||||||
break;
|
|
||||||
skip(',');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now generate code in reverse order by reading the stack */
|
|
||||||
save_parse_state(&saved_parse_state);
|
|
||||||
while (args) {
|
|
||||||
macro_ptr = (int *)args->c;
|
|
||||||
next();
|
|
||||||
expr_eq();
|
|
||||||
if (tok != -1)
|
|
||||||
expect("',' or ')'");
|
|
||||||
gfunc_param_typed(&gf, s, args->next);
|
|
||||||
s1 = args->prev;
|
|
||||||
tok_str_free((int *)args->c);
|
|
||||||
tcc_free(args);
|
|
||||||
args = s1;
|
|
||||||
}
|
|
||||||
restore_parse_state(&saved_parse_state);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* compute first implicit argument if a structure is returned */
|
/* compute first implicit argument if a structure is returned */
|
||||||
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
|
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||||
/* get some space for the returned structure */
|
/* get some space for the returned structure */
|
||||||
|
@ -6849,10 +6796,7 @@ static void unary(void)
|
||||||
problems */
|
problems */
|
||||||
vseti(VT_LOCAL, loc);
|
vseti(VT_LOCAL, loc);
|
||||||
ret.c = vtop->c;
|
ret.c = vtop->c;
|
||||||
if (!nocode_wanted)
|
nb_args++;
|
||||||
gfunc_param(&gf);
|
|
||||||
else
|
|
||||||
vtop--;
|
|
||||||
} else {
|
} else {
|
||||||
ret.type = s->type;
|
ret.type = s->type;
|
||||||
ret.r2 = VT_CONST;
|
ret.r2 = VT_CONST;
|
||||||
|
@ -6866,11 +6810,11 @@ static void unary(void)
|
||||||
}
|
}
|
||||||
ret.c.i = 0;
|
ret.c.i = 0;
|
||||||
}
|
}
|
||||||
#ifndef INVERT_FUNC_PARAMS
|
|
||||||
if (tok != ')') {
|
if (tok != ')') {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
expr_eq();
|
expr_eq();
|
||||||
gfunc_param_typed(&gf, s, sa);
|
gfunc_param_typed(s, sa);
|
||||||
|
nb_args++;
|
||||||
if (sa)
|
if (sa)
|
||||||
sa = sa->next;
|
sa = sa->next;
|
||||||
if (tok == ')')
|
if (tok == ')')
|
||||||
|
@ -6878,14 +6822,14 @@ static void unary(void)
|
||||||
skip(',');
|
skip(',');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (sa)
|
if (sa)
|
||||||
error("too few arguments to function");
|
error("too few arguments to function");
|
||||||
skip(')');
|
skip(')');
|
||||||
if (!nocode_wanted)
|
if (!nocode_wanted) {
|
||||||
gfunc_call(&gf);
|
gfunc_call(nb_args);
|
||||||
else
|
} else {
|
||||||
vtop--;
|
vtop -= (nb_args + 1);
|
||||||
|
}
|
||||||
/* return value */
|
/* return value */
|
||||||
vsetc(&ret.type, ret.r, &ret.c);
|
vsetc(&ret.type, ret.r, &ret.c);
|
||||||
vtop->r2 = ret.r2;
|
vtop->r2 = ret.r2;
|
||||||
|
@ -7793,20 +7737,14 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
|
||||||
/* put zeros for variable based init */
|
/* put zeros for variable based init */
|
||||||
static void init_putz(CType *t, Section *sec, unsigned long c, int size)
|
static void init_putz(CType *t, Section *sec, unsigned long c, int size)
|
||||||
{
|
{
|
||||||
GFuncContext gf;
|
|
||||||
|
|
||||||
if (sec) {
|
if (sec) {
|
||||||
/* nothing to do because globals are already set to zero */
|
/* nothing to do because globals are already set to zero */
|
||||||
} else {
|
} else {
|
||||||
gfunc_start(&gf, FUNC_CDECL);
|
|
||||||
vpushi(size);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
vpushi(0);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
vseti(VT_LOCAL, c);
|
|
||||||
gfunc_param(&gf);
|
|
||||||
vpush_global_sym(&func_old_type, TOK_memset);
|
vpush_global_sym(&func_old_type, TOK_memset);
|
||||||
gfunc_call(&gf);
|
vseti(VT_LOCAL, c);
|
||||||
|
vpushi(0);
|
||||||
|
vpushi(size);
|
||||||
|
gfunc_call(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue