tccgen: nocode_wanted alternatively

tccgen.c: remove any 'nocode_wanted' checks, except in
- greloca(), disables output elf symbols and relocs
- get_reg(), will return just the first suitable reg)
- save_regs(), will do nothing

Some minor adjustments were made where nocode_wanted is set.

xxx-gen.c: disable code output directly where it happens
in functions:
- g(), output disabled
- gjmp(), will do nothing
- gtst(), dto.
This commit is contained in:
grischka 2016-12-18 17:23:33 +01:00
parent 77d7ea04ac
commit f843cadb6b
7 changed files with 111 additions and 131 deletions

View File

@ -214,7 +214,8 @@ void o(uint32_t i)
{ {
/* this is a good place to start adding big-endian support*/ /* this is a good place to start adding big-endian support*/
int ind1; int ind1;
if (nocode_wanted)
return;
ind1 = ind + 4; ind1 = ind + 4;
if (!cur_text_section) if (!cur_text_section)
tcc_error("compiler error! This happens f.ex. if the compiler\n" tcc_error("compiler error! This happens f.ex. if the compiler\n"
@ -1411,6 +1412,8 @@ void gfunc_epilog(void)
int gjmp(int t) int gjmp(int t)
{ {
int r; int r;
if (nocode_wanted)
return t;
r=ind; r=ind;
o(0xE0000000|encbranch(r,t,1)); o(0xE0000000|encbranch(r,t,1));
return r; return r;
@ -1427,9 +1430,13 @@ int gtst(int inv, int t)
{ {
int v, r; int v, r;
uint32_t op; uint32_t op;
v = vtop->r & VT_VALMASK; v = vtop->r & VT_VALMASK;
r=ind; r=ind;
if (v == VT_CMP) {
if (nocode_wanted) {
;
} else if (v == VT_CMP) {
op=mapcc(inv?negcc(vtop->c.i):vtop->c.i); op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
op|=encbranch(r,t,1); op|=encbranch(r,t,1);
o(op); o(op);

View File

@ -95,6 +95,8 @@ static uint32_t fltr(int r)
ST_FUNC void o(unsigned int c) ST_FUNC void o(unsigned int c)
{ {
int ind1 = ind + 4; int ind1 = ind + 4;
if (nocode_wanted)
return;
if (ind1 > cur_text_section->data_allocated) if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
write32le(cur_text_section->data + ind, c); write32le(cur_text_section->data + ind, c);
@ -1278,6 +1280,8 @@ ST_FUNC void gfunc_epilog(void)
ST_FUNC int gjmp(int t) ST_FUNC int gjmp(int t)
{ {
int r = ind; int r = ind;
if (nocode_wanted)
return t;
o(t); o(t);
return r; return r;
} }

View File

@ -182,7 +182,8 @@ FILE *f = NULL;
void C67_g(int c) void C67_g(int c)
{ {
int ind1; int ind1;
if (nocode_wanted)
return;
#ifdef ASSEMBLY_LISTING_C67 #ifdef ASSEMBLY_LISTING_C67
fprintf(f, " %08X", c); fprintf(f, " %08X", c);
#endif #endif
@ -2038,6 +2039,8 @@ void gfunc_epilog(void)
int gjmp(int t) int gjmp(int t)
{ {
int ind1 = ind; int ind1 = ind;
if (nocode_wanted)
return t;
C67_MVKL(C67_A0, t); //r=reg to load, constant C67_MVKL(C67_A0, t); //r=reg to load, constant
C67_MVKH(C67_A0, t); //r=reg to load, constant C67_MVKH(C67_A0, t); //r=reg to load, constant
@ -2070,7 +2073,9 @@ int gtst(int inv, int t)
int v, *p; int v, *p;
v = vtop->r & VT_VALMASK; v = vtop->r & VT_VALMASK;
if (v == VT_CMP) { if (nocode_wanted) {
;
} else if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
// C67 uses B2 sort of as flags register // C67 uses B2 sort of as flags register
ind1 = ind; ind1 = ind;

View File

@ -70,8 +70,8 @@ enum {
/* maximum alignment (for aligned attribute support) */ /* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8 #define MAX_ALIGN 8
/* generate jmp to a label */
#define psym oad #define gjmp2(instr,lbl) oad(instr,lbl)
/******************************************************/ /******************************************************/
#else /* ! TARGET_DEFS_ONLY */ #else /* ! TARGET_DEFS_ONLY */
@ -100,6 +100,8 @@ static unsigned long func_bound_ind;
ST_FUNC void g(int c) ST_FUNC void g(int c)
{ {
int ind1; int ind1;
if (nocode_wanted)
return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
@ -145,23 +147,16 @@ ST_FUNC void gsym(int t)
gsym_addr(t, ind); gsym_addr(t, ind);
} }
/* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */
#define psym oad
/* instruction + 4 bytes data. Return the address of the data */ /* instruction + 4 bytes data. Return the address of the data */
ST_FUNC int oad(int c, int s) ST_FUNC int oad(int c, int s)
{ {
int ind1; int t;
if (nocode_wanted)
return s;
o(c); o(c);
ind1 = ind + 4; t = ind;
if (ind1 > cur_text_section->data_allocated) gen_le32(s);
section_realloc(cur_text_section, ind1); return t;
write32le(cur_text_section->data + ind, s);
s = ind;
ind = ind1;
return s;
} }
/* output constant with relocation if 'r & VT_SYM' is true */ /* output constant with relocation if 'r & VT_SYM' is true */
@ -676,7 +671,7 @@ ST_FUNC void gfunc_epilog(void)
/* generate a jump to a label */ /* generate a jump to a label */
ST_FUNC int gjmp(int t) ST_FUNC int gjmp(int t)
{ {
return psym(0xe9, t); return gjmp2(0xe9, t);
} }
/* generate a jump to a fixed address */ /* generate a jump to a fixed address */
@ -722,10 +717,12 @@ ST_FUNC void gtst_addr(int inv, int a)
ST_FUNC int gtst(int inv, int t) ST_FUNC int gtst(int inv, int t)
{ {
int v = vtop->r & VT_VALMASK; int v = vtop->r & VT_VALMASK;
if (v == VT_CMP) { if (nocode_wanted) {
;
} else if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
g(0x0f); g(0x0f);
t = psym((vtop->c.i - 16) ^ inv, t); t = gjmp2((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) { } else if (v == VT_JMP || v == VT_JMPI) {
/* && or || optimization */ /* && or || optimization */
if ((v & 1) == inv) { if ((v & 1) == inv) {

View File

@ -915,8 +915,12 @@ static void asm_parse_directive(TCCState *s1)
/* assemble a file */ /* assemble a file */
static int tcc_assemble_internal(TCCState *s1, int do_preprocess) static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
{ {
int saved_nocode_wanted;
int opcode; int opcode;
saved_nocode_wanted = nocode_wanted;
nocode_wanted = 0;
/* XXX: undefine C labels */ /* XXX: undefine C labels */
ch = file->buf_ptr[0]; ch = file->buf_ptr[0];
@ -960,7 +964,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
/* handle "extern void vide(void); __asm__("vide: ret");" as /* handle "extern void vide(void); __asm__("vide: ret");" as
"__asm__("globl vide\nvide: ret");" */ "__asm__("globl vide\nvide: ret");" */
Sym *sym = sym_find(opcode); Sym *sym = sym_find(opcode);
if (sym && (sym->type.t & VT_EXTERN) && nocode_wanted) { if (sym && (sym->type.t & VT_EXTERN) && saved_nocode_wanted) {
sym = label_find(opcode); sym = label_find(opcode);
if (!sym) { if (!sym) {
sym = label_push(&s1->asm_labels, opcode, 0); sym = label_push(&s1->asm_labels, opcode, 0);
@ -989,6 +993,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
asm_free_labels(s1); asm_free_labels(s1);
nocode_wanted = saved_nocode_wanted;
return 0; return 0;
} }

144
tccgen.c
View File

@ -69,6 +69,7 @@ ST_DATA struct switch_t {
} *cur_switch; /* current switch */ } *cur_switch; /* current switch */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static void gen_cast(CType *type); static void gen_cast(CType *type);
static inline CType *pointed_type(CType *type); static inline CType *pointed_type(CType *type);
static int is_compatible_types(CType *type1, CType *type2); static int is_compatible_types(CType *type1, CType *type2);
@ -322,11 +323,16 @@ ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
addr_t addend) addr_t addend)
{ {
int c = 0; int c = 0;
if (nocode_wanted && s == cur_text_section)
return;
if (sym) { if (sym) {
if (0 == sym->c) if (0 == sym->c)
put_extern_sym(sym, NULL, 0, 0); put_extern_sym(sym, NULL, 0, 0);
c = sym->c; c = sym->c;
} }
/* now we can add ELF relocation info */ /* now we can add ELF relocation info */
put_elf_reloca(symtab_section, s, offset, type, c, addend); put_elf_reloca(symtab_section, s, offset, type, c, addend);
} }
@ -774,6 +780,8 @@ ST_FUNC void save_reg_upstack(int r, int n)
if ((r &= VT_VALMASK) >= VT_CONST) if ((r &= VT_VALMASK) >= VT_CONST)
return; return;
if (nocode_wanted)
return;
/* modify all stack values */ /* modify all stack values */
saved = 0; saved = 0;
@ -865,6 +873,8 @@ ST_FUNC int get_reg(int rc)
/* find a free register */ /* find a free register */
for(r=0;r<NB_REGS;r++) { for(r=0;r<NB_REGS;r++) {
if (reg_classes[r] & rc) { if (reg_classes[r] & rc) {
if (nocode_wanted)
return r;
for(p=vstack;p<=vtop;p++) { for(p=vstack;p<=vtop;p++) {
if ((p->r & VT_VALMASK) == r || if ((p->r & VT_VALMASK) == r ||
(p->r2 & VT_VALMASK) == r) (p->r2 & VT_VALMASK) == r)
@ -913,7 +923,7 @@ static void move_reg(int r, int s, int t)
/* get address of vtop (vtop MUST BE an lvalue) */ /* get address of vtop (vtop MUST BE an lvalue) */
ST_FUNC void gaddrof(void) ST_FUNC void gaddrof(void)
{ {
if (vtop->r & VT_REF && !nocode_wanted) if (vtop->r & VT_REF)
gv(RC_INT); gv(RC_INT);
vtop->r &= ~VT_LVAL; vtop->r &= ~VT_LVAL;
/* tricky: if saved lvalue, then we can go back to lvalue */ /* tricky: if saved lvalue, then we can go back to lvalue */
@ -1317,7 +1327,7 @@ ST_FUNC void vpop(void)
v = vtop->r & VT_VALMASK; v = vtop->r & VT_VALMASK;
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
/* for x86, we need to pop the FP stack */ /* for x86, we need to pop the FP stack */
if (v == TREG_ST0 && !nocode_wanted) { if (v == TREG_ST0) {
o(0xd8dd); /* fstp %st(0) */ o(0xd8dd); /* fstp %st(0) */
} else } else
#endif #endif
@ -1607,7 +1617,7 @@ static void gen_opl(int op)
b = gvtst(0, 0); b = gvtst(0, 0);
} else { } else {
#if defined(TCC_TARGET_I386) #if defined(TCC_TARGET_I386)
b = psym(0x850f, 0); b = gjmp2(0x850f, 0);
#elif defined(TCC_TARGET_ARM) #elif defined(TCC_TARGET_ARM)
b = ind; b = ind;
o(0x1A000000 | encbranch(ind, 0, 1)); o(0x1A000000 | encbranch(ind, 0, 1));
@ -1789,23 +1799,12 @@ static void gen_opic(int op)
vtop->c.i = l2; vtop->c.i = l2;
} else { } else {
general_case: general_case:
if (!nocode_wanted) {
/* call low level op generator */ /* call low level op generator */
if (t1 == VT_LLONG || t2 == VT_LLONG || if (t1 == VT_LLONG || t2 == VT_LLONG ||
(PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR))) (PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR)))
gen_opl(op); gen_opl(op);
else else
gen_opi(op); gen_opi(op);
} else {
vtop--;
/* Ensure vtop isn't marked VT_CONST in case something
up our callchain is interested in const-ness of the
expression. Also make it a non-LVAL if it was,
so that further code can't accidentally generate
a deref (happen only for buggy uses of e.g.
gv() under nocode_wanted). */
vtop->r &= ~(VT_VALMASK | VT_LVAL);
}
} }
} }
} }
@ -1866,11 +1865,7 @@ static void gen_opif(int op)
vtop--; vtop--;
} else { } else {
general_case: general_case:
if (!nocode_wanted) { gen_opf(op);
gen_opf(op);
} else {
vtop--;
}
} }
} }
@ -2149,7 +2144,7 @@ redo:
} }
} }
// Make sure that we have converted to an rvalue: // Make sure that we have converted to an rvalue:
if (vtop->r & VT_LVAL && !nocode_wanted) if (vtop->r & VT_LVAL)
gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT); gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
} }
@ -2255,7 +2250,7 @@ static void gen_cast(CType *type)
} }
/* bitfields first get cast to ints */ /* bitfields first get cast to ints */
if (vtop->type.t & VT_BITFIELD && !nocode_wanted) { if (vtop->type.t & VT_BITFIELD) {
gv(RC_INT); gv(RC_INT);
} }
@ -2331,7 +2326,7 @@ static void gen_cast(CType *type)
} else if (p && dbt == VT_BOOL) { } else if (p && dbt == VT_BOOL) {
vtop->r = VT_CONST; vtop->r = VT_CONST;
vtop->c.i = 1; vtop->c.i = 1;
} else if (!nocode_wanted) { } else {
/* non constant case: generate code */ /* non constant case: generate code */
if (sf && df) { if (sf && df) {
/* convert from fp to fp */ /* convert from fp to fp */
@ -2883,7 +2878,6 @@ ST_FUNC void vstore(void)
/* if structure, only generate pointer */ /* if structure, only generate pointer */
/* structure assignment : generate memcpy */ /* structure assignment : generate memcpy */
/* XXX: optimize if small size */ /* XXX: optimize if small size */
if (!nocode_wanted) {
size = type_size(&vtop->type, &align); size = type_size(&vtop->type, &align);
/* destination */ /* destination */
@ -2910,10 +2904,7 @@ ST_FUNC void vstore(void)
/* type size */ /* type size */
vpushi(size); vpushi(size);
gfunc_call(3); gfunc_call(3);
} else {
vswap();
vpop();
}
/* leave source on stack */ /* leave source on stack */
} else if (ft & VT_BITFIELD) { } else if (ft & VT_BITFIELD) {
/* bitfield store handling */ /* bitfield store handling */
@ -2961,7 +2952,6 @@ ST_FUNC void vstore(void)
vpop(); vpop();
} else { } else {
if (!nocode_wanted) {
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
/* bound check case */ /* bound check case */
if (vtop[-1].r & VT_MUSTBOUND) { if (vtop[-1].r & VT_MUSTBOUND) {
@ -3020,7 +3010,7 @@ ST_FUNC void vstore(void)
} else { } else {
store(r, vtop - 1); store(r, vtop - 1);
} }
}
vswap(); vswap();
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
vtop->r |= delayed_cast; vtop->r |= delayed_cast;
@ -3033,10 +3023,7 @@ ST_FUNC void inc(int post, int c)
test_lvalue(); test_lvalue();
vdup(); /* save lvalue */ vdup(); /* save lvalue */
if (post) { if (post) {
if (!nocode_wanted) gv_dup(); /* duplicate value */
gv_dup(); /* duplicate value */
else
vdup(); /* duplicate value */
vrotb(3); vrotb(3);
vrotb(3); vrotb(3);
} }
@ -4189,7 +4176,7 @@ ST_FUNC void indir(void)
return; return;
expect("pointer"); expect("pointer");
} }
if ((vtop->r & VT_LVAL) && !nocode_wanted) if (vtop->r & VT_LVAL)
gv(RC_INT); gv(RC_INT);
vtop->type = *pointed_type(&vtop->type); vtop->type = *pointed_type(&vtop->type);
/* Arrays and functions are never lvalues */ /* Arrays and functions are never lvalues */
@ -4382,8 +4369,7 @@ ST_FUNC void unary(void)
if (const_wanted) if (const_wanted)
tcc_error("expected constant"); tcc_error("expected constant");
/* save all registers */ /* save all registers */
if (!nocode_wanted) save_regs(0);
save_regs(0);
/* statement expression : we do not accept break/continue /* statement expression : we do not accept break/continue
inside as GCC does */ inside as GCC does */
block(NULL, NULL, 1); block(NULL, NULL, 1);
@ -4610,8 +4596,6 @@ ST_FUNC void unary(void)
#ifdef TCC_TARGET_ARM64 #ifdef TCC_TARGET_ARM64
case TOK___va_start: { case TOK___va_start: {
if (nocode_wanted)
tcc_error("statement in global scope");
next(); next();
skip('('); skip('(');
expr_eq(); expr_eq();
@ -4626,8 +4610,6 @@ ST_FUNC void unary(void)
} }
case TOK___va_arg: { case TOK___va_arg: {
CType type; CType type;
if (nocode_wanted)
tcc_error("statement in global scope");
next(); next();
skip('('); skip('(');
expr_eq(); expr_eq();
@ -4906,11 +4888,7 @@ ST_FUNC void unary(void)
if (sa) if (sa)
tcc_error("too few arguments to function"); tcc_error("too few arguments to function");
skip(')'); skip(')');
if (!nocode_wanted) { gfunc_call(nb_args);
gfunc_call(nb_args);
} else {
vtop -= (nb_args + 1);
}
/* return value */ /* return value */
for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) { for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {
@ -5083,9 +5061,9 @@ static void expr_land(void)
expr_or(); expr_or();
vpop(); vpop();
} }
nocode_wanted = saved_nocode_wanted;
if (t) if (t)
gsym(t); gsym(t);
nocode_wanted = saved_nocode_wanted;
gen_cast(&int_type); gen_cast(&int_type);
break; break;
} }
@ -5127,9 +5105,9 @@ static void expr_lor(void)
expr_land(); expr_land();
vpop(); vpop();
} }
nocode_wanted = saved_nocode_wanted;
if (t) if (t)
gsym(t); gsym(t);
nocode_wanted = saved_nocode_wanted;
gen_cast(&int_type); gen_cast(&int_type);
break; break;
} }
@ -5206,16 +5184,6 @@ static void expr_cond(void)
} }
} }
else { else {
/* XXX This doesn't handle nocode_wanted correctly at all.
It unconditionally calls gv/gvtst and friends. That's
the case for many of the expr_ routines. Currently
that should generate only useless code, but depending
on other operand handling this might also generate
pointer derefs for lvalue conversions whose result
is useless, but nevertheless can lead to segfault.
Somewhen we need to overhaul the whole nocode_wanted
handling. */
if (vtop != vstack) { if (vtop != vstack) {
/* needed to avoid having different registers saved in /* needed to avoid having different registers saved in
each branch */ each branch */
@ -5575,19 +5543,22 @@ static void block(int *bsym, int *csym, int is_expr)
gexpr(); gexpr();
skip(')'); skip(')');
cond = condition_3way(); cond = condition_3way();
if (cond == 0) if (cond == 1)
a = 0, vpop();
else
a = gvtst(1, 0);
if (cond == 0)
nocode_wanted |= 2; nocode_wanted |= 2;
a = gvtst(1, 0);
block(bsym, csym, 0); block(bsym, csym, 0);
if (cond != 1) if (cond != 1)
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
c = tok; c = tok;
if (c == TOK_ELSE) { if (c == TOK_ELSE) {
next(); next();
if (cond == 1)
nocode_wanted |= 2;
d = gjmp(0); d = gjmp(0);
gsym(a); gsym(a);
if (cond == 1)
nocode_wanted |= 2;
block(bsym, csym, 0); block(bsym, csym, 0);
gsym(d); /* patch else jmp */ gsym(d); /* patch else jmp */
if (cond != 0) if (cond != 0)
@ -5610,8 +5581,7 @@ static void block(int *bsym, int *csym, int is_expr)
block(&a, &b, 0); block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
--local_scope; --local_scope;
if(!nocode_wanted) gjmp_addr(d);
gjmp_addr(d);
gsym(a); gsym(a);
gsym_addr(b, d); gsym_addr(b, d);
} else if (tok == '{') { } else if (tok == '{') {
@ -5801,8 +5771,7 @@ static void block(int *bsym, int *csym, int is_expr)
saved_nocode_wanted = nocode_wanted; saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0); block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
if(!nocode_wanted) gjmp_addr(c);
gjmp_addr(c);
gsym(a); gsym(a);
gsym_addr(b, c); gsym_addr(b, c);
--local_scope; --local_scope;
@ -5823,11 +5792,8 @@ static void block(int *bsym, int *csym, int is_expr)
skip('('); skip('(');
gsym(b); gsym(b);
gexpr(); gexpr();
if (!nocode_wanted) { c = gvtst(0, 0);
c = gvtst(0, 0); gsym_addr(c, d);
gsym_addr(c, d);
} else
vtop--;
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
skip(')'); skip(')');
gsym(a); gsym(a);
@ -5852,21 +5818,19 @@ static void block(int *bsym, int *csym, int is_expr)
a = gjmp(a); /* add implicit break */ a = gjmp(a); /* add implicit break */
/* case lookup */ /* case lookup */
gsym(b); gsym(b);
if (!nocode_wanted) { qsort(sw.p, sw.n, sizeof(void*), case_cmp);
qsort(sw.p, sw.n, sizeof(void*), case_cmp); for (b = 1; b < sw.n; b++)
for (b = 1; b < sw.n; b++) if (sw.p[b - 1]->v2 >= sw.p[b]->v1)
if (sw.p[b - 1]->v2 >= sw.p[b]->v1) tcc_error("duplicate case value");
tcc_error("duplicate case value"); /* Our switch table sorting is signed, so the compared
/* Our switch table sorting is signed, so the compared value needs to be as well when it's 64bit. */
value needs to be as well when it's 64bit. */ if ((switchval.type.t & VT_BTYPE) == VT_LLONG)
if ((switchval.type.t & VT_BTYPE) == VT_LLONG) switchval.type.t &= ~VT_UNSIGNED;
switchval.type.t &= ~VT_UNSIGNED; vpushv(&switchval);
vpushv(&switchval); gcase(sw.p, sw.n, &a);
gcase(sw.p, sw.n, &a); vpop();
vpop(); if (sw.def_sym)
if (sw.def_sym) gjmp_addr(sw.def_sym);
gjmp_addr(sw.def_sym);
}
dynarray_reset(&sw.p, &sw.n); dynarray_reset(&sw.p, &sw.n);
cur_switch = saved; cur_switch = saved;
/* break label */ /* break label */
@ -5910,10 +5874,7 @@ static void block(int *bsym, int *csym, int is_expr)
gexpr(); gexpr();
if ((vtop->type.t & VT_BTYPE) != VT_PTR) if ((vtop->type.t & VT_BTYPE) != VT_PTR)
expect("pointer"); expect("pointer");
if (!nocode_wanted) ggoto();
ggoto();
else
vtop--;
} else if (tok >= TOK_UIDENT) { } else if (tok >= TOK_UIDENT) {
s = label_find(tok); s = label_find(tok);
/* put forward definition if needed */ /* put forward definition if needed */
@ -5924,9 +5885,7 @@ static void block(int *bsym, int *csym, int is_expr)
s->r = LABEL_FORWARD; s->r = LABEL_FORWARD;
} }
vla_sp_restore_root(); vla_sp_restore_root();
if (nocode_wanted) if (s->r & LABEL_FORWARD)
;
else if (s->r & LABEL_FORWARD)
s->jnext = gjmp(s->jnext); s->jnext = gjmp(s->jnext);
else else
gjmp_addr(s->jnext); gjmp_addr(s->jnext);
@ -6893,6 +6852,7 @@ static void gen_function(Sym *sym)
rsym = 0; rsym = 0;
block(NULL, NULL, 0); block(NULL, NULL, 0);
nocode_wanted = 0;
gsym(rsym); gsym(rsym);
gfunc_epilog(); gfunc_epilog();
cur_text_section->data_offset = ind; cur_text_section->data_offset = ind;

View File

@ -145,6 +145,8 @@ static int func_ret_sub;
ST_FUNC void g(int c) ST_FUNC void g(int c)
{ {
int ind1; int ind1;
if (nocode_wanted)
return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
@ -213,9 +215,6 @@ void gsym(int t)
gsym_addr(t, ind); gsym_addr(t, ind);
} }
/* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */
#define psym oad
static int is64_type(int t) static int is64_type(int t)
{ {
@ -227,18 +226,18 @@ static int is64_type(int t)
/* instruction + 4 bytes data. Return the address of the data */ /* instruction + 4 bytes data. Return the address of the data */
ST_FUNC int oad(int c, int s) ST_FUNC int oad(int c, int s)
{ {
int ind1; int t;
if (nocode_wanted)
return s;
o(c); o(c);
ind1 = ind + 4; t = ind;
if (ind1 > cur_text_section->data_allocated) gen_le32(s);
section_realloc(cur_text_section, ind1); return t;
write32le(cur_text_section->data + ind, s);
s = ind;
ind = ind1;
return s;
} }
/* generate jmp to a label */
#define gjmp2(instr,lbl) oad(instr,lbl)
ST_FUNC void gen_addr32(int r, Sym *sym, long c) ST_FUNC void gen_addr32(int r, Sym *sym, long c)
{ {
if (r & VT_SYM) if (r & VT_SYM)
@ -1703,7 +1702,7 @@ void gfunc_epilog(void)
/* generate a jump to a label */ /* generate a jump to a label */
int gjmp(int t) int gjmp(int t)
{ {
return psym(0xe9, t); return gjmp2(0xe9, t);
} }
/* generate a jump to a fixed address */ /* generate a jump to a fixed address */
@ -1749,7 +1748,10 @@ ST_FUNC void gtst_addr(int inv, int a)
ST_FUNC int gtst(int inv, int t) ST_FUNC int gtst(int inv, int t)
{ {
int v = vtop->r & VT_VALMASK; int v = vtop->r & VT_VALMASK;
if (v == VT_CMP) {
if (nocode_wanted) {
;
} else if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
if (vtop->c.i & 0x100) if (vtop->c.i & 0x100)
{ {
@ -1766,11 +1768,11 @@ ST_FUNC int gtst(int inv, int t)
else else
{ {
g(0x0f); g(0x0f);
t = psym(0x8a, t); /* jp t */ t = gjmp2(0x8a, t); /* jp t */
} }
} }
g(0x0f); g(0x0f);
t = psym((vtop->c.i - 16) ^ inv, t); t = gjmp2((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) { } else if (v == VT_JMP || v == VT_JMPI) {
/* && or || optimization */ /* && or || optimization */
if ((v & 1) == inv) { if ((v & 1) == inv) {