aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard>2002-11-18 21:46:44 +0000
committerbellard <bellard>2002-11-18 21:46:44 +0000
commit9620fd18e4804d9062ebaf329bc09f2b027c0469 (patch)
tree2ab4d085bb81b0faf921669022b7518f369e94aa
parent6cd2d5d2c84421eb188dce91b49391c8cc4dd479 (diff)
downloadtinycc-9620fd18e4804d9062ebaf329bc09f2b027c0469.tar.gz
tinycc-9620fd18e4804d9062ebaf329bc09f2b027c0469.tar.bz2
added CType structure for type storage - supressed define hash table - added time dump in bench
-rw-r--r--i386-gen.c76
-rw-r--r--tcc.c1124
2 files changed, 664 insertions, 536 deletions
diff --git a/i386-gen.c b/i386-gen.c
index 1fb27e4..ab2d794 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -185,13 +185,13 @@ void load(int r, SValue *sv)
SValue v1;
fr = sv->r;
- ft = sv->t;
+ ft = sv->type.t;
fc = sv->c.ul;
v = fr & VT_VALMASK;
if (fr & VT_LVAL) {
if (v == VT_LLOCAL) {
- v1.t = VT_INT;
+ v1.type.t = VT_INT;
v1.r = VT_LOCAL | VT_LVAL;
v1.c.ul = fc;
load(r, &v1);
@@ -248,7 +248,7 @@ void store(int r, SValue *v)
{
int fr, bt, ft, fc;
- ft = v->t;
+ ft = v->type.t;
fc = v->c.ul;
fr = v->r & VT_VALMASK;
bt = ft & VT_BTYPE;
@@ -293,8 +293,8 @@ void gfunc_param(GFuncContext *c)
{
int size, align, r;
- if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
- size = type_size(vtop->t, &align);
+ 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 */
@@ -303,15 +303,15 @@ void gfunc_param(GFuncContext *c)
r = get_reg(RC_INT);
o(0x89); /* mov %esp, r */
o(0xe0 + r);
- vset(vtop->t, r | VT_LVAL, 0);
+ vset(&vtop->type, r | VT_LVAL, 0);
vswap();
vstore();
c->args_size += size;
- } else if (is_float(vtop->t)) {
+ } else if (is_float(vtop->type.t)) {
gv(RC_FLOAT); /* only one float register */
- if ((vtop->t & VT_BTYPE) == VT_FLOAT)
+ if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
size = 4;
- else if ((vtop->t & VT_BTYPE) == VT_DOUBLE)
+ else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
size = 8;
else
size = 12;
@@ -327,7 +327,7 @@ void gfunc_param(GFuncContext *c)
/* simple type (currently always same size) */
/* XXX: implicit cast ? */
r = gv(RC_INT);
- if ((vtop->t & VT_BTYPE) == VT_LLONG) {
+ if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
size = 8;
o(0x50 + vtop->r2); /* push r */
} else {
@@ -384,31 +384,32 @@ void gfunc_call(GFuncContext *c)
}
/* generate function prolog of type 't' */
-void gfunc_prolog(int t)
+void gfunc_prolog(CType *func_type)
{
- int addr, align, size, u, func_call;
+ int addr, align, size, func_call;
Sym *sym;
+ CType *type;
- sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
+ sym = func_type->ref;
func_call = sym->r;
addr = 8;
/* if the function returns a structure, then add an
implicit pointer parameter */
- func_vt = sym->t;
- if ((func_vt & VT_BTYPE) == VT_STRUCT) {
+ func_vt = sym->type;
+ if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
func_vc = addr;
addr += 4;
}
/* define parameters */
while ((sym = sym->next) != NULL) {
- u = sym->t;
- sym_push(sym->v & ~SYM_FIELD, u,
+ type = &sym->type;
+ sym_push(sym->v & ~SYM_FIELD, type,
VT_LOCAL | VT_LVAL, addr);
- size = type_size(u, &align);
+ size = type_size(type, &align);
size = (size + 3) & ~3;
#ifdef FUNC_STRUCT_PARAM_AS_PTR
/* structs are passed as pointer */
- if ((u & VT_BTYPE) == VT_STRUCT) {
+ if ((type->t & VT_BTYPE) == VT_STRUCT) {
size = 4;
}
#endif
@@ -442,12 +443,12 @@ void gfunc_epilog(void)
/* generate bound local allocation */
saved_ind = ind;
ind = func_sub_sp_offset + 4;
- sym_data = get_sym_ref(char_pointer_type, lbounds_section,
+ sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, lbounds_section->data_offset);
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
- sym = external_global_sym(TOK___bound_local_new, func_old_type, 0);
+ sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
greloc(cur_text_section, sym,
ind + 1, R_386_PC32);
oad(0xe8, -4);
@@ -457,7 +458,7 @@ void gfunc_epilog(void)
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
- sym = external_global_sym(TOK___bound_local_delete, func_old_type, 0);
+ sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
greloc(cur_text_section, sym,
ind + 1, R_386_PC32);
oad(0xe8, -4);
@@ -518,7 +519,7 @@ int gtst(int inv, int t)
gsym(vtop->c.i);
}
} else {
- if (is_float(vtop->t)) {
+ if (is_float(vtop->type.t)) {
vpushi(0);
gen_op(TOK_NE);
}
@@ -572,8 +573,8 @@ void gen_opi(int op)
}
vtop--;
if (op >= TOK_ULT && op <= TOK_GT) {
- vtop--;
- vset(VT_INT, VT_CMP, op);
+ vtop->r = VT_CMP;
+ vtop->c.i = op;
}
break;
case '-':
@@ -731,7 +732,7 @@ void gen_opf(int op)
vtop->c.i = op;
} else {
/* no memory reference possible for long double operations */
- if ((vtop->t & VT_BTYPE) == VT_LDOUBLE) {
+ if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
load(REG_ST0, vtop);
swapped = !swapped;
}
@@ -755,7 +756,7 @@ void gen_opf(int op)
a++;
break;
}
- ft = vtop->t;
+ ft = vtop->type.t;
fc = vtop->c.ul;
if ((ft & VT_BTYPE) == VT_LDOUBLE) {
o(0xde); /* fxxxp %st, %st(1) */
@@ -766,7 +767,7 @@ void gen_opf(int op)
if ((r & VT_VALMASK) == VT_LLOCAL) {
SValue v1;
r = get_reg(RC_INT);
- v1.t = VT_INT;
+ v1.type.t = VT_INT;
v1.r = VT_LOCAL | VT_LVAL;
v1.c.ul = fc;
load(r, &v1);
@@ -789,14 +790,14 @@ void gen_cvt_itof(int t)
{
save_reg(REG_ST0);
gv(RC_INT);
- if ((vtop->t & VT_BTYPE) == VT_LLONG) {
+ if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
/* signed long long to float/double/long double (unsigned case
is handled generically) */
o(0x50 + vtop->r2); /* push r2 */
o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
o(0x242cdf); /* fildll (%esp) */
o(0x08c483); /* add $8, %esp */
- } else if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
+ } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
(VT_INT | VT_UNSIGNED)) {
/* unsigned int to float/double/long double */
o(0x6a); /* push $0 */
@@ -819,6 +820,9 @@ void gen_cvt_ftoi(int t)
{
int r, r2, size;
Sym *sym;
+ CType ushort_type;
+
+ ushort_type.t = VT_SHORT | VT_UNSIGNED;
gv(RC_FLOAT);
if (t != VT_INT)
@@ -828,7 +832,7 @@ void gen_cvt_ftoi(int t)
o(0x2dd9); /* ldcw xxx */
sym = external_global_sym(TOK___tcc_int_fpu_control,
- VT_SHORT | VT_UNSIGNED, VT_LVAL);
+ &ushort_type, VT_LVAL);
greloc(cur_text_section, sym,
ind, R_386_32);
gen_le32(0);
@@ -841,7 +845,7 @@ void gen_cvt_ftoi(int t)
o(0x24);
o(0x2dd9); /* ldcw xxx */
sym = external_global_sym(TOK___tcc_fpu_control,
- VT_SHORT | VT_UNSIGNED, VT_LVAL);
+ &ushort_type, VT_LVAL);
greloc(cur_text_section, sym,
ind, R_386_32);
gen_le32(0);
@@ -889,7 +893,7 @@ void gen_bounded_ptr_add(void)
vtop -= 2;
save_regs(0);
/* do a fast function call */
- sym = external_global_sym(TOK___bound_ptr_add, func_old_type, 0);
+ sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
greloc(cur_text_section, sym,
ind + 1, R_386_PC32);
oad(0xe8, -4);
@@ -911,14 +915,14 @@ void gen_bounded_ptr_deref(void)
size = 0;
/* XXX: put that code in generic part of tcc */
- if (!is_float(vtop->t)) {
+ if (!is_float(vtop->type.t)) {
if (vtop->r & VT_LVAL_BYTE)
size = 1;
else if (vtop->r & VT_LVAL_SHORT)
size = 2;
}
if (!size)
- size = type_size(vtop->t, &align);
+ size = type_size(&vtop->type, &align);
switch(size) {
case 1: func = TOK___bound_ptr_indir1; break;
case 2: func = TOK___bound_ptr_indir2; break;
@@ -935,7 +939,7 @@ void gen_bounded_ptr_deref(void)
/* patch relocation */
/* XXX: find a better solution ? */
rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
- sym = external_global_sym(func, func_old_type, 0);
+ sym = external_global_sym(func, &func_old_type, 0);
if (!sym->c)
put_extern_sym(sym, NULL, 0, 0);
rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
diff --git a/tcc.c b/tcc.c
index d76c471..9f5bd0b 100644
--- a/tcc.c
+++ b/tcc.c
@@ -28,7 +28,11 @@
#include <unistd.h>
#include <fcntl.h>
#include <setjmp.h>
+#ifdef WIN32
+#include <sys/timeb.h>
+#endif
#ifndef WIN32
+#include <sys/time.h>
#include <sys/ucontext.h>
#endif
#include "elf.h"
@@ -80,6 +84,7 @@
/* token symbol management */
typedef struct TokenSym {
struct TokenSym *hash_next;
+ struct Sym *sym_define; /* direct pointer to define */
int tok; /* token number */
int len;
char str[1];
@@ -92,6 +97,12 @@ typedef struct CString {
void *data_allocated; /* if non NULL, data has been malloced */
} CString;
+/* type definition */
+typedef struct CType {
+ int t;
+ struct Sym *ref;
+} CType;
+
/* constant value */
typedef union CValue {
long double ld;
@@ -109,7 +120,7 @@ typedef union CValue {
/* value on stack */
typedef struct SValue {
- int t; /* type */
+ CType type; /* type */
unsigned short r; /* register + flags */
unsigned short r2; /* second register, used for 'long long'
type. If not used, set to VT_CONST */
@@ -120,9 +131,9 @@ typedef struct SValue {
/* symbol management */
typedef struct Sym {
int v; /* symbol token */
- int t; /* associated type */
int r; /* associated register */
int c; /* associated number */
+ CType type; /* associated type */
struct Sym *next; /* next related symbol */
struct Sym *prev; /* prev symbol in stack */
struct Sym *hash_next; /* next symbol in hash table */
@@ -273,20 +284,22 @@ int const_wanted; /* true if constant wanted */
int nocode_wanted; /* true if no code generation wanted for an expression */
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) */
+CType func_vt; /* current function return type (used by return
+ instruction) */
+int func_vc;
int last_line_num, last_ind, func_ind; /* debug last line number and pc */
int tok_ident;
TokenSym **table_ident;
TokenSym *hash_ident[TOK_HASH_SIZE];
char token_buf[STRING_MAX_SIZE + 1];
char *funcname;
-SymStack define_stack, global_stack, local_stack, label_stack;
+SymStack global_stack, local_stack, label_stack;
+Sym *define_stack;
SValue vstack[VSTACK_SIZE], *vtop;
int *macro_ptr, *macro_ptr_allocated;
-int char_pointer_type;
-int func_old_type;
+/* some predefined types */
+CType char_pointer_type, func_old_type, int_type;
/* compile with debug symbol (and use them if error during execution) */
int do_debug = 0;
@@ -511,6 +524,7 @@ static const char *tcc_keywords =
#ifdef WIN32
#define snprintf _snprintf
+#define vsnprintf _vsnprintf
#endif
#if defined(WIN32) || defined(TCC_UCLIBC)
@@ -535,16 +549,16 @@ static char *pstrcat(char *buf, int buf_size, const char *s);
static void sum(int l);
static void next(void);
static void next_nomacro(void);
-static int parse_expr_type(void);
-static int expr_type(void);
-static int unary_type(void);
+static void parse_expr_type(CType *type);
+static void expr_type(CType *type);
+static void unary_type(CType *type);
static int expr_const(void);
static void expr_eq(void);
static void gexpr(void);
static void decl(int l);
-static void decl_initializer(int t, Section *sec, unsigned long c,
+static void decl_initializer(CType *type, Section *sec, unsigned long c,
int first, int size_only);
-static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
+static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
int has_init, int v, int scope);
int gv(int rc);
void gv2(int rc1, int rc2);
@@ -561,30 +575,29 @@ static void macro_subst(TokenString *tok_str,
int save_reg_forced(int r);
void gen_op(int op);
void force_charshort_cast(int t);
-void gen_cast(int t);
+static void gen_cast(CType *type);
void vstore(void);
Sym *sym_find(int v);
-Sym *sym_push(int v, int t, int r, int c);
+Sym *sym_push(int v, CType *type, int r, int c);
/* type handling */
-int type_size(int t, int *a);
-int pointed_type(int t);
-int pointed_size(int t);
+int type_size(CType *type, int *a);
+static inline CType *pointed_type(CType *type);
+static int pointed_size(CType *type);
static int lvalue_type(int t);
-int is_compatible_types(int t1, int t2);
-int parse_btype(int *type_ptr, AttributeDef *ad);
-int type_decl(AttributeDef *ad, int *v, int t, int td);
+static int is_compatible_types(CType *type1, CType *type2);
+static int parse_btype(CType *type, AttributeDef *ad);
+static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
void error(const char *fmt, ...);
-void rt_error(struct ucontext *uc, const char *fmt, ...);
void vpushi(int v);
-void vset(int t, int r, int v);
+void vset(CType *type, int r, int v);
void type_to_str(char *buf, int buf_size,
- int t, const char *varstr);
+ CType *type, const char *varstr);
char *get_tok_str(int v, CValue *cv);
-static Sym *get_sym_ref(int t, Section *sec,
+static Sym *get_sym_ref(CType *type, Section *sec,
unsigned long offset, unsigned long size);
-static Sym *external_global_sym(int v, int u, int r);
+static Sym *external_global_sym(int v, CType *type, int r);
/* section generation */
static void section_realloc(Section *sec, unsigned long new_size);
@@ -632,6 +645,7 @@ static inline int is_float(int t)
#define RTLD_LAZY 0x001
#define RTLD_NOW 0x002
#define RTLD_GLOBAL 0x100
+#define RTLD_DEFAULT NULL
/* dummy function for profiling */
void *dlopen(const char *filename, int flag)
@@ -895,18 +909,17 @@ static void put_extern_sym(Sym *sym, Section *section,
int sym_type, sym_bind, sh_num, info;
Elf32_Sym *esym;
const char *name;
- char buf[32];
if (section)
sh_num = section->sh_num;
else
sh_num = SHN_UNDEF;
if (!sym->c) {
- if ((sym->t & VT_BTYPE) == VT_FUNC)
+ if ((sym->type.t & VT_BTYPE) == VT_FUNC)
sym_type = STT_FUNC;
else
sym_type = STT_OBJECT;
- if (sym->t & VT_STATIC)
+ if (sym->type.t & VT_STATIC)
sym_bind = STB_LOCAL;
else
sym_bind = STB_GLOBAL;
@@ -914,6 +927,8 @@ static void put_extern_sym(Sym *sym, Section *section,
name = get_tok_str(sym->v, NULL);
#ifdef CONFIG_TCC_BCHECK
if (do_bounds_check) {
+ char buf[32];
+
/* XXX: avoid doing that for statics ? */
/* if bound checking is activated, we change some function
names by adding the "__bound" prefix */
@@ -1131,6 +1146,7 @@ TokenSym *tok_alloc(const char *str, int len)
ts = tcc_malloc(sizeof(TokenSym) + len);
table_ident[i] = ts;
ts->tok = tok_ident++;
+ ts->sym_define = NULL;
ts->len = len;
ts->hash_next = NULL;
memcpy(ts->str, str, len + 1);
@@ -1331,7 +1347,7 @@ Sym *sym_push2(Sym **ps, int v, int t, int c)
Sym *s;
s = tcc_malloc(sizeof(Sym));
s->v = v;
- s->t = t;
+ s->type.t = t;
s->c = c;
s->next = NULL;
/* add in stack */
@@ -1393,13 +1409,14 @@ Sym *sym_find(int v)
}
/* push a given symbol on the symbol stack */
-Sym *sym_push(int v, int t, int r, int c)
+Sym *sym_push(int v, CType *type, int r, int c)
{
Sym *s;
if (local_stack.top)
- s = sym_push1(&local_stack, v, t, c);
+ s = sym_push1(&local_stack, v, type->t, c);
else
- s = sym_push1(&global_stack, v, t, c);
+ s = sym_push1(&global_stack, v, type->t, c);
+ s->type.ref = type->ref;
s->r = r;
return s;
}
@@ -1422,21 +1439,6 @@ void sym_pop(SymStack *st, Sym *b)
st->top = b;
}
-/* undefined a hashed symbol (used for #undef). Its name is set to
- zero */
-void sym_undef(SymStack *st, Sym *s)
-{
- Sym **ss;
- ss = &st->hash[HASH_SYM(s->v)];
- while (*ss != NULL) {
- if (*ss == s)
- break;
- ss = &(*ss)->hash_next;
- }
- *ss = s->hash_next;
- s->v = 0;
-}
-
/* I/O layer */
BufferedFile *tcc_open(TCCState *s1, const char *filename)
@@ -1794,6 +1796,55 @@ static int tok_get(int **tok_str, CValue *cv)
return t;
}
+/* defines handling */
+static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
+{
+ Sym *s;
+
+ s = sym_push2(&define_stack, v, macro_type, (int)str);
+ s->next = first_arg;
+ table_ident[v - TOK_IDENT]->sym_define = s;
+}
+
+/* undefined a define symbol. Its name is just set to zero */
+static void define_undef(Sym *s)
+{
+ int v;
+ v = s->v;
+ if (v >= TOK_IDENT && v < tok_ident)
+ table_ident[v - TOK_IDENT]->sym_define = NULL;
+ s->v = 0;
+}
+
+static inline Sym *define_find(int v)
+{
+ v -= TOK_IDENT;
+ if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
+ return NULL;
+ return table_ident[v]->sym_define;
+}
+
+/* free define stack until top reaches 'b' */
+static void free_defines(Sym *b)
+{
+ Sym *top, *top1;
+ int v;
+
+ top = define_stack;
+ while (top != b) {
+ top1 = top->prev;
+ /* do not free args or predefined defines */
+ if (top->c)
+ tok_str_free((int *)top->c);
+ v = top->v;
+ if (v >= TOK_IDENT && v < tok_ident)
+ table_ident[v - TOK_IDENT]->sym_define = NULL;
+ tcc_free(top);
+ top = top1;
+ }
+ define_stack = b;
+}
+
/* eval an expression for #if/#elif */
int expr_preprocess(void)
{
@@ -1808,7 +1859,7 @@ int expr_preprocess(void)
t = tok;
if (t == '(')
next_nomacro();
- c = sym_find1(&define_stack, tok) != 0;
+ c = define_find(tok) != 0;
if (t == '(')
next_nomacro();
tok = TOK_CINT;
@@ -1855,6 +1906,8 @@ void parse_define(void)
TokenString str;
v = tok;
+ if (v < TOK_IDENT)
+ error("invalid macro name '%s'", get_tok_str(tok, &tokc));
/* XXX: should check if same macro (ANSI) */
first = NULL;
t = MACRO_OBJ;
@@ -1876,7 +1929,7 @@ void parse_define(void)
}
if (varg < TOK_IDENT)
error("badly punctuated parameter list");
- s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
+ s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
*ps = s;
ps = &s->next;
if (tok != ',')
@@ -1897,8 +1950,7 @@ void parse_define(void)
printf("define %s %d: ", get_tok_str(v, NULL), t);
tok_print(str.str);
#endif
- s = sym_push1(&define_stack, v, t, (int)str.str);
- s->next = first;
+ define_push(v, t, str.str, first);
}
/* XXX: use a token or a hash table to accelerate matching ? */
@@ -1965,10 +2017,10 @@ void preprocess(void)
parse_define();
} else if (tok == TOK_UNDEF) {
next_nomacro();
- s = sym_find1(&define_stack, tok);
+ s = define_find(tok);
/* undefine symbol by putting an invalid name */
if (s)
- sym_undef(&define_stack, s);
+ define_undef(s);
} else if (tok == TOK_INCLUDE) {
skip_spaces();
if (ch == '<') {
@@ -2022,7 +2074,7 @@ void preprocess(void)
ch = '\n';
e = search_cached_include(s1, c, buf);
- if (e && sym_find1(&define_stack, e->ifndef_macro)) {
+ if (e && define_find(e->ifndef_macro)) {
/* no need to parse the include because the 'ifndef macro'
is defined */
#ifdef INC_DEBUG
@@ -2105,7 +2157,7 @@ void preprocess(void)
}
state = INCLUDE_STATE_NONE;
}
- c = (sym_find1(&define_stack, tok) != 0) ^ c;
+ c = (define_find(tok) != 0) ^ c;
do_if:
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
error("memory full");
@@ -2772,7 +2824,7 @@ static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
/* XXX: test of the ',' is not 100%
reliable. should fix it to avoid security
problems */
- if (gnu_ext && s->t &&
+ if (gnu_ext && s->type.t &&
last_tok == TOK_TWOSHARPS &&
str.len >= 2 && str.str[str.len - 2] == ',') {
if (*st == 0) {
@@ -2959,7 +3011,7 @@ static int macro_subst_tok(TokenString *tok_str,
} else {
mstr = (int *)s->c;
mstr_allocated = 0;
- if (s->t == MACRO_FUNC) {
+ if (s->type.t == MACRO_FUNC) {
/* NOTE: we do not use next_nomacro to avoid eating the
next token. XXX: find better solution */
if (macro_ptr) {
@@ -2990,7 +3042,7 @@ static int macro_subst_tok(TokenString *tok_str,
/* NOTE: non zero sa->t indicates VA_ARGS */
while ((parlevel > 0 ||
(tok != ')' &&
- (tok != ',' || sa->t))) &&
+ (tok != ',' || sa->type.t))) &&
tok != -1) {
if (tok == '(')
parlevel++;
@@ -3000,12 +3052,12 @@ static int macro_subst_tok(TokenString *tok_str,
next_nomacro();
}
tok_str_add(&str, 0);
- sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
+ sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
sa = sa->next;
if (tok == ')') {
/* special case for gcc var args: add an empty
var arg argument if it is omitted */
- if (sa && sa->t && gnu_ext)
+ if (sa && sa->type.t && gnu_ext)
continue;
else
break;
@@ -3063,7 +3115,7 @@ static void macro_subst(TokenString *tok_str,
next_nomacro();
if (tok == 0)
break;
- s = sym_find1(&define_stack, tok);
+ s = define_find(tok);
if (s != NULL) {
if (macro_subst_tok(tok_str, nested_list, s) != 0)
goto no_subst;
@@ -3094,7 +3146,7 @@ static void next(void)
/* if not reading from macro substituted string, then try
to substitute macros */
if (tok >= TOK_IDENT) {
- s = sym_find1(&define_stack, tok);
+ s = define_find(tok);
if (s) {
/* we have a macro: we try to substitute */
tok_str_new(&str);
@@ -3135,7 +3187,7 @@ void swap(int *p, int *q)
*q = t;
}
-void vsetc(int t, int r, CValue *vc)
+void vsetc(CType *type, int r, CValue *vc)
{
int v;
@@ -3150,7 +3202,7 @@ void vsetc(int t, int r, CValue *vc)
gv(RC_INT);
}
vtop++;
- vtop->t = t;
+ vtop->type = *type;
vtop->r = r;
vtop->r2 = VT_CONST;
vtop->c = *vc;
@@ -3161,35 +3213,36 @@ void vpushi(int v)
{
CValue cval;
cval.i = v;
- vsetc(VT_INT, VT_CONST, &cval);
+ vsetc(&int_type, VT_CONST, &cval);
}
/* Return a static symbol pointing to a section */
-static Sym *get_sym_ref(int t, Section *sec,
+static Sym *get_sym_ref(CType *type, Section *sec,
unsigned long offset, unsigned long size)
{
int v;
Sym *sym;
v = anon_sym++;
- sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
+ sym = sym_push1(&global_stack, v, type->t | VT_STATIC, 0);
+ sym->type.ref = type->ref;
sym->r = VT_CONST | VT_SYM;
put_extern_sym(sym, sec, offset, size);
return sym;
}
/* push a reference to a section offset by adding a dummy symbol */
-static void vpush_ref(int t, Section *sec, unsigned long offset, unsigned long size)
+static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
{
CValue cval;
cval.ul = 0;
- vsetc(t, VT_CONST | VT_SYM, &cval);
- vtop->sym = get_sym_ref(t, sec, offset, size);
+ vsetc(type, VT_CONST | VT_SYM, &cval);
+ vtop->sym = get_sym_ref(type, sec, offset, size);
}
/* define a new external reference to a symbol 'v' of type 'u' */
-static Sym *external_global_sym(int v, int u, int r)
+static Sym *external_global_sym(int v, CType *type, int r)
{
Sym *s;
@@ -3197,43 +3250,52 @@ static Sym *external_global_sym(int v, int u, int r)
if (!s) {
/* push forward reference */
s = sym_push1(&global_stack,
- v, u | VT_EXTERN, 0);
+ v, type->t | VT_EXTERN, 0);
+ s->type.ref = type->ref;
s->r = r | VT_CONST | VT_SYM;
}
return s;
}
/* define a new external reference to a symbol 'v' of type 'u' */
-static Sym *external_sym(int v, int u, int r)
+static Sym *external_sym(int v, CType *type, int r)
{
Sym *s;
s = sym_find(v);
if (!s) {
/* push forward reference */
- s = sym_push(v, u | VT_EXTERN, r | VT_CONST | VT_SYM, 0);
+ s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
+ s->type.t |= VT_EXTERN;
}
return s;
}
/* push a reference to global symbol v */
-static void vpush_global_sym(int t, int v)
+static void vpush_global_sym(CType *type, int v)
{
Sym *sym;
CValue cval;
- sym = external_global_sym(v, t, 0);
+ sym = external_global_sym(v, type, 0);
cval.ul = 0;
- vsetc(t, VT_CONST | VT_SYM, &cval);
+ vsetc(type, VT_CONST | VT_SYM, &cval);
vtop->sym = sym;
}
-void vset(int t, int r, int v)
+void vset(CType *type, int r, int v)
{
CValue cval;
cval.i = v;
- vsetc(t, r, &cval);
+ vsetc(type, r, &cval);
+}
+
+void vseti(int r, int v)
+{
+ CType type;
+ type.t = VT_INT;
+ vset(&type, r, v);
}
void vswap(void)
@@ -3261,8 +3323,9 @@ void vdup(void)
/* save r to the memory stack, and mark it as being free */
void save_reg(int r)
{
- int l, saved, t, size, align;
+ int l, saved, size, align;
SValue *p, sv;
+ CType *type;
/* modify all stack values */
saved = 0;
@@ -3275,13 +3338,13 @@ void save_reg(int r)
/* NOTE: must reload 'r' because r might be equal to r2 */
r = p->r & VT_VALMASK;
/* store register in the stack */
- t = p->t;
+ type = &p->type;
if ((p->r & VT_LVAL) ||
- (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
- t = VT_INT;
- size = type_size(t, &align);
+ (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
+ type = &int_type;
+ size = type_size(type, &align);
loc = (loc - size) & -align;
- sv.t = t;
+ sv.type.t = type->t;
sv.r = VT_LOCAL | VT_LVAL;
sv.c.ul = loc;
store(r, &sv);
@@ -3292,7 +3355,7 @@ void save_reg(int r)
}
#endif
/* special long long case */
- if ((t & VT_BTYPE) == VT_LLONG) {
+ if ((type->t & VT_BTYPE) == VT_LLONG) {
sv.c.ul += 4;
store(p->r2, &sv);
}
@@ -3306,7 +3369,7 @@ void save_reg(int r)
p->c.ul */
p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
} else {
- p->r = lvalue_type(p->t) | VT_LOCAL;
+ p->r = lvalue_type(p->type.t) | VT_LOCAL;
}
p->r2 = VT_CONST;
p->c.ul = l;
@@ -3374,7 +3437,7 @@ void move_reg(int r, int s)
if (r != s) {
save_reg(r);
- sv.t = VT_INT;
+ sv.type.t = VT_INT;
sv.r = s;
sv.c.ul = 0;
load(r, &sv);
@@ -3394,7 +3457,8 @@ void gaddrof(void)
/* generate lvalue bound code */
void gbound(void)
{
- int lval_type, t1;
+ int lval_type;
+ CType type1;
vtop->r &= ~VT_MUSTBOUND;
/* if lvalue, then use checking code before dereferencing */
@@ -3403,13 +3467,13 @@ void gbound(void)
if (!(vtop->r & VT_BOUNDED)) {
lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
/* must save type because we must set it to int to get pointer */
- t1 = vtop->t;
- vtop->t = VT_INT;
+ type1 = vtop->type;
+ vtop->type.t = VT_INT;
gaddrof();
vpushi(0);
gen_bounded_ptr_add();
vtop->r |= lval_type;
- vtop->t = t1;
+ vtop->type = type1;
}
/* then check for dereferencing */
gen_bounded_ptr_deref();
@@ -3426,11 +3490,11 @@ int gv(int rc)
unsigned long long ll;
/* NOTE: get_reg can modify vstack[] */
- if (vtop->t & VT_BITFIELD) {
- bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
- bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
+ if (vtop->type.t & VT_BITFIELD) {
+ bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
+ bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
/* remove bit field info to avoid loops */
- vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
+ vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
/* generate shifts */
vpushi(32 - (bit_pos + bit_size));
gen_op(TOK_SHL);
@@ -3439,7 +3503,7 @@ int gv(int rc)
gen_op(TOK_SAR);
r = gv(rc);
} else {
- if (is_float(vtop->t) &&
+ if (is_float(vtop->type.t) &&
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
Sym *sym;
int *ptr;
@@ -3448,7 +3512,7 @@ int gv(int rc)
/* XXX: unify with initializers handling ? */
/* CPUs usually cannot use float constants, so we store them
generically in data segment */
- size = type_size(vtop->t, &align);
+ size = type_size(&vtop->type, &align);
offset = (data_section->data_offset + align - 1) & -align;
data_section->data_offset = offset;
/* XXX: not portable yet */
@@ -3456,7 +3520,7 @@ int gv(int rc)
size = size >> 2;
for(i=0;i<size;i++)
ptr[i] = vtop->c.tab[i];
- sym = get_sym_ref(vtop->t, data_section, offset, size << 2);
+ sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
vtop->r |= VT_LVAL | VT_SYM;
vtop->sym = sym;
vtop->c.ul = 0;
@@ -3474,10 +3538,10 @@ int gv(int rc)
if (r >= VT_CONST ||
(vtop->r & VT_LVAL) ||
!(reg_classes[r] & rc) ||
- ((vtop->t & VT_BTYPE) == VT_LLONG &&
+ ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
!(reg_classes[vtop->r2] & rc))) {
r = get_reg(rc);
- if ((vtop->t & VT_BTYPE) == VT_LLONG) {
+ if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
/* two register type load : expand to two words
temporarily */
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
@@ -3494,7 +3558,7 @@ int gv(int rc)
vdup();
vtop[-1].r = r; /* save register value */
/* increment pointer to get second word */
- vtop->t = VT_INT;
+ vtop->type.t = VT_INT;
gaddrof();
vpushi(4);
gen_op('+');
@@ -3515,11 +3579,11 @@ int gv(int rc)
vpop();
/* write second register */
vtop->r2 = r2;
- } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
+ } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
int t1, t;
/* lvalue of scalar type : need to use lvalue type
because of possible cast */
- t = vtop->t;
+ t = vtop->type.t;
t1 = t;
/* compute memory access type */
if (vtop->r & VT_LVAL_BYTE)
@@ -3528,10 +3592,10 @@ int gv(int rc)
t = VT_SHORT;
if (vtop->r & VT_LVAL_UNSIGNED)
t |= VT_UNSIGNED;
- vtop->t = t;
+ vtop->type.t = t;
load(r, vtop);
/* restore wanted type */
- vtop->t = t1;
+ vtop->type.t = t1;
} else {
/* one register type load */
load(r, vtop);
@@ -3579,14 +3643,14 @@ void lexpand(void)
{
int u;
- u = vtop->t & VT_UNSIGNED;
+ u = vtop->type.t & VT_UNSIGNED;
gv(RC_INT);
vdup();
vtop[0].r = vtop[-1].r2;
vtop[0].r2 = VT_CONST;
vtop[-1].r2 = VT_CONST;
- vtop[0].t = VT_INT | u;
- vtop[-1].t = VT_INT | u;
+ vtop[0].type.t = VT_INT | u;
+ vtop[-1].type.t = VT_INT | u;
}
/* build a long long from two ints */
@@ -3594,7 +3658,7 @@ void lbuild(int t)
{
gv2(RC_INT, RC_INT);
vtop[-1].r2 = vtop[0].r;
- vtop[-1].t = t;
+ vtop[-1].type.t = t;
vpop();
}
@@ -3635,7 +3699,7 @@ void gv_dup(void)
int rc, t, r, r1;
SValue sv;
- t = vtop->t;
+ t = vtop->type.t;
if ((t & VT_BTYPE) == VT_LLONG) {
lexpand();
gv_dup();
@@ -3653,10 +3717,10 @@ void gv_dup(void)
} else {
/* duplicate value */
rc = RC_INT;
- sv.t = VT_INT;
+ sv.type.t = VT_INT;
if (is_float(t)) {
rc = RC_FLOAT;
- sv.t = t;
+ sv.type.t = t;
}
r = gv(rc);
r1 = get_reg(rc);
@@ -3695,7 +3759,7 @@ void gen_opl(int op)
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);
vpushi(0);
vtop->r = REG_IRET;
@@ -3707,7 +3771,7 @@ void gen_opl(int op)
case '*':
case '+':
case '-':
- t = vtop->t;
+ t = vtop->type.t;
vswap();
lexpand();
vrotb(3);
@@ -3768,7 +3832,7 @@ void gen_opl(int op)
case TOK_SHR:
case TOK_SHL:
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
- t = vtop[-1].t;
+ t = vtop[-1].type.t;
vswap();
lexpand();
vrotb(3);
@@ -3836,7 +3900,7 @@ void gen_opl(int op)
break;
default:
/* compare operations */
- t = vtop->t;
+ t = vtop->type.t;
vswap();
lexpand();
vrotb(3);
@@ -3881,7 +3945,7 @@ void gen_opl(int op)
gen_op(op);
a = gtst(1, a);
gsym(b);
- vset(VT_INT, VT_JMPI, a);
+ vseti(VT_JMPI, a);
break;
}
}
@@ -4015,10 +4079,10 @@ void gen_opif(int op)
c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
if (c1 && c2) {
- if (v1->t == VT_FLOAT) {
+ if (v1->type.t == VT_FLOAT) {
f1 = v1->c.f;
f2 = v2->c.f;
- } else if (v1->t == VT_DOUBLE) {
+ } else if (v1->type.t == VT_DOUBLE) {
f1 = v1->c.d;
f2 = v2->c.d;
} else {
@@ -4048,9 +4112,9 @@ void gen_opif(int op)
goto general_case;
}
/* XXX: overflow test ? */
- if (v1->t == VT_FLOAT) {
+ if (v1->type.t == VT_FLOAT) {
v1->c.f = f1;
- } else if (v1->t == VT_DOUBLE) {
+ } else if (v1->type.t == VT_DOUBLE) {
v1->c.d = f1;
} else {
v1->c.ld = f1;
@@ -4066,9 +4130,10 @@ void gen_opif(int op)
}
}
-int pointed_size(int t)
+static int pointed_size(CType *type)
{
- return type_size(pointed_type(t), &t);
+ int align;
+ return type_size(pointed_type(type), &align);
}
#if 0
@@ -4090,9 +4155,10 @@ void check_pointer_types(SValue *p1, SValue *p2)
void gen_op(int op)
{
int u, t1, t2, bt1, bt2, t;
+ CType type1;
- t1 = vtop[-1].t;
- t2 = vtop[0].t;
+ t1 = vtop[-1].type.t;
+ t2 = vtop[0].type.t;
bt1 = t1 & VT_BTYPE;
bt2 = t2 & VT_BTYPE;
@@ -4106,16 +4172,15 @@ void gen_op(int op)
goto std_op;
}
/* if both pointers, then it must be the '-' op */
- if ((t1 & VT_BTYPE) == VT_PTR &&
- (t2 & VT_BTYPE) == VT_PTR) {
+ if (bt1 == VT_PTR && bt2 == VT_PTR) {
if (op != '-')
error("cannot use pointers here");
// check_pointer_types(vtop - 1, vtop);
/* XXX: check that types are compatible */
- u = pointed_size(t1);
+ u = pointed_size(&vtop[-1].type);
gen_opic(op);
/* set to integer type */
- vtop->t = VT_INT;
+ vtop->type.t = VT_INT;
vpushi(u);
gen_op(TOK_PDIV);
} else {
@@ -4123,12 +4188,13 @@ void gen_op(int op)
if (op != '-' && op != '+')
error("cannot use pointers here");
/* Put pointer as first operand */
- if ((t2 & VT_BTYPE) == VT_PTR) {
+ if (bt2 == VT_PTR) {
vswap();
swap(&t1, &t2);
}
+ type1 = vtop[-1].type;
/* XXX: cast to int ? (long long case) */
- vpushi(pointed_size(vtop[-1].t));
+ vpushi(pointed_size(&vtop[-1].type));
gen_op('*');
#ifdef CONFIG_TCC_BCHECK
/* if evaluating constant expression, no code should be
@@ -4148,7 +4214,7 @@ void gen_op(int op)
gen_opic(op);
}
/* put again type if gen_opic() swaped operands */
- vtop->t = t1;
+ vtop->type = type1;
}
} else if (is_float(bt1) || is_float(bt2)) {
/* compute bigger type and do implicit casts */
@@ -4199,14 +4265,14 @@ void gen_op(int op)
op = TOK_UGE;
}
vswap();
- gen_cast(t);
+ type1.t = t;
+ gen_cast(&type1);
vswap();
/* special case for shifts and long long: we keep the shift as
an integer */
if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
- gen_cast(VT_INT);
- else
- gen_cast(t);
+ type1.t = VT_INT;
+ gen_cast(&type1);
if (is_float(t))
gen_opif(op);
else if ((t & VT_BTYPE) == VT_LLONG)
@@ -4215,9 +4281,9 @@ void gen_op(int op)
gen_opic(op);
if (op >= TOK_ULT && op <= TOK_GT) {
/* relationnal op: the result is an int */
- vtop->t = VT_INT;
+ vtop->type.t = VT_INT;
} else {
- vtop->t = t;
+ vtop->type.t = t;
}
}
}
@@ -4227,17 +4293,17 @@ void gen_cvt_itof1(int t)
{
GFuncContext gf;
- if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
+ if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
(VT_LLONG | VT_UNSIGNED)) {
gfunc_start(&gf, FUNC_CDECL);
gfunc_param(&gf);
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)
- vpush_global_sym(func_old_type, TOK___ulltod);
+ vpush_global_sym(&func_old_type, TOK___ulltod);
else
- vpush_global_sym(func_old_type, TOK___ulltold);
+ vpush_global_sym(&func_old_type, TOK___ulltold);
gfunc_call(&gf);
vpushi(0);
vtop->r = REG_FRET;
@@ -4255,14 +4321,14 @@ void gen_cvt_ftoi1(int t)
if (t == (VT_LLONG | VT_UNSIGNED)) {
/* not handled natively */
gfunc_start(&gf, FUNC_CDECL);
- st = vtop->t & VT_BTYPE;
+ st = vtop->type.t & VT_BTYPE;
gfunc_param(&gf);
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)
- vpush_global_sym(func_old_type, TOK___fixunsdfdi);
+ vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
else
- vpush_global_sym(func_old_type, TOK___fixunsxfdi);
+ vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
gfunc_call(&gf);
vpushi(0);
vtop->r = REG_IRET;
@@ -4294,8 +4360,8 @@ void force_charshort_cast(int t)
}
}
-/* cast 'vtop' to 't' type */
-void gen_cast(int t)
+/* cast 'vtop' to 'type' */
+static void gen_cast(CType *type)
{
int sbt, dbt, sf, df, c;
@@ -4304,11 +4370,11 @@ void gen_cast(int t)
be incorrect */
if (vtop->r & VT_MUSTCAST) {
vtop->r &= ~VT_MUSTCAST;
- force_charshort_cast(vtop->t);
+ force_charshort_cast(vtop->type.t);
}
-
- dbt = t & (VT_BTYPE | VT_UNSIGNED);
- sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
+
+ dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
+ sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
if (sbt != dbt && !nocode_wanted) {
sf = is_float(sbt);
@@ -4395,10 +4461,10 @@ void gen_cast(int t)
do_ftoi:
gen_cvt_ftoi1(dbt);
}
- if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
+ if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
/* additionnal cast for char/short/bool... */
- vtop->t = dbt;
- gen_cast(t);
+ vtop->type.t = dbt;
+ gen_cast(type);
}
} else if ((dbt & VT_BTYPE) == VT_LLONG) {
if ((sbt & VT_BTYPE) != VT_LLONG) {
@@ -4431,7 +4497,7 @@ void gen_cast(int t)
gen_op(TOK_NE);
} else if ((dbt & VT_BTYPE) == VT_BYTE ||
(dbt & VT_BTYPE) == VT_SHORT) {
- force_charshort_cast(t);
+ force_charshort_cast(dbt);
} else if ((dbt & VT_BTYPE) == VT_INT) {
/* scalar to int */
if (sbt == VT_LLONG) {
@@ -4444,25 +4510,25 @@ void gen_cast(int t)
VT_LVAL_xxx constants) */
}
}
- vtop->t = t;
+ vtop->type = *type;
}
/* return type size. Put alignment at 'a' */
-int type_size(int t, int *a)
+int type_size(CType *type, int *a)
{
Sym *s;
int bt;
- bt = t & VT_BTYPE;
+ bt = type->t & VT_BTYPE;
if (bt == VT_STRUCT) {
/* struct/union */
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
+ s = type->ref;
*a = 4; /* XXX: cannot store it yet. Doing that is safe */
return s->c;
} else if (bt == VT_PTR) {
- if (t & VT_ARRAY) {
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
- return type_size(s->t, a) * s->c;
+ if (type->t & VT_ARRAY) {
+ s = type->ref;
+ return type_size(&s->type, a) * s->c;
} else {
*a = PTR_SIZE;
return PTR_SIZE;
@@ -4487,52 +4553,50 @@ int type_size(int t, int *a)
}
/* return the pointed type of t */
-int pointed_type(int t)
+static inline CType *pointed_type(CType *type)
{
- Sym *s;
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
- return s->t | (t & ~VT_TYPE);
+ return &type->ref->type;
}
-int mk_pointer(int t)
+/* modify type so that its it is a pointer to type. */
+static void mk_pointer(CType *type)
{
- int p;
- p = anon_sym++;
- sym_push(p, t, 0, -1);
- return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
+ Sym *s;
+ s = sym_push(0, type, 0, -1);
+ type->t = VT_PTR | (type->t & ~VT_TYPE);
+ type->ref = s;
}
-int is_compatible_types(int t1, int t2)
+static int is_compatible_types(CType *type1, CType *type2)
{
Sym *s1, *s2;
- int bt1, bt2;
+ int bt1, bt2, t1, t2;
- t1 &= VT_TYPE;
- t2 &= VT_TYPE;
+ t1 = type1->t & VT_TYPE;
+ t2 = type2->t & VT_TYPE;
bt1 = t1 & VT_BTYPE;
bt2 = t2 & VT_BTYPE;
if (bt1 == VT_PTR) {
- t1 = pointed_type(t1);
+ type1 = pointed_type(type1);
/* if function, then convert implicitely to function pointer */
if (bt2 != VT_FUNC) {
if (bt2 != VT_PTR)
return 0;
- t2 = pointed_type(t2);
+ type2 = pointed_type(type2);
}
/* void matches everything */
- t1 &= VT_TYPE;
- t2 &= VT_TYPE;
- if (t1 == VT_VOID || t2 == VT_VOID)
+ /* XXX: not fully compliant */
+ if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
return 1;
- return is_compatible_types(t1, t2);
+ return is_compatible_types(type1, type2);
} else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
return (t2 == t1);
} else if (bt1 == VT_FUNC) {
if (bt2 != VT_FUNC)
return 0;
- s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
- s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
- if (!is_compatible_types(s1->t, s2->t))
+ s1 = type1->ref;
+ s2 = type2->ref;
+ if (!is_compatible_types(&s1->type, &s2->type))
return 0;
/* XXX: not complete */
if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
@@ -4542,7 +4606,7 @@ int is_compatible_types(int t1, int t2)
while (s1 != NULL) {
if (s2 == NULL)
return 0;
- if (!is_compatible_types(s1->t, s2->t))
+ if (!is_compatible_types(&s1->type, &s2->type))
return 0;
s1 = s1->next;
s2 = s2->next;
@@ -4561,14 +4625,14 @@ int is_compatible_types(int t1, int t2)
/* XXX: union */
/* XXX: add array and function pointers */
void type_to_str(char *buf, int buf_size,
- int t, const char *varstr)
+ CType *type, const char *varstr)
{
- int bt, v;
+ int bt, v, t;
Sym *s, *sa;
char buf1[256];
const char *tstr;
- t = t & VT_TYPE;
+ t = type->t & VT_TYPE;
bt = t & VT_BTYPE;
buf[0] = '\0';
if (t & VT_UNSIGNED)
@@ -4613,19 +4677,19 @@ void type_to_str(char *buf, int buf_size,
else
tstr = "enum ";
pstrcat(buf, buf_size, tstr);
- v = (unsigned)t >> VT_STRUCT_SHIFT;
+ v = type->ref->v;
if (v >= SYM_FIRST_ANOM)
pstrcat(buf, buf_size, "<anonymous>");
else
pstrcat(buf, buf_size, get_tok_str(v, NULL));
break;
case VT_FUNC:
- s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
- type_to_str(buf, buf_size, s->t, varstr);
+ s = type->ref;
+ type_to_str(buf, buf_size, &s->type, varstr);
pstrcat(buf, buf_size, "(");
sa = s->next;
while (sa != NULL) {
- type_to_str(buf1, sizeof(buf1), sa->t, NULL);
+ type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
pstrcat(buf, buf_size, buf1);
sa = sa->next;
if (sa)
@@ -4634,11 +4698,11 @@ void type_to_str(char *buf, int buf_size,
pstrcat(buf, buf_size, ")");
goto no_var;
case VT_PTR:
- s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
+ s = type->ref;
pstrcpy(buf1, sizeof(buf1), "*");
if (varstr)
pstrcat(buf1, sizeof(buf1), varstr);
- type_to_str(buf, buf_size, s->t, buf1);
+ type_to_str(buf, buf_size, &s->type, buf1);
goto no_var;
}
if (varstr) {
@@ -4650,23 +4714,23 @@ void type_to_str(char *buf, int buf_size,
/* verify type compatibility to store vtop in 'dt' type, and generate
casts if needed. */
-void gen_assign_cast(int dt)
+void gen_assign_cast(CType *dt)
{
- int st;
+ CType *st;
char buf1[256], buf2[256];
- st = vtop->t; /* source type */
- if ((dt & VT_BTYPE) == VT_PTR) {
+ st = &vtop->type; /* source type */
+ if ((dt->t & VT_BTYPE) == VT_PTR) {
/* special cases for pointers */
/* a function is implicitely a function pointer */
- if ((st & VT_BTYPE) == VT_FUNC) {
+ if ((st->t & VT_BTYPE) == VT_FUNC) {
if (!is_compatible_types(pointed_type(dt), st))
goto error;
else
goto type_ok;
}
/* '0' can also be a pointer */
- if ((st & VT_BTYPE) == VT_INT &&
+ if ((st->t & VT_BTYPE) == VT_INT &&
((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
vtop->c.i == 0)
goto type_ok;
@@ -4687,17 +4751,17 @@ void vstore(void)
int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
GFuncContext gf;
- ft = vtop[-1].t;
- sbt = vtop->t & VT_BTYPE;
+ ft = vtop[-1].type.t;
+ sbt = vtop->type.t & VT_BTYPE;
dbt = ft & VT_BTYPE;
if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
(sbt == VT_INT && dbt == VT_SHORT)) {
/* optimize char/short casts */
delayed_cast = VT_MUSTCAST;
- vtop->t = ft & VT_TYPE;
+ vtop->type.t = ft & VT_TYPE;
} else {
delayed_cast = 0;
- gen_assign_cast(ft & VT_TYPE);
+ gen_assign_cast(&vtop[-1].type);
}
if (sbt == VT_STRUCT) {
@@ -4708,21 +4772,21 @@ void vstore(void)
vdup();
gfunc_start(&gf, FUNC_CDECL);
/* type size */
- size = type_size(vtop->t, &align);
+ size = type_size(&vtop->type, &align);
vpushi(size);
gfunc_param(&gf);
/* source */
- vtop->t = VT_INT;
+ vtop->type.t = VT_INT;
gaddrof();
gfunc_param(&gf);
/* destination */
vswap();
- vtop->t = VT_INT;
+ 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);
} else {
vswap();
@@ -4734,7 +4798,7 @@ void vstore(void)
bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
/* remove bit field info to avoid loops */
- vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
+ vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
/* duplicate destination */
vdup();
@@ -4770,7 +4834,7 @@ void vstore(void)
if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
SValue sv;
t = get_reg(RC_INT);
- sv.t = VT_INT;
+ sv.type.t = VT_INT;
sv.r = VT_LOCAL | VT_LVAL;
sv.c.ul = vtop[-1].c.ul;
load(t, &sv);
@@ -4781,7 +4845,7 @@ void vstore(void)
if ((ft & VT_BTYPE) == VT_LLONG) {
vswap();
/* convert to int to increment easily */
- vtop->t = VT_INT;
+ vtop->type.t = VT_INT;
gaddrof();
vpushi(4);
gen_op('+');
@@ -4892,13 +4956,14 @@ void parse_attribute(AttributeDef *ad)
skip(')');
}
-/* enum/struct/union declaration */
-int struct_decl(int u)
+/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
+static void struct_decl(CType *type, int u)
{
- int a, t, b, v, size, align, maxalign, c, offset;
+ int a, v, size, align, maxalign, c, offset;
int bit_size, bit_pos, bsize, bt, lbit_pos;
Sym *s, *ss, **ps;
AttributeDef ad;
+ CType type1, btype;
a = tok; /* save decl type */
next();
@@ -4909,17 +4974,19 @@ int struct_decl(int u)
/* XXX: check consistency */
s = sym_find(v | SYM_STRUCT);
if (s) {
- if (s->t != a)
+ if (s->type.t != a)
error("invalid type");
goto do_decl;
}
} else {
v = anon_sym++;
}
- s = sym_push(v | SYM_STRUCT, a, 0, 0);
+ type1.t = a;
+ s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
/* put struct/union/enum name in type */
do_decl:
- u = u | (v << VT_STRUCT_SHIFT);
+ type->t = u;
+ type->ref = s;
if (tok == '{') {
next();
@@ -4940,23 +5007,23 @@ int struct_decl(int u)
c = expr_const();
}
/* enum symbols have static storage */
- sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
+ ss = sym_push(v, &int_type, VT_CONST, c);
+ ss->type.t |= VT_STATIC;
if (tok == ',')
next();
c++;
} else {
- parse_btype(&b, &ad);
+ parse_btype(&btype, &ad);
while (1) {
bit_size = -1;
v = 0;
+ type1 = btype;
if (tok != ':') {
- t = type_decl(&ad, &v, b, TYPE_DIRECT);
- if ((t & VT_BTYPE) == VT_FUNC ||
- (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
+ type_decl(&type1, &ad, &v, TYPE_DIRECT);
+ if ((type1.t & VT_BTYPE) == VT_FUNC ||
+ (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
error("invalid type for '%s'",
get_tok_str(v, NULL));
- } else {
- t = b;
}
if (tok == ':') {
next();
@@ -4969,10 +5036,10 @@ int struct_decl(int u)
error("zero width for bit-field '%s'",
get_tok_str(v, NULL));
}
- size = type_size(t, &align);
+ size = type_size(&type1, &align);
lbit_pos = 0;
if (bit_size >= 0) {
- bt = t & VT_BTYPE;
+ bt = type1.t & VT_BTYPE;
if (bt != VT_INT &&
bt != VT_BYTE &&
bt != VT_SHORT)
@@ -4996,7 +5063,7 @@ int struct_decl(int u)
bit_pos = 0;
lbit_pos = bit_pos;
/* XXX: handle LSB first */
- t |= VT_BITFIELD |
+ type1.t |= VT_BITFIELD |
(bit_pos << VT_STRUCT_SHIFT) |
(bit_size << (VT_STRUCT_SHIFT + 6));
bit_pos += bit_size;
@@ -5023,14 +5090,14 @@ int struct_decl(int u)
#if 0
printf("add field %s offset=%d",
get_tok_str(v, NULL), offset);
- if (t & VT_BITFIELD) {
+ if (type1.t & VT_BITFIELD) {
printf(" pos=%d size=%d",
- (t >> VT_STRUCT_SHIFT) & 0x3f,
- (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
+ (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
+ (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
}
printf("\n");
#endif
- ss = sym_push(v | SYM_FIELD, t, 0, offset);
+ ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
*ps = ss;
ps = &ss->next;
}
@@ -5047,16 +5114,16 @@ int struct_decl(int u)
/* size for struct/union, dummy for enum */
s->c = (c + maxalign - 1) & -maxalign;
}
- return u;
}
/* return 0 if no type declaration. otherwise, return the basic type
and skip it.
*/
-int parse_btype(int *type_ptr, AttributeDef *ad)
+static int parse_btype(CType *type, AttributeDef *ad)
{
int t, u, type_found;
Sym *s;
+ CType type1;
memset(ad, 0, sizeof(AttributeDef));
type_found = 0;
@@ -5109,12 +5176,15 @@ int parse_btype(int *type_ptr, AttributeDef *ad)
}
break;
case TOK_ENUM:
- u = struct_decl(VT_ENUM);
+ struct_decl(&type1, VT_ENUM);
+ basic_type2:
+ u = type1.t;
+ type->ref = type1.ref;
goto basic_type1;
case TOK_STRUCT:
case TOK_UNION:
- u = struct_decl(VT_STRUCT);
- goto basic_type1;
+ struct_decl(&type1, VT_STRUCT);
+ goto basic_type2;
/* type modifiers */
case TOK_CONST:
@@ -5153,13 +5223,14 @@ int parse_btype(int *type_ptr, AttributeDef *ad)
/* GNUC typeof */
case TOK_TYPEOF:
next();
- u = parse_expr_type();
- goto basic_type1;
+ parse_expr_type(&type1);
+ goto basic_type2;
default:
s = sym_find(tok);
- if (!s || !(s->t & VT_TYPEDEF))
+ if (!s || !(s->type.t & VT_TYPEDEF))
goto the_end;
- t |= (s->t & ~VT_TYPEDEF);
+ t |= (s->type.t & ~VT_TYPEDEF);
+ type->ref = s->type.ref;
next();
break;
}
@@ -5169,15 +5240,16 @@ the_end:
/* long is never used as type */
if ((t & VT_BTYPE) == VT_LONG)
t = (t & ~VT_BTYPE) | VT_INT;
- *type_ptr = t;
+ type->t = t;
return type_found;
}
-int post_type(int t, AttributeDef *ad)
+static void post_type(CType *type, AttributeDef *ad)
{
- int p, n, pt, l, t1;
+ int n, l, t1;
Sym **plast, *s, *first;
AttributeDef ad1;
+ CType pt;
if (tok == '(') {
/* function declaration */
@@ -5197,20 +5269,20 @@ int post_type(int t, AttributeDef *ad)
}
}
l = FUNC_NEW;
- if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
+ if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
break;
- pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
- if ((pt & VT_BTYPE) == VT_VOID)
+ type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
+ if ((pt.t & VT_BTYPE) == VT_VOID)
error("parameter declared as void");
} else {
old_proto:
n = tok;
- pt = VT_INT;
+ pt.t = VT_INT;
next();
}
/* array must be transformed to pointer according to ANSI C */
- pt &= ~VT_ARRAY;
- s = sym_push(n | SYM_FIELD, pt, 0, 0);
+ pt.t &= ~VT_ARRAY;
+ s = sym_push(n | SYM_FIELD, &pt, 0, 0);
*plast = s;
plast = &s->next;
if (tok == ',') {
@@ -5226,13 +5298,14 @@ int post_type(int t, AttributeDef *ad)
if (l == 0)
l = FUNC_OLD;
skip(')');
- t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
- t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
+ t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
+ type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
+ post_type(type, ad);
/* we push a anonymous symbol which will contain the function prototype */
- p = anon_sym++;
- s = sym_push(p, t, ad->func_call, l);
+ s = sym_push(0, type, ad->func_call, l);
s->next = first;
- t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
+ type->t = t1 | VT_FUNC;
+ type->ref = s;
} else if (tok == '[') {
/* array definition */
next();
@@ -5244,46 +5317,48 @@ int post_type(int t, AttributeDef *ad)
}
skip(']');
/* parse next post type */
- t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
- t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
+ t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
+ type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
+ post_type(type, ad);
/* we push a anonymous symbol which will contain the array
element type */
- p = anon_sym++;
- sym_push(p, t, 0, n);
- t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
+ s = sym_push(0, type, 0, n);
+ type->t = t1 | VT_ARRAY | VT_PTR;
+ type->ref = s;
}
- return t;
}
-/* Read a type declaration (except basic type), and return the
- type. 'td' is a bitmask indicating which kind of type decl is
- expected. 't' should contain the basic type. 'ad' is the attribute
- definition of the basic type. It can be modified by type_decl(). */
-int type_decl(AttributeDef *ad, int *v, int t, int td)
+/* Parse a type declaration (except basic type), and return the type
+ in 'type'. 'td' is a bitmask indicating which kind of type decl is
+ expected. 'type' should contain the basic type. 'ad' is the
+ attribute definition of the basic type. It can be modified by
+ type_decl().
+ */
+static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
{
- int u, p;
Sym *s;
+ CType type1, *type2;
while (tok == '*') {
next();
while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
next();
- t = mk_pointer(t);
+ mk_pointer(type);
}
/* recursive type */
/* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
+ type1.t = 0; /* XXX: same as int */
if (tok == '(') {
next();
/* XXX: this is not correct to modify 'ad' at this point, but
the syntax is not clear */
if (tok == TOK___ATTRIBUTE__)
parse_attribute(ad);
- u = type_decl(ad, v, 0, td);
+ type_decl(&type1, ad, v, td);
skip(')');
} else {
- u = 0;
/* type identifier */
if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
*v = tok;
@@ -5294,22 +5369,22 @@ int type_decl(AttributeDef *ad, int *v, int t, int td)
*v = 0;
}
}
- /* append t at the end of u */
- t = post_type(t, ad);
+ post_type(type, ad);
if (tok == TOK___ATTRIBUTE__)
parse_attribute(ad);
- if (!u)
- return t;
- p = u;
- while(1) {
- s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
- p = s->t;
- if (!p) {
- s->t = t;
+ if (!type1.t)
+ return;
+ /* append type at the end of type1 */
+ type2 = &type1;
+ for(;;) {
+ s = type2->ref;
+ type2 = &s->type;
+ if (!type2->t) {
+ *type2 = *type;
break;
}
}
- return u;
+ *type = type1;
}
/* compute the lvalue VT_LVAL_xxx needed to match type t. */
@@ -5332,14 +5407,14 @@ static int lvalue_type(int t)
/* indirection with full error checking and bound check */
static void indir(void)
{
- if ((vtop->t & VT_BTYPE) != VT_PTR)
+ if ((vtop->type.t & VT_BTYPE) != VT_PTR)
expect("pointer");
if ((vtop->r & VT_LVAL) && !nocode_wanted)
gv(RC_INT);
- vtop->t = pointed_type(vtop->t);
+ vtop->type = *pointed_type(&vtop->type);
/* an array is never an lvalue */
- if (!(vtop->t & VT_ARRAY)) {
- vtop->r |= lvalue_type(vtop->t);
+ if (!(vtop->type.t & VT_ARRAY)) {
+ vtop->r |= lvalue_type(vtop->type.t);
/* if bound checking, the referenced pointer must be checked */
if (do_bounds_check)
vtop->r |= VT_MUSTBOUND;
@@ -5350,16 +5425,20 @@ static void indir(void)
void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
{
int func_type;
+ CType type;
+
func_type = func->c;
if (func_type == FUNC_OLD ||
(func_type == FUNC_ELLIPSIS && arg == NULL)) {
/* default casting : only need to convert float to double */
- if ((vtop->t & VT_BTYPE) == VT_FLOAT)
- gen_cast(VT_DOUBLE);
+ if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
+ type.t = VT_DOUBLE;
+ gen_cast(&type);
+ }
} else if (arg == NULL) {
error("too many arguments to function");
} else {
- gen_assign_cast(arg->t);
+ gen_assign_cast(&arg->type);
}
if (!nocode_wanted) {
gfunc_param(gf);
@@ -5370,24 +5449,31 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
/* parse an expression of the form '(type)' or '(expr)' and return its
type */
-static int parse_expr_type(void)
+static void parse_expr_type(CType *type)
{
- int ft, n;
+ int n;
AttributeDef ad;
skip('(');
- if (parse_btype(&ft, &ad)) {
- ft = type_decl(&ad, &n, ft, TYPE_ABSTRACT);
+ if (parse_btype(type, &ad)) {
+ type_decl(type, &ad, &n, TYPE_ABSTRACT);
} else {
- ft = expr_type();
+ expr_type(type);
}
skip(')');
- return ft;
+}
+
+static void vpush_tokc(int t)
+{
+ CType type;
+ type.t = t;
+ vsetc(&type, VT_CONST, &tokc);
}
static void unary(void)
{
- int n, t, ft, align, size, r;
+ int n, t, align, size, r;
+ CType type;
Sym *s;
GFuncContext gf;
AttributeDef ad;
@@ -5396,22 +5482,22 @@ static void unary(void)
vpushi(tokc.i);
next();
} else if (tok == TOK_CUINT) {
- vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
+ vpush_tokc(VT_INT | VT_UNSIGNED);
next();
} else if (tok == TOK_CLLONG) {
- vsetc(VT_LLONG, VT_CONST, &tokc);
+ vpush_tokc(VT_LLONG);
next();
} else if (tok == TOK_CULLONG) {
- vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
+ vpush_tokc(VT_LLONG | VT_UNSIGNED);
next();
} else if (tok == TOK_CFLOAT) {
- vsetc(VT_FLOAT, VT_CONST, &tokc);
+ vpush_tokc(VT_FLOAT);
next();
} else if (tok == TOK_CDOUBLE) {
- vsetc(VT_DOUBLE, VT_CONST, &tokc);
+ vpush_tokc(VT_DOUBLE);
next();
} else if (tok == TOK_CLDOUBLE) {
- vsetc(VT_LDOUBLE, VT_CONST, &tokc);
+ vpush_tokc(VT_LDOUBLE);
next();
} else if (tok == TOK___FUNC__ || (tok == TOK___FUNCTION__ && gnu_ext)) {
void *ptr;
@@ -5420,10 +5506,11 @@ static void unary(void)
len = strlen(funcname) + 1;
/* generate char[len] type */
- t = VT_ARRAY | mk_pointer(VT_BYTE);
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
- s->c = len;
- vpush_ref(t, data_section, data_section->data_offset, len);
+ type.t = VT_BYTE;
+ mk_pointer(&type);
+ type.t |= VT_ARRAY;
+ type.ref->c = len;
+ vpush_ref(&type, data_section, data_section->data_offset, len);
ptr = section_ptr_add(data_section, len);
memcpy(ptr, funcname, len);
next();
@@ -5434,16 +5521,18 @@ static void unary(void)
/* string parsing */
t = VT_BYTE;
str_init:
- t = VT_ARRAY | mk_pointer(t);
+ type.t = t;
+ mk_pointer(&type);
+ type.t |= VT_ARRAY;
memset(&ad, 0, sizeof(AttributeDef));
- decl_initializer_alloc(t, &ad, VT_CONST, 2, 0, 0);
+ decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
} else {
t = tok;
next();
if (t == '(') {
/* cast ? */
- if (parse_btype(&t, &ad)) {
- ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
+ if (parse_btype(&type, &ad)) {
+ type_decl(&type, &ad, &n, TYPE_ABSTRACT);
skip(')');
/* check ISOC99 compound literal */
if (tok == '{') {
@@ -5453,13 +5542,13 @@ static void unary(void)
else
r = VT_LOCAL;
/* all except arrays are lvalues */
- if (!(ft & VT_ARRAY))
- r |= lvalue_type(ft);
+ if (!(type.t & VT_ARRAY))
+ r |= lvalue_type(type.t);
memset(&ad, 0, sizeof(AttributeDef));
- decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
+ decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
} else {
unary();
- gen_cast(ft);
+ gen_cast(&type);
}
} else {
gexpr();
@@ -5475,10 +5564,10 @@ static void unary(void)
functions are not lvalues, we only have to handle it
there and in function calls. */
/* arrays can also be used although they are not lvalues */
- if ((vtop->t & VT_BTYPE) != VT_FUNC &&
- !(vtop->t & VT_ARRAY))
+ if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
+ !(vtop->type.t & VT_ARRAY))
test_lvalue();
- vtop->t = mk_pointer(vtop->t);
+ mk_pointer(&vtop->type);
gaddrof();
} else if (t == '!') {
unary();
@@ -5487,7 +5576,7 @@ static void unary(void)
else if ((vtop->r & VT_VALMASK) == VT_CMP)
vtop->c.i = vtop->c.i ^ 1;
else
- vset(VT_INT, VT_JMP, gtst(1, 0));
+ vseti(VT_JMP, gtst(1, 0));
} else if (t == '~') {
unary();
vpushi(-1);
@@ -5495,17 +5584,17 @@ static void unary(void)
} else if (t == '+') {
/* in order to force cast, we add zero */
unary();
- if ((vtop->t & VT_BTYPE) == VT_PTR)
+ if ((vtop->type.t & VT_BTYPE) == VT_PTR)
error("pointer not accepted for unary plus");
vpushi(0);
gen_op('+');
} else if (t == TOK_SIZEOF || t == TOK_ALIGNOF) {
if (tok == '(') {
- ft = parse_expr_type();
+ parse_expr_type(&type);
} else {
- ft = unary_type();
+ unary_type(&type);
}
- size = type_size(ft, &align);
+ size = type_size(&type, &align);
if (t == TOK_SIZEOF)
vpushi(size);
else
@@ -5526,9 +5615,12 @@ static void unary(void)
s = sym_push1(&label_stack, tok, 0, 0);
s->r = LABEL_FORWARD;
}
- if (!s->t)
- s->t = mk_pointer(VT_VOID) | VT_STATIC;
- vset(s->t, VT_CONST | VT_SYM, 0);
+ if (!s->type.t) {
+ s->type.t = VT_VOID;
+ mk_pointer(&s->type);
+ s->type.t |= VT_STATIC;
+ }
+ vset(&s->type, VT_CONST | VT_SYM, 0);
vtop->sym = s;
next();
} else {
@@ -5540,9 +5632,9 @@ static void unary(void)
error("'%s' undeclared", get_tok_str(t, NULL));
/* for simple function calls, we tolerate undeclared
external reference to int() function */
- s = external_global_sym(t, func_old_type, 0);
+ s = external_global_sym(t, &func_old_type, 0);
}
- vset(s->t, s->r, s->c);
+ vset(&s->type, s->r, s->c);
/* if forward reference, we must point to s */
if (vtop->r & VT_SYM) {
vtop->sym = s;
@@ -5564,9 +5656,9 @@ static void unary(void)
gaddrof();
next();
/* expect pointer on structure */
- if ((vtop->t & VT_BTYPE) != VT_STRUCT)
+ if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
expect("struct or union");
- s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
+ s = vtop->type.ref;
/* find field */
tok |= SYM_FIELD;
while ((s = s->next) != NULL) {
@@ -5576,14 +5668,14 @@ static void unary(void)
if (!s)
error("field not found");
/* add field offset to pointer */
- vtop->t = char_pointer_type; /* change type to 'char *' */
+ vtop->type = char_pointer_type; /* change type to 'char *' */
vpushi(s->c);
gen_op('+');
/* change type to field type, and set to lvalue */
- vtop->t = s->t;
+ vtop->type = s->type;
/* an array is never an lvalue */
- if (!(vtop->t & VT_ARRAY)) {
- vtop->r |= lvalue_type(vtop->t);
+ if (!(vtop->type.t & VT_ARRAY)) {
+ vtop->r |= lvalue_type(vtop->type.t);
/* if bound checking, the referenced pointer must be checked */
if (do_bounds_check)
vtop->r |= VT_MUSTBOUND;
@@ -5600,11 +5692,11 @@ static void unary(void)
Sym *sa;
/* function call */
- if ((vtop->t & VT_BTYPE) != VT_FUNC) {
+ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
/* pointer test (no array accepted) */
- if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
- vtop->t = pointed_type(vtop->t);
- if ((vtop->t & VT_BTYPE) != VT_FUNC)
+ if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
+ vtop->type = *pointed_type(&vtop->type);
+ if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
goto error_func;
} else {
error_func:
@@ -5614,7 +5706,7 @@ static void unary(void)
vtop->r &= ~VT_LVAL; /* no lvalue */
}
/* get return type */
- s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
+ s = vtop->type.ref;
if (!nocode_wanted) {
save_regs(0); /* save used temporary registers */
gfunc_start(&gf, s->r);
@@ -5673,28 +5765,28 @@ static void unary(void)
}
#endif
/* compute first implicit argument if a structure is returned */
- if ((s->t & VT_BTYPE) == VT_STRUCT) {
+ if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
/* get some space for the returned structure */
- size = type_size(s->t, &align);
+ size = type_size(&s->type, &align);
loc = (loc - size) & -align;
- ret.t = s->t;
+ ret.type = s->type;
ret.r = VT_LOCAL | VT_LVAL;
/* pass it as 'int' to avoid structure arg passing
problems */
- vset(VT_INT, VT_LOCAL, loc);
+ vseti(VT_LOCAL, loc);
ret.c = vtop->c;
if (!nocode_wanted)
gfunc_param(&gf);
else
vtop--;
} else {
- ret.t = s->t;
+ ret.type = s->type;
ret.r2 = VT_CONST;
/* return in register */
- if (is_float(ret.t)) {
+ if (is_float(ret.type.t)) {
ret.r = REG_FRET;
} else {
- if ((ret.t & VT_BTYPE) == VT_LLONG)
+ if ((ret.type.t & VT_BTYPE) == VT_LLONG)
ret.r2 = REG_LRET;
ret.r = REG_IRET;
}
@@ -5721,7 +5813,7 @@ static void unary(void)
else
vtop--;
/* return value */
- vsetc(ret.t, ret.r, &ret.c);
+ vsetc(&ret.type, ret.r, &ret.c);
vtop->r2 = ret.r2;
} else {
break;
@@ -5790,7 +5882,7 @@ static void eand(void)
if (tok != TOK_LAND) {
if (t) {
t = gtst(1, t);
- vset(VT_INT, VT_JMPI, t);
+ vseti(VT_JMPI, t);
}
break;
}
@@ -5810,7 +5902,7 @@ static void eor(void)
if (tok != TOK_LOR) {
if (t) {
t = gtst(0, t);
- vset(VT_INT, VT_JMP, t);
+ vseti(VT_JMP, t);
}
break;
}
@@ -5823,8 +5915,9 @@ static void eor(void)
/* XXX: better constant handling */
static void expr_eq(void)
{
- int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
+ int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
SValue sv;
+ CType type, type1, type2;
if (const_wanted) {
int c1, c;
@@ -5849,8 +5942,7 @@ static void expr_eq(void)
at the top because it is a branch point */
tt = gtst(1, 0);
gexpr();
- t1 = vtop->t;
- bt1 = t1 & VT_BTYPE;
+ type1 = vtop->type;
sv = *vtop; /* save value to handle it later */
vtop--; /* no vpop so that FP stack is not flushed */
skip(':');
@@ -5858,49 +5950,52 @@ static void expr_eq(void)
gsym(tt);
expr_eq();
- t2 = vtop->t;
+ type2 = vtop->type;
+ t1 = type1.t;
+ bt1 = t1 & VT_BTYPE;
+ t2 = type2.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;
+ type.t = VT_LDOUBLE;
} else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
- t = VT_DOUBLE;
+ type.t = VT_DOUBLE;
} else {
- t = VT_FLOAT;
+ type.t = VT_FLOAT;
}
} else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
/* cast to biggest op */
- t = VT_LLONG;
+ type.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;
+ type.t |= VT_UNSIGNED;
} else if (bt1 == VT_PTR || bt2 == VT_PTR) {
/* XXX: test pointer compatibility */
- t = t1;
+ type = type1;
} else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
/* XXX: test structure compatibility */
- t = t1;
+ type = type1;
} else if (bt1 == VT_VOID || bt2 == VT_VOID) {
/* NOTE: as an extension, we accept void on only one side */
- t = VT_VOID;
+ type.t = VT_VOID;
} else {
/* integer operations */
- t = VT_INT;
+ type.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;
+ type.t |= VT_UNSIGNED;
}
/* now we convert second operand */
- gen_cast(t);
+ gen_cast(&type);
rc = RC_INT;
- if (is_float(t)) {
+ if (is_float(type.t)) {
rc = RC_FLOAT;
- } else if ((t & VT_BTYPE) == VT_LLONG) {
+ } else if ((type.t & VT_BTYPE) == VT_LLONG) {
/* for long longs, we use fixed registers to avoid having
to handle a complicated move */
rc = RC_IRET;
@@ -5912,7 +6007,7 @@ static void expr_eq(void)
gsym(u);
/* put again first value and cast it */
*vtop = sv;
- gen_cast(t);
+ gen_cast(&type);
r1 = gv(rc);
move_reg(r2, r1);
vtop->r = r2;
@@ -5933,32 +6028,30 @@ static void gexpr(void)
}
/* parse an expression and return its type without any side effect. */
-static int expr_type(void)
+static void expr_type(CType *type)
{
- int a, t;
+ int a;
a = nocode_wanted;
nocode_wanted = 1;
gexpr();
- t = vtop->t;
+ *type = vtop->type;
vpop();
nocode_wanted = a;
- return t;
}
/* parse a unary expression and return its type without any side
effect. */
-static int unary_type(void)
+static void unary_type(CType *type)
{
- int a, t;
+ int a;
a = nocode_wanted;
nocode_wanted = 1;
unary();
- t = vtop->t;
+ *type = vtop->type;
vpop();
nocode_wanted = a;
- return t;
}
/* parse a constant expression and return value in vtop. */
@@ -6068,16 +6161,19 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re
next();
if (tok != ';') {
gexpr();
- gen_assign_cast(func_vt);
- if ((func_vt & VT_BTYPE) == VT_STRUCT) {
+ gen_assign_cast(&func_vt);
+ if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
+ CType type;
/* if returning structure, must copy it to implicit
first pointer arg location */
- vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
+ type = func_vt;
+ mk_pointer(&type);
+ vset(&type, VT_LOCAL | VT_LVAL, func_vc);
indir();
vswap();
/* copy structure value to pointer */
vstore();
- } else if (is_float(func_vt)) {
+ } else if (is_float(func_vt.t)) {
gv(RC_FRET);
} else {
gv(RC_IRET);
@@ -6184,7 +6280,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re
/* since a case is like a label, we must skip it with a jmp */
b = gjmp(0);
gsym(*case_sym);
- vset(VT_INT, case_reg, 0);
+ vseti(case_reg, 0);
vpushi(v1);
if (v1 == v2) {
gen_op(TOK_EQ);
@@ -6192,7 +6288,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re
} else {
gen_op(TOK_GE);
*case_sym = gtst(1, 0);
- vset(VT_INT, case_reg, 0);
+ vseti(case_reg, 0);
vpushi(v2);
gen_op(TOK_LE);
*case_sym = gtst(1, *case_sym);
@@ -6217,7 +6313,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re
/* computed goto */
next();
gexpr();
- if ((vtop->t & VT_BTYPE) != VT_PTR)
+ if ((vtop->type.t & VT_BTYPE) != VT_PTR)
expect("pointer");
ggoto();
} else if (tok >= TOK_UIDENT) {
@@ -6271,12 +6367,13 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re
address. cur_index/cur_field is the pointer to the current
value. 'size_only' is true if only size info is needed (only used
in arrays) */
-static void decl_designator(int t, Section *sec, unsigned long c,
+static void decl_designator(CType *type, Section *sec, unsigned long c,
int *cur_index, Sym **cur_field,
int size_only)
{
Sym *s, *f;
int notfirst, index, align, l;
+ CType type1;
notfirst = 0;
if (gnu_ext && (l = is_label()) != 0)
@@ -6284,9 +6381,9 @@ static void decl_designator(int t, Section *sec, unsigned long c,
while (tok == '[' || tok == '.') {
if (tok == '[') {
- if (!(t & VT_ARRAY))
+ if (!(type->t & VT_ARRAY))
expect("array type");
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
+ s = type->ref;
next();
index = expr_const();
if (index < 0 || (s->c >= 0 && index >= s->c))
@@ -6294,16 +6391,16 @@ static void decl_designator(int t, Section *sec, unsigned long c,
skip(']');
if (!notfirst)
*cur_index = index;
- t = pointed_type(t);
- c += index * type_size(t, &align);
+ type = pointed_type(type);
+ c += index * type_size(type, &align);
} else {
next();
l = tok;
next();
struct_field:
- if ((t & VT_BTYPE) != VT_STRUCT)
+ if ((type->t & VT_BTYPE) != VT_STRUCT)
expect("struct/union type");
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
+ s = type->ref;
l |= SYM_FIELD;
f = s->next;
while (f) {
@@ -6315,7 +6412,10 @@ static void decl_designator(int t, Section *sec, unsigned long c,
expect("field");
if (!notfirst)
*cur_field = f;
- t = f->t | (t & ~VT_TYPE);
+ /* XXX: suppress this mess by using explicit storage field */
+ type1 = f->type;
+ type1.t |= (type->t & ~VT_TYPE);
+ type = &type1;
c += f->c;
}
notfirst = 1;
@@ -6328,19 +6428,22 @@ static void decl_designator(int t, Section *sec, unsigned long c,
expect("=");
}
} else {
- if (t & VT_ARRAY) {
+ if (type->t & VT_ARRAY) {
index = *cur_index;
- t = pointed_type(t);
- c += index * type_size(t, &align);
+ type = pointed_type(type);
+ c += index * type_size(type, &align);
} else {
f = *cur_field;
if (!f)
error("too many field init");
- t = f->t | (t & ~VT_TYPE);
+ /* XXX: suppress this mess by using explicit storage field */
+ type1 = f->type;
+ type1.t |= (type->t & ~VT_TYPE);
+ type = &type1;
c += f->c;
}
}
- decl_initializer(t, sec, c, 0, size_only);
+ decl_initializer(type, sec, c, 0, size_only);
}
#define EXPR_VAL 0
@@ -6348,7 +6451,7 @@ static void decl_designator(int t, Section *sec, unsigned long c,
#define EXPR_ANY 2
/* store a value or an expression directly in global data or in local array */
-static void init_putv(int t, Section *sec, unsigned long c,
+static void init_putv(CType *type, Section *sec, unsigned long c,
int v, int expr_type)
{
int saved_global_expr, bt;
@@ -6376,8 +6479,8 @@ static void init_putv(int t, Section *sec, unsigned long c,
if (sec) {
/* XXX: not portable */
/* XXX: generate error if incorrect relocation */
- gen_assign_cast(t);
- bt = t & VT_BTYPE;
+ gen_assign_cast(type);
+ bt = type->t & VT_BTYPE;
ptr = sec->data + c;
if ((vtop->r & VT_SYM) &&
(bt == VT_BYTE ||
@@ -6411,7 +6514,7 @@ static void init_putv(int t, Section *sec, unsigned long c,
}
vtop--;
} else {
- vset(t, VT_LOCAL, c);
+ vset(type, VT_LOCAL, c);
vswap();
vstore();
vpop();
@@ -6419,7 +6522,7 @@ static void init_putv(int t, Section *sec, unsigned long c,
}
/* put zeros for variable based init */
-static void init_putz(int t, Section *sec, unsigned long c, int size)
+static void init_putz(CType *t, Section *sec, unsigned long c, int size)
{
GFuncContext gf;
@@ -6431,9 +6534,9 @@ static void init_putz(int t, Section *sec, unsigned long c, int size)
gfunc_param(&gf);
vpushi(0);
gfunc_param(&gf);
- vset(VT_INT, VT_LOCAL, c);
+ 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);
}
}
@@ -6443,18 +6546,19 @@ static void init_putz(int t, Section *sec, unsigned long c, int size)
allocation. 'first' is true if array '{' must be read (multi
dimension implicit array init handling). 'size_only' is true if
size only evaluation is wanted (only for arrays). */
-static void decl_initializer(int t, Section *sec, unsigned long c,
+static void decl_initializer(CType *type, Section *sec, unsigned long c,
int first, int size_only)
{
int index, array_length, n, no_oblock, nb, parlevel, i;
- int t1, size1, align1, expr_type;
+ int size1, align1, expr_type;
Sym *s, *f;
+ CType *t1;
- if (t & VT_ARRAY) {
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
+ if (type->t & VT_ARRAY) {
+ s = type->ref;
n = s->c;
array_length = 0;
- t1 = pointed_type(t);
+ t1 = pointed_type(type);
size1 = type_size(t1, &align1);
no_oblock = 1;
@@ -6467,9 +6571,9 @@ static void decl_initializer(int t, Section *sec, unsigned long c,
/* only parse strings here if correct type (otherwise: handle
them as ((w)char *) expressions */
if ((tok == TOK_LSTR &&
- (t1 & VT_BTYPE) == VT_INT) ||
+ (t1->t & VT_BTYPE) == VT_INT) ||
(tok == TOK_STR &&
- (t1 & VT_BTYPE) == VT_BYTE)) {
+ (t1->t & VT_BTYPE) == VT_BYTE)) {
while (tok == TOK_STR || tok == TOK_LSTR) {
int cstr_len, ch;
CString *cstr;
@@ -6517,7 +6621,7 @@ static void decl_initializer(int t, Section *sec, unsigned long c,
} else {
index = 0;
while (tok != '}') {
- decl_designator(t, sec, c, &index, NULL, size_only);
+ decl_designator(type, sec, c, &index, NULL, size_only);
if (n >= 0 && index >= n)
error("index too large");
/* must put zero in holes (note that doing it that way
@@ -6549,23 +6653,23 @@ static void decl_initializer(int t, Section *sec, unsigned long c,
/* patch type size if needed */
if (n < 0)
s->c = array_length;
- } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
+ } else if ((type->t & VT_BTYPE) == VT_STRUCT && tok == '{') {
/* XXX: union needs only one init */
next();
- s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
+ s = type->ref;
f = s->next;
array_length = 0;
index = 0;
n = s->c;
while (tok != '}') {
- decl_designator(t, sec, c, NULL, &f, size_only);
+ decl_designator(type, sec, c, NULL, &f, size_only);
/* fill with zero between fields */
index = f->c;
if (!size_only && array_length < index) {
- init_putz(t, sec, c + array_length,
+ init_putz(type, sec, c + array_length,
index - array_length);
}
- index = index + type_size(f->t, &align1);
+ index = index + type_size(&f->type, &align1);
if (index > array_length)
array_length = index;
if (tok == '}')
@@ -6575,13 +6679,13 @@ static void decl_initializer(int t, Section *sec, unsigned long c,
}
/* put zeros at the end */
if (!size_only && array_length < n) {
- init_putz(t, sec, c + array_length,
+ init_putz(type, sec, c + array_length,
n - array_length);
}
skip('}');
} else if (tok == '{') {
next();
- decl_initializer(t, sec, c, first, size_only);
+ decl_initializer(type, sec, c, first, size_only);
skip('}');
} else if (size_only) {
/* just skip expression */
@@ -6600,7 +6704,7 @@ static void decl_initializer(int t, Section *sec, unsigned long c,
expr_type = EXPR_CONST;
if (!sec)
expr_type = EXPR_ANY;
- init_putv(t, sec, c, 0, expr_type);
+ init_putv(type, sec, c, 0, expr_type);
}
}
@@ -6611,7 +6715,7 @@ static void decl_initializer(int t, Section *sec, unsigned long c,
parsed. If 'v' is zero, then a reference to the new object is put
in the value stack. If 'has_init' is 2, a special parsing is done
to handle string constants. */
-static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
+static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
int has_init, int v, int scope)
{
int size, align, addr, data_offset;
@@ -6620,7 +6724,7 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
TokenString init_str;
Section *sec;
- size = type_size(t, &align);
+ size = type_size(type, &align);
/* If unknown size, we must evaluate it before
evaluating initializers because
initializers can generate global data too
@@ -6662,13 +6766,13 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
macro_ptr = init_str.str;
next();
- decl_initializer(t, NULL, 0, 1, 1);
+ decl_initializer(type, NULL, 0, 1, 1);
/* prepare second initializer parsing */
macro_ptr = init_str.str;
next();
/* if still unknown size, error */
- size = type_size(t, &align);
+ size = type_size(type, &align);
if (size < 0)
error("unknown type size");
}
@@ -6677,7 +6781,7 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
align = ad->aligned;
if ((r & VT_VALMASK) == VT_LOCAL) {
sec = NULL;
- if (do_bounds_check && (t & VT_ARRAY))
+ if (do_bounds_check && (type->t & VT_ARRAY))
loc--;
#ifdef TCC_TARGET_IL
/* XXX: ugly patch to allocate local variables for IL, just
@@ -6691,7 +6795,7 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
/* handles bounds */
/* XXX: currently, since we do only one pass, we cannot track
'&' operators, so we add only arrays */
- if (do_bounds_check && (t & VT_ARRAY)) {
+ if (do_bounds_check && (type->t & VT_ARRAY)) {
unsigned long *bounds_ptr;
/* add padding between regions */
loc--;
@@ -6727,10 +6831,10 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
if (!sec) {
if (v) {
/* local variable */
- sym_push(v, t, r, addr);
+ sym_push(v, type, r, addr);
} else {
/* push local reference */
- vset(t, r, addr);
+ vset(type, r, addr);
}
} else {
Sym *sym;
@@ -6741,24 +6845,24 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
sym = sym_find(v);
if (!sym)
goto do_def;
- if (!is_compatible_types(sym->t, t))
+ if (!is_compatible_types(&sym->type, type))
error("incompatible types for redefinition of '%s'",
get_tok_str(v, NULL));
- if (!(sym->t & VT_EXTERN))
+ if (!(sym->type.t & VT_EXTERN))
error("redefinition of '%s'", get_tok_str(v, NULL));
- sym->t &= ~VT_EXTERN;
+ sym->type.t &= ~VT_EXTERN;
} else {
do_def:
- sym = sym_push(v, t, r | VT_SYM, 0);
+ sym = sym_push(v, type, r | VT_SYM, 0);
}
put_extern_sym(sym, sec, addr, size);
} else {
CValue cval;
/* push global reference */
- sym = get_sym_ref(t, sec, addr, size);
+ sym = get_sym_ref(type, sec, addr, size);
cval.ul = 0;
- vsetc(t, VT_CONST | VT_SYM, &cval);
+ vsetc(type, VT_CONST | VT_SYM, &cval);
vtop->sym = sym;
}
@@ -6775,7 +6879,7 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
}
}
if (has_init) {
- decl_initializer(t, sec, addr, 1, 0);
+ decl_initializer(type, sec, addr, 1, 0);
/* restore parse state if needed */
if (init_str.str) {
tok_str_free(init_str.str);
@@ -6791,7 +6895,7 @@ void put_func_debug(Sym *sym)
/* stabs info */
/* XXX: we put here a dummy type */
snprintf(buf, sizeof(buf), "%s:%c1",
- funcname, sym->t & VT_STATIC ? 'f' : 'F');
+ funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
cur_text_section, sym->c);
last_ind = 0;
@@ -6862,19 +6966,22 @@ void analyse_function(void)
static void func_decl_list(Sym *func_sym)
{
AttributeDef ad;
- int b, v, t;
+ int v;
Sym *s;
+ CType btype, type;
+
/* parse each declaration */
while (tok != '{' && tok != ';' && tok != TOK_EOF) {
- if (!parse_btype(&b, &ad))
+ if (!parse_btype(&btype, &ad))
expect("declaration list");
- if (((b & VT_BTYPE) == VT_ENUM ||
- (b & VT_BTYPE) == VT_STRUCT) &&
+ if (((btype.t & VT_BTYPE) == VT_ENUM ||
+ (btype.t & VT_BTYPE) == VT_STRUCT) &&
tok == ';') {
/* we accept no variable after */
} else {
for(;;) {
- t = type_decl(&ad, &v, b, TYPE_DIRECT);
+ type = btype;
+ type_decl(&type, &ad, &v, TYPE_DIRECT);
/* find parameter in function parameter list */
s = func_sym->next;
while (s != NULL) {
@@ -6886,10 +6993,10 @@ static void func_decl_list(Sym *func_sym)
get_tok_str(v, NULL));
found:
/* check that no storage specifier except 'register' was given */
- if (t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
+ if (type.t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
error("storage class specified for '%s'", get_tok_str(v, NULL));
/* we can add the type (NOTE: it could be local to the function) */
- s->t = t;
+ s->type = type;
/* accept other parameters */
if (tok == ',')
next();
@@ -6904,12 +7011,13 @@ static void func_decl_list(Sym *func_sym)
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
static void decl(int l)
{
- int t, b, v, has_init, r;
+ int v, has_init, r;
+ CType type, btype;
Sym *sym;
AttributeDef ad;
while (1) {
- if (!parse_btype(&b, &ad)) {
+ if (!parse_btype(&btype, &ad)) {
/* skip redundant ';' */
/* XXX: find more elegant solution */
if (tok == ';') {
@@ -6920,17 +7028,18 @@ static void decl(int l)
type. Only accepted when defining global data */
if (l == VT_LOCAL || tok < TOK_DEFINE)
break;
- b = VT_INT;
+ btype.t = VT_INT;
}
- if (((b & VT_BTYPE) == VT_ENUM ||
- (b & VT_BTYPE) == VT_STRUCT) &&
+ if (((btype.t & VT_BTYPE) == VT_ENUM ||
+ (btype.t & VT_BTYPE) == VT_STRUCT) &&
tok == ';') {
/* we accept no variable after */
next();
continue;
}
while (1) { /* iterate thru each declaration */
- t = type_decl(&ad, &v, b, TYPE_DIRECT);
+ type = btype;
+ type_decl(&type, &ad, &v, TYPE_DIRECT);
#if 0
{
char buf[500];
@@ -6938,10 +7047,10 @@ static void decl(int l)
printf("type = '%s'\n", buf);
}
#endif
- if ((t & VT_BTYPE) == VT_FUNC) {
+ if ((type.t & VT_BTYPE) == VT_FUNC) {
/* if old style function prototype, we accept a
declaration list */
- sym = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
+ sym = type.ref;
if (sym->c == FUNC_OLD)
func_decl_list(sym);
}
@@ -6955,7 +7064,7 @@ static void decl(int l)
if (l == VT_LOCAL)
error("cannot use local functions");
- if (!(t & VT_FUNC))
+ if (!(type.t & VT_FUNC))
expect("function definition");
#ifdef CONFIG_REG_VARS
@@ -6998,10 +7107,11 @@ static void decl(int l)
sym = sym_find(v);
if (sym) {
/* if symbol is already defined, then put complete type */
- sym->t = t;
+ sym->type = type;
} else {
/* put function symbol */
- sym = sym_push1(&global_stack, v, t, 0);
+ sym = sym_push1(&global_stack, v, type.t, 0);
+ sym->type.ref = type.ref;
}
/* NOTE: we patch the symbol size later */
put_extern_sym(sym, cur_text_section, ind, 0);
@@ -7012,7 +7122,7 @@ static void decl(int l)
put_func_debug(sym);
/* push a dummy symbol to enable local sym storage */
sym_push1(&local_stack, 0, 0, 0);
- gfunc_prolog(t);
+ gfunc_prolog(&type);
loc = 0;
rsym = 0;
#ifdef CONFIG_REG_VARS
@@ -7049,7 +7159,7 @@ static void decl(int l)
put_stabn(N_FUN, 0, 0, ind - func_ind);
}
funcname = ""; /* for safety */
- func_vt = VT_VOID; /* for safety */
+ func_vt.t = VT_VOID; /* for safety */
ind = 0; /* for safety */
#ifdef CONFIG_REG_VARS
@@ -7058,30 +7168,31 @@ static void decl(int l)
#endif
break;
} else {
- if (b & VT_TYPEDEF) {
+ if (btype.t & VT_TYPEDEF) {
/* save typedefed type */
/* XXX: test storage specifiers ? */
- sym_push(v, t | VT_TYPEDEF, 0, 0);
- } else if ((t & VT_BTYPE) == VT_FUNC) {
+ sym = sym_push(v, &type, 0, 0);
+ sym->type.t |= VT_TYPEDEF;
+ } else if ((type.t & VT_BTYPE) == VT_FUNC) {
/* external function definition */
- external_sym(v, t, 0);
+ external_sym(v, &type, 0);
} else {
/* not lvalue if array */
r = 0;
- if (!(t & VT_ARRAY))
- r |= lvalue_type(t);
- if (b & VT_EXTERN) {
+ if (!(type.t & VT_ARRAY))
+ r |= lvalue_type(type.t);
+ if (btype.t & VT_EXTERN) {
/* external variable */
- external_sym(v, t, r);
+ external_sym(v, &type, r);
} else {
- if (t & VT_STATIC)
+ if (type.t & VT_STATIC)
r |= VT_CONST;
else
r |= l;
has_init = (tok == '=');
if (has_init)
next();
- decl_initializer_alloc(t, &ad, r,
+ decl_initializer_alloc(&type, &ad, r,
has_init, v, l);
}
}
@@ -7095,29 +7206,12 @@ static void decl(int l)
}
}
-/* free define stack until top reaches 'b' */
-static void free_defines(Sym *b)
-{
- Sym *top, *top1;
-
- top = define_stack.top;
- while (top != b) {
- top1 = top->prev;
- /* do not free args or predefined defines */
- if (top->c)
- tok_str_free((int *)top->c);
- sym_pop(&define_stack, top1);
- top = top1;
- }
-}
-
/* compile the C file opened in 'file'. Return non zero if errors. */
static int tcc_compile(TCCState *s1)
{
- Sym *define_start, *sym;
+ Sym *define_start;
char buf[512];
volatile int section_sym;
- int p;
#ifdef INC_DEBUG
printf("%s: **** new file\n", file->filename);
@@ -7152,13 +7246,15 @@ static int tcc_compile(TCCState *s1)
ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
SHN_ABS, file->filename);
- /* define common 'char *' type because it is often used internally
- for arrays and struct dereference */
- char_pointer_type = mk_pointer(VT_BYTE);
- /* define an old type function 'int func()' */
- p = anon_sym++;
- sym = sym_push(p, 0, FUNC_CDECL, FUNC_OLD);
- func_old_type = VT_FUNC | (p << VT_STRUCT_SHIFT);
+ /* define some often used types */
+ int_type.t = VT_INT;
+
+ char_pointer_type.t = VT_BYTE;
+ mk_pointer(&char_pointer_type);
+
+ func_old_type.t = VT_FUNC;
+ func_old_type.ref = sym_push(0, &int_type, FUNC_CDECL, FUNC_OLD);
+
#if 0
/* define 'void *alloca(unsigned int)' builtin function */
{
@@ -7173,7 +7269,7 @@ static int tcc_compile(TCCState *s1)
}
#endif
- define_start = define_stack.top;
+ define_start = define_stack;
if (setjmp(s1->error_jmp_buf) == 0) {
s1->nb_errors = 0;
@@ -7222,7 +7318,7 @@ int tcc_compile_string(TCCState *s, const char *str)
return ret;
}
-/* define a symbol. A value can also be provided with the '=' operator */
+/* define a preprocessor symbol. A value can also be provided with the '=' operator */
void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
{
BufferedFile bf1, *bf = &bf1;
@@ -7252,15 +7348,16 @@ void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
file = NULL;
}
+/* undefine a preprocessor symbol */
void tcc_undefine_symbol(TCCState *s1, const char *sym)
{
TokenSym *ts;
Sym *s;
ts = tok_alloc(sym, strlen(sym));
- s = sym_find1(&define_stack, tok);
+ s = define_find(ts->tok);
/* undefine symbol by putting an invalid name */
if (s)
- sym_undef(&define_stack, s);
+ define_undef(s);
}
#include "tccelf.c"
@@ -7387,6 +7484,8 @@ static void rt_printline(unsigned long wanted_pc)
fprintf(stderr, "\n");
}
+#ifndef WIN32
+
#ifdef __i386__
#ifndef EIP
@@ -7417,7 +7516,7 @@ static int rt_get_caller_pc(unsigned long *paddr,
}
}
#else
-#error add corresponding function
+#error add arch specific rt_get_caller_pc()
#endif
/* emit a run time error at position 'pc' */
@@ -7444,7 +7543,6 @@ void rt_error(struct ucontext *uc, const char *fmt, ...)
va_end(ap);
}
-#ifndef WIN32
/* signal handler for fatal errors */
static void sig_error(int signum, siginfo_t *siginf, void *puc)
{
@@ -7594,10 +7692,10 @@ TCCState *tcc_new(void)
/* we add dummy defines for some special macros to speed up tests
and to have working defined() */
- sym_push1(&define_stack, TOK___LINE__, MACRO_OBJ, 0);
- sym_push1(&define_stack, TOK___FILE__, MACRO_OBJ, 0);
- sym_push1(&define_stack, TOK___DATE__, MACRO_OBJ, 0);
- sym_push1(&define_stack, TOK___TIME__, MACRO_OBJ, 0);
+ define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
+ define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
+ define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
+ define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
/* standard defines */
tcc_define_symbol(s, "__STDC__", NULL);
@@ -7889,6 +7987,19 @@ int tcc_set_output_type(TCCState *s, int output_type)
#if !defined(LIBTCC)
+static int64_t getclock_us(void)
+{
+#ifdef WIN32
+ struct _timeb tb;
+ _ftime(&tb);
+ return (tb.time * 1000LL + tb.millitm) * 1000LL;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000000LL + tv.tv_usec;
+#endif
+}
+
void help(void)
{
printf("tcc version 0.9.13 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
@@ -7930,6 +8041,7 @@ int main(int argc, char **argv)
char **files;
int nb_files, nb_libraries, nb_objfiles, dminus, ret;
char objfilename[1024];
+ int64_t start_time = 0;
s = tcc_new();
output_type = TCC_OUTPUT_MEMORY;
@@ -8061,6 +8173,10 @@ int main(int argc, char **argv)
outfile = objfilename;
}
+ if (do_bench) {
+ start_time = getclock_us();
+ }
+
tcc_set_output_type(s, output_type);
/* compile or add each files or library */
@@ -8083,8 +8199,16 @@ int main(int argc, char **argv)
tcc_free(files);
if (do_bench) {
- printf("total: %d idents, %d lines, %d bytes\n",
- tok_ident - TOK_IDENT, total_lines, total_bytes);
+ double total_time;
+ total_time = (double)(getclock_us() - start_time) / 1000000.0;
+ if (total_time < 0.001)
+ total_time = 0.001;
+ if (total_bytes < 1)
+ total_bytes = 1;
+ printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
+ tok_ident - TOK_IDENT, total_lines, total_bytes,
+ total_time, (int)(total_lines / total_time),
+ total_bytes / total_time / 1000000.0);
}
if (s->output_type != TCC_OUTPUT_MEMORY) {