mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
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:
parent
77d7ea04ac
commit
f843cadb6b
11
arm-gen.c
11
arm-gen.c
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
33
i386-gen.c
33
i386-gen.c
@ -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) {
|
||||||
|
7
tccasm.c
7
tccasm.c
@ -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
144
tccgen.c
@ -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;
|
||||||
|
34
x86_64-gen.c
34
x86_64-gen.c
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user