aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2016-12-18 17:23:33 +0100
committergrischka <grischka>2016-12-18 18:53:21 +0100
commitf843cadb6bc07b3b3de6786233df4592d2d5f60d (patch)
treec11a7c8e9138015eb15dbaffff3bc28708292797
parent77d7ea04acb56f839031993c102366e30cad5c25 (diff)
downloadtinycc-f843cadb6bc07b3b3de6786233df4592d2d5f60d.tar.gz
tinycc-f843cadb6bc07b3b3de6786233df4592d2d5f60d.tar.bz2
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.
-rw-r--r--arm-gen.c11
-rw-r--r--arm64-gen.c4
-rw-r--r--c67-gen.c9
-rw-r--r--i386-gen.c33
-rw-r--r--tccasm.c7
-rw-r--r--tccgen.c144
-rw-r--r--x86_64-gen.c34
7 files changed, 111 insertions, 131 deletions
diff --git a/arm-gen.c b/arm-gen.c
index cf3ea95..8fec432 100644
--- a/arm-gen.c
+++ b/arm-gen.c
@@ -214,7 +214,8 @@ void o(uint32_t i)
{
/* this is a good place to start adding big-endian support*/
int ind1;
-
+ if (nocode_wanted)
+ return;
ind1 = ind + 4;
if (!cur_text_section)
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 r;
+ if (nocode_wanted)
+ return t;
r=ind;
o(0xE0000000|encbranch(r,t,1));
return r;
@@ -1427,9 +1430,13 @@ int gtst(int inv, int t)
{
int v, r;
uint32_t op;
+
v = vtop->r & VT_VALMASK;
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|=encbranch(r,t,1);
o(op);
diff --git a/arm64-gen.c b/arm64-gen.c
index 4b2608a..71e977e 100644
--- a/arm64-gen.c
+++ b/arm64-gen.c
@@ -95,6 +95,8 @@ static uint32_t fltr(int r)
ST_FUNC void o(unsigned int c)
{
int ind1 = ind + 4;
+ if (nocode_wanted)
+ return;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
write32le(cur_text_section->data + ind, c);
@@ -1278,6 +1280,8 @@ ST_FUNC void gfunc_epilog(void)
ST_FUNC int gjmp(int t)
{
int r = ind;
+ if (nocode_wanted)
+ return t;
o(t);
return r;
}
diff --git a/c67-gen.c b/c67-gen.c
index 28db68b..7c950eb 100644
--- a/c67-gen.c
+++ b/c67-gen.c
@@ -182,7 +182,8 @@ FILE *f = NULL;
void C67_g(int c)
{
int ind1;
-
+ if (nocode_wanted)
+ return;
#ifdef ASSEMBLY_LISTING_C67
fprintf(f, " %08X", c);
#endif
@@ -2038,6 +2039,8 @@ void gfunc_epilog(void)
int gjmp(int t)
{
int ind1 = ind;
+ if (nocode_wanted)
+ return t;
C67_MVKL(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;
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 */
// C67 uses B2 sort of as flags register
ind1 = ind;
diff --git a/i386-gen.c b/i386-gen.c
index a8c6f4a..3a26f7a 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -70,8 +70,8 @@ enum {
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8
-
-#define psym oad
+/* generate jmp to a label */
+#define gjmp2(instr,lbl) oad(instr,lbl)
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
@@ -100,6 +100,8 @@ static unsigned long func_bound_ind;
ST_FUNC void g(int c)
{
int ind1;
+ if (nocode_wanted)
+ return;
ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
@@ -145,23 +147,16 @@ ST_FUNC void gsym(int t)
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 */
ST_FUNC int oad(int c, int s)
{
- int ind1;
-
+ int t;
+ if (nocode_wanted)
+ return s;
o(c);
- ind1 = ind + 4;
- if (ind1 > cur_text_section->data_allocated)
- section_realloc(cur_text_section, ind1);
- write32le(cur_text_section->data + ind, s);
- s = ind;
- ind = ind1;
- return s;
+ t = ind;
+ gen_le32(s);
+ return t;
}
/* 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 */
ST_FUNC int gjmp(int t)
{
- return psym(0xe9, t);
+ return gjmp2(0xe9, t);
}
/* 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)
{
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 */
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) {
/* && or || optimization */
if ((v & 1) == inv) {
diff --git a/tccasm.c b/tccasm.c
index 7e9c6e6..ee368f4 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -915,8 +915,12 @@ static void asm_parse_directive(TCCState *s1)
/* assemble a file */
static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
{
+ int saved_nocode_wanted;
int opcode;
+ saved_nocode_wanted = nocode_wanted;
+ nocode_wanted = 0;
+
/* XXX: undefine C labels */
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
"__asm__("globl vide\nvide: ret");" */
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);
if (!sym) {
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);
+ nocode_wanted = saved_nocode_wanted;
return 0;
}
diff --git a/tccgen.c b/tccgen.c
index f6c7700..cb013d1 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -69,6 +69,7 @@ ST_DATA struct switch_t {
} *cur_switch; /* current switch */
/* ------------------------------------------------------------------------- */
+
static void gen_cast(CType *type);
static inline CType *pointed_type(CType *type);
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)
{
int c = 0;
+
+ if (nocode_wanted && s == cur_text_section)
+ return;
+
if (sym) {
if (0 == sym->c)
put_extern_sym(sym, NULL, 0, 0);
c = sym->c;
}
+
/* now we can add ELF relocation info */
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)
return;
+ if (nocode_wanted)
+ return;
/* modify all stack values */
saved = 0;
@@ -865,6 +873,8 @@ ST_FUNC int get_reg(int rc)
/* find a free register */
for(r=0;r<NB_REGS;r++) {
if (reg_classes[r] & rc) {
+ if (nocode_wanted)
+ return r;
for(p=vstack;p<=vtop;p++) {
if ((p->r & 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) */
ST_FUNC void gaddrof(void)
{
- if (vtop->r & VT_REF && !nocode_wanted)
+ if (vtop->r & VT_REF)
gv(RC_INT);
vtop->r &= ~VT_LVAL;
/* 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;
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
/* for x86, we need to pop the FP stack */
- if (v == TREG_ST0 && !nocode_wanted) {
+ if (v == TREG_ST0) {
o(0xd8dd); /* fstp %st(0) */
} else
#endif
@@ -1607,7 +1617,7 @@ static void gen_opl(int op)
b = gvtst(0, 0);
} else {
#if defined(TCC_TARGET_I386)
- b = psym(0x850f, 0);
+ b = gjmp2(0x850f, 0);
#elif defined(TCC_TARGET_ARM)
b = ind;
o(0x1A000000 | encbranch(ind, 0, 1));
@@ -1789,23 +1799,12 @@ static void gen_opic(int op)
vtop->c.i = l2;
} else {
general_case:
- if (!nocode_wanted) {
/* call low level op generator */
if (t1 == VT_LLONG || t2 == VT_LLONG ||
(PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR)))
gen_opl(op);
else
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--;
} else {
general_case:
- if (!nocode_wanted) {
- gen_opf(op);
- } else {
- vtop--;
- }
+ gen_opf(op);
}
}
@@ -2149,7 +2144,7 @@ redo:
}
}
// 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);
}
@@ -2255,7 +2250,7 @@ static void gen_cast(CType *type)
}
/* bitfields first get cast to ints */
- if (vtop->type.t & VT_BITFIELD && !nocode_wanted) {
+ if (vtop->type.t & VT_BITFIELD) {
gv(RC_INT);
}
@@ -2331,7 +2326,7 @@ static void gen_cast(CType *type)
} else if (p && dbt == VT_BOOL) {
vtop->r = VT_CONST;
vtop->c.i = 1;
- } else if (!nocode_wanted) {
+ } else {
/* non constant case: generate code */
if (sf && df) {
/* convert from fp to fp */
@@ -2883,7 +2878,6 @@ ST_FUNC void vstore(void)
/* if structure, only generate pointer */
/* structure assignment : generate memcpy */
/* XXX: optimize if small size */
- if (!nocode_wanted) {
size = type_size(&vtop->type, &align);
/* destination */
@@ -2910,10 +2904,7 @@ ST_FUNC void vstore(void)
/* type size */
vpushi(size);
gfunc_call(3);
- } else {
- vswap();
- vpop();
- }
+
/* leave source on stack */
} else if (ft & VT_BITFIELD) {
/* bitfield store handling */
@@ -2961,7 +2952,6 @@ ST_FUNC void vstore(void)
vpop();
} else {
- if (!nocode_wanted) {
#ifdef CONFIG_TCC_BCHECK
/* bound check case */
if (vtop[-1].r & VT_MUSTBOUND) {
@@ -3020,7 +3010,7 @@ ST_FUNC void vstore(void)
} else {
store(r, vtop - 1);
}
- }
+
vswap();
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
vtop->r |= delayed_cast;
@@ -3033,10 +3023,7 @@ ST_FUNC void inc(int post, int c)
test_lvalue();
vdup(); /* save lvalue */
if (post) {
- if (!nocode_wanted)
- gv_dup(); /* duplicate value */
- else
- vdup(); /* duplicate value */
+ gv_dup(); /* duplicate value */
vrotb(3);
vrotb(3);
}
@@ -4189,7 +4176,7 @@ ST_FUNC void indir(void)
return;
expect("pointer");
}
- if ((vtop->r & VT_LVAL) && !nocode_wanted)
+ if (vtop->r & VT_LVAL)
gv(RC_INT);
vtop->type = *pointed_type(&vtop->type);
/* Arrays and functions are never lvalues */
@@ -4382,8 +4369,7 @@ ST_FUNC void unary(void)
if (const_wanted)
tcc_error("expected constant");
/* save all registers */
- if (!nocode_wanted)
- save_regs(0);
+ save_regs(0);
/* statement expression : we do not accept break/continue
inside as GCC does */
block(NULL, NULL, 1);
@@ -4610,8 +4596,6 @@ ST_FUNC void unary(void)
#ifdef TCC_TARGET_ARM64
case TOK___va_start: {
- if (nocode_wanted)
- tcc_error("statement in global scope");
next();
skip('(');
expr_eq();
@@ -4626,8 +4610,6 @@ ST_FUNC void unary(void)
}
case TOK___va_arg: {
CType type;
- if (nocode_wanted)
- tcc_error("statement in global scope");
next();
skip('(');
expr_eq();
@@ -4906,11 +4888,7 @@ ST_FUNC void unary(void)
if (sa)
tcc_error("too few arguments to function");
skip(')');
- if (!nocode_wanted) {
- gfunc_call(nb_args);
- } else {
- vtop -= (nb_args + 1);
- }
+ gfunc_call(nb_args);
/* return value */
for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {
@@ -5083,9 +5061,9 @@ static void expr_land(void)
expr_or();
vpop();
}
+ nocode_wanted = saved_nocode_wanted;
if (t)
gsym(t);
- nocode_wanted = saved_nocode_wanted;
gen_cast(&int_type);
break;
}
@@ -5127,9 +5105,9 @@ static void expr_lor(void)
expr_land();
vpop();
}
+ nocode_wanted = saved_nocode_wanted;
if (t)
gsym(t);
- nocode_wanted = saved_nocode_wanted;
gen_cast(&int_type);
break;
}
@@ -5206,16 +5184,6 @@ static void expr_cond(void)
}
}
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) {
/* needed to avoid having different registers saved in
each branch */
@@ -5575,19 +5543,22 @@ static void block(int *bsym, int *csym, int is_expr)
gexpr();
skip(')');
cond = condition_3way();
- if (cond == 0)
+ if (cond == 1)
+ a = 0, vpop();
+ else
+ a = gvtst(1, 0);
+ if (cond == 0)
nocode_wanted |= 2;
- a = gvtst(1, 0);
block(bsym, csym, 0);
if (cond != 1)
nocode_wanted = saved_nocode_wanted;
c = tok;
if (c == TOK_ELSE) {
next();
- if (cond == 1)
- nocode_wanted |= 2;
d = gjmp(0);
gsym(a);
+ if (cond == 1)
+ nocode_wanted |= 2;
block(bsym, csym, 0);
gsym(d); /* patch else jmp */
if (cond != 0)
@@ -5610,8 +5581,7 @@ static void block(int *bsym, int *csym, int is_expr)
block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted;
--local_scope;
- if(!nocode_wanted)
- gjmp_addr(d);
+ gjmp_addr(d);
gsym(a);
gsym_addr(b, d);
} else if (tok == '{') {
@@ -5801,8 +5771,7 @@ static void block(int *bsym, int *csym, int is_expr)
saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted;
- if(!nocode_wanted)
- gjmp_addr(c);
+ gjmp_addr(c);
gsym(a);
gsym_addr(b, c);
--local_scope;
@@ -5823,11 +5792,8 @@ static void block(int *bsym, int *csym, int is_expr)
skip('(');
gsym(b);
gexpr();
- if (!nocode_wanted) {
- c = gvtst(0, 0);
- gsym_addr(c, d);
- } else
- vtop--;
+ c = gvtst(0, 0);
+ gsym_addr(c, d);
nocode_wanted = saved_nocode_wanted;
skip(')');
gsym(a);
@@ -5852,21 +5818,19 @@ static void block(int *bsym, int *csym, int is_expr)
a = gjmp(a); /* add implicit break */
/* case lookup */
gsym(b);
- if (!nocode_wanted) {
- qsort(sw.p, sw.n, sizeof(void*), case_cmp);
- for (b = 1; b < sw.n; b++)
- if (sw.p[b - 1]->v2 >= sw.p[b]->v1)
- tcc_error("duplicate case value");
- /* Our switch table sorting is signed, so the compared
- value needs to be as well when it's 64bit. */
- if ((switchval.type.t & VT_BTYPE) == VT_LLONG)
- switchval.type.t &= ~VT_UNSIGNED;
- vpushv(&switchval);
- gcase(sw.p, sw.n, &a);
- vpop();
- if (sw.def_sym)
- gjmp_addr(sw.def_sym);
- }
+ qsort(sw.p, sw.n, sizeof(void*), case_cmp);
+ for (b = 1; b < sw.n; b++)
+ if (sw.p[b - 1]->v2 >= sw.p[b]->v1)
+ tcc_error("duplicate case value");
+ /* Our switch table sorting is signed, so the compared
+ value needs to be as well when it's 64bit. */
+ if ((switchval.type.t & VT_BTYPE) == VT_LLONG)
+ switchval.type.t &= ~VT_UNSIGNED;
+ vpushv(&switchval);
+ gcase(sw.p, sw.n, &a);
+ vpop();
+ if (sw.def_sym)
+ gjmp_addr(sw.def_sym);
dynarray_reset(&sw.p, &sw.n);
cur_switch = saved;
/* break label */
@@ -5910,10 +5874,7 @@ static void block(int *bsym, int *csym, int is_expr)
gexpr();
if ((vtop->type.t & VT_BTYPE) != VT_PTR)
expect("pointer");
- if (!nocode_wanted)
- ggoto();
- else
- vtop--;
+ ggoto();
} else if (tok >= TOK_UIDENT) {
s = label_find(tok);
/* put forward definition if needed */
@@ -5924,9 +5885,7 @@ static void block(int *bsym, int *csym, int is_expr)
s->r = LABEL_FORWARD;
}
vla_sp_restore_root();
- if (nocode_wanted)
- ;
- else if (s->r & LABEL_FORWARD)
+ if (s->r & LABEL_FORWARD)
s->jnext = gjmp(s->jnext);
else
gjmp_addr(s->jnext);
@@ -6893,6 +6852,7 @@ static void gen_function(Sym *sym)
rsym = 0;
block(NULL, NULL, 0);
+ nocode_wanted = 0;
gsym(rsym);
gfunc_epilog();
cur_text_section->data_offset = ind;
diff --git a/x86_64-gen.c b/x86_64-gen.c
index 86e097e..c94eb05 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -145,6 +145,8 @@ static int func_ret_sub;
ST_FUNC void g(int c)
{
int ind1;
+ if (nocode_wanted)
+ return;
ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
@@ -213,9 +215,6 @@ void gsym(int t)
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)
{
@@ -227,18 +226,18 @@ static int is64_type(int t)
/* instruction + 4 bytes data. Return the address of the data */
ST_FUNC int oad(int c, int s)
{
- int ind1;
-
+ int t;
+ if (nocode_wanted)
+ return s;
o(c);
- ind1 = ind + 4;
- if (ind1 > cur_text_section->data_allocated)
- section_realloc(cur_text_section, ind1);
- write32le(cur_text_section->data + ind, s);
- s = ind;
- ind = ind1;
- return s;
+ t = ind;
+ gen_le32(s);
+ return t;
}
+/* generate jmp to a label */
+#define gjmp2(instr,lbl) oad(instr,lbl)
+
ST_FUNC void gen_addr32(int r, Sym *sym, long c)
{
if (r & VT_SYM)
@@ -1703,7 +1702,7 @@ void gfunc_epilog(void)
/* generate a jump to a label */
int gjmp(int t)
{
- return psym(0xe9, t);
+ return gjmp2(0xe9, t);
}
/* 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)
{
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 */
if (vtop->c.i & 0x100)
{
@@ -1766,11 +1768,11 @@ ST_FUNC int gtst(int inv, int t)
else
{
g(0x0f);
- t = psym(0x8a, t); /* jp t */
+ t = gjmp2(0x8a, t); /* jp t */
}
}
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) {
/* && or || optimization */
if ((v & 1) == inv) {