aboutsummaryrefslogtreecommitdiff
path: root/tcc.c
diff options
context:
space:
mode:
authorbellard <bellard>2002-09-08 12:42:36 +0000
committerbellard <bellard>2002-09-08 12:42:36 +0000
commit405c88106d0fb0d5eefcf17cefe6e9c4db10e27f (patch)
tree886959a78969c648c2682e8cec73e163121ed8f4 /tcc.c
parentf1418e836fd2def153df8ee2ee6ad855605dc250 (diff)
downloadtinycc-405c88106d0fb0d5eefcf17cefe6e9c4db10e27f.tar.gz
tinycc-405c88106d0fb0d5eefcf17cefe6e9c4db10e27f.tar.bz2
fixed bound checking for structures - fixed ?: type handling - fixed '--' parsing
Diffstat (limited to 'tcc.c')
-rw-r--r--tcc.c129
1 files changed, 103 insertions, 26 deletions
diff --git a/tcc.c b/tcc.c
index 35bc618..35b6297 100644
--- a/tcc.c
+++ b/tcc.c
@@ -271,9 +271,11 @@ int nb_library_paths;
anon_sym: anonymous symbol index
*/
int rsym, anon_sym,
- prog, ind, loc, const_wanted;
-int global_expr; /* true if compound literals must be allocated
- globally (used during initializers parsing */
+ prog, ind, loc;
+/* expression generation modifiers */
+int const_wanted; /* true if constant wanted */
+int global_expr; /* true if compound literals must be allocated
+ globally (used during initializers parsing */
int func_vt, func_vc; /* current function return type (used by
return instruction) */
int last_line_num, last_ind, func_ind; /* debug last line number and pc */
@@ -921,11 +923,14 @@ static void put_extern_sym(Sym *sym, Section *section,
/* if bound checking is activated, we change some function
names by adding the "__bound" prefix */
switch(sym->v) {
+#if 0
+ /* XXX: we rely only on malloc hooks */
case TOK_malloc:
case TOK_free:
case TOK_realloc:
case TOK_memalign:
case TOK_calloc:
+#endif
case TOK_memcpy:
case TOK_memmove:
case TOK_memset:
@@ -1901,7 +1906,7 @@ void preprocess(void)
}
if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
- error("memory full");
+ error("#include recursion too deep");
if (c == '\"') {
/* first search in current dir if "header.h" */
size = 0;
@@ -2857,12 +2862,18 @@ void swap(int *p, int *q)
void vsetc(int t, int r, CValue *vc)
{
+ int v;
+
if (vtop >= vstack + VSTACK_SIZE)
error("memory full");
- /* cannot let cpu flags if other instruction are generated */
- /* XXX: VT_JMP test too ? */
- if ((vtop->r & VT_VALMASK) == VT_CMP)
- gv(RC_INT);
+ /* cannot let cpu flags if other instruction are generated. Also
+ avoid leaving VT_JMP anywhere except on the top of the stack
+ because it would complicate the code generator. */
+ if (vtop >= vstack) {
+ v = vtop->r & VT_VALMASK;
+ if (v == VT_CMP || (v & ~1) == VT_JMP)
+ gv(RC_INT);
+ }
vtop++;
vtop->t = t;
vtop->r = r;
@@ -3251,8 +3262,13 @@ int gv(int rc)
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
void gv2(int rc1, int rc2)
{
- /* generate more generic register first */
- if (rc1 <= rc2) {
+ int v;
+
+ /* generate more generic register first. But VT_JMP or VT_CMP
+ values must be generated first in all cases to avoid possible
+ reload errors */
+ v = vtop[0].r & VT_VALMASK;
+ if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
vswap();
gv(rc1);
vswap();
@@ -5239,8 +5255,12 @@ void unary(void)
/* change type to field type, and set to lvalue */
vtop->t = s->t;
/* an array is never an lvalue */
- if (!(vtop->t & VT_ARRAY))
+ if (!(vtop->t & VT_ARRAY)) {
vtop->r |= lvalue_type(vtop->t);
+ /* if bound checking, the referenced pointer must be checked */
+ if (do_bounds_check)
+ vtop->r |= VT_MUSTBOUND;
+ }
next();
} else if (tok == '[') {
next();
@@ -5468,21 +5488,23 @@ void eor(void)
/* XXX: better constant handling */
void expr_eq(void)
{
- int t, u, c, r1, r2, rc;
+ int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
+ SValue sv;
if (const_wanted) {
+ int c1, c;
sum(10);
if (tok == '?') {
c = vtop->c.i;
vpop();
next();
gexpr();
- t = vtop->c.i;
+ c1 = vtop->c.i;
vpop();
skip(':');
expr_eq();
if (c)
- vtop->c.i = t;
+ vtop->c.i = c1;
}
} else {
eor();
@@ -5490,23 +5512,76 @@ void expr_eq(void)
next();
save_regs(1); /* we need to save all registers here except
at the top because it is a branch point */
- t = gtst(1, 0);
+ tt = gtst(1, 0);
gexpr();
- /* XXX: long long handling ? */
- rc = RC_INT;
- if (is_float(vtop->t))
- rc = RC_FLOAT;
- r1 = gv(rc);
+ t1 = vtop->t;
+ bt1 = t1 & VT_BTYPE;
+ sv = *vtop; /* save value to handle it later */
vtop--; /* no vpop so that FP stack is not flushed */
skip(':');
u = gjmp(0);
- gsym(t);
+ gsym(tt);
expr_eq();
+ t2 = vtop->t;
+
+ bt2 = t2 & VT_BTYPE;
+ /* cast operands to correct type according to ISOC rules */
+ if (is_float(bt1) || is_float(bt2)) {
+ if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
+ t = VT_LDOUBLE;
+ } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
+ t = VT_DOUBLE;
+ } else {
+ t = VT_FLOAT;
+ }
+ } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
+ /* cast to biggest op */
+ t = VT_LLONG;
+ /* convert to unsigned if it does not fit in a long long */
+ if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
+ (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
+ t |= VT_UNSIGNED;
+ } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
+ /* XXX: test pointer compatibility */
+ t = t1;
+ } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
+ /* XXX: test structure compatibility */
+ t = t1;
+ } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
+ /* NOTE: as an extension, we accept void on only one side */
+ t = VT_VOID;
+ } else {
+ /* integer operations */
+ t = VT_INT;
+ /* convert to unsigned if it does not fit in an integer */
+ if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
+ (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
+ t |= VT_UNSIGNED;
+ }
+
+ /* now we convert second operand */
+ gen_cast(t);
+ rc = RC_INT;
+ if (is_float(t)) {
+ rc = RC_FLOAT;
+ } else if ((t & VT_BTYPE) == VT_LLONG) {
+ /* for long longs, we use fixed registers to avoid having
+ to handle a complicated move */
+ rc = RC_IRET;
+ }
r2 = gv(rc);
- move_reg(r1, r2);
- vtop->r = r1;
+ /* this is horrible, but we must also convert first
+ operand */
+ tt = gjmp(0);
gsym(u);
+ /* put again first value and cast it */
+ *vtop = sv;
+ gen_cast(t);
+ r1 = gv(rc);
+ move_reg(r2, r1);
+ vtop->r = r2;
+ gsym(tt);
}
}
}
@@ -7196,7 +7271,7 @@ int tcc_set_output_type(TCCState *s, int output_type)
void help(void)
{
- printf("tcc version 0.9.11 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
+ printf("tcc version 0.9.12 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
"usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
" [-g] [-b] [-Ldir] [-llib] [-shared] [-static]\n"
" [--] infile1 [infile2... --] [infile_args...]\n"
@@ -7232,7 +7307,7 @@ int main(int argc, char **argv)
int optind, output_type, multiple_files, i, reloc_output;
TCCState *s;
char **files;
- int nb_files, nb_libraries, nb_objfiles;
+ int nb_files, nb_libraries, nb_objfiles, dminus;
char objfilename[1024];
s = tcc_new();
@@ -7241,6 +7316,7 @@ int main(int argc, char **argv)
optind = 1;
outfile = NULL;
multiple_files = 0;
+ dminus = 0;
files = NULL;
nb_files = 0;
nb_libraries = 0;
@@ -7263,10 +7339,11 @@ int main(int argc, char **argv)
}
} else if (r[1] == '-') {
/* '--' enables multiple files input and also ends several file input */
- if (multiple_files) {
+ if (dminus && multiple_files) {
optind--; /* argv[0] will be '--' */
break;
}
+ dminus = 1;
multiple_files = 1;
} else if (r[1] == 'h' || r[1] == '?') {
show_help: