added alignof and typeof - better sizeof support - fixed get_tok_str() for TOK_PPNUM
This commit is contained in:
parent
c0180c4e5f
commit
43f30315f9
1 changed files with 227 additions and 163 deletions
390
tcc.c
390
tcc.c
|
@ -270,6 +270,7 @@ int rsym, anon_sym,
|
||||||
prog, ind, loc;
|
prog, ind, loc;
|
||||||
/* expression generation modifiers */
|
/* expression generation modifiers */
|
||||||
int const_wanted; /* true if constant wanted */
|
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
|
int global_expr; /* true if compound literals must be allocated
|
||||||
globally (used during initializers parsing */
|
globally (used during initializers parsing */
|
||||||
int func_vt, func_vc; /* current function return type (used by
|
int func_vt, func_vc; /* current function return type (used by
|
||||||
|
@ -490,83 +491,20 @@ static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<
|
||||||
#define TOK_IDENT 256
|
#define TOK_IDENT 256
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TOK_INT = TOK_IDENT,
|
TOK_LAST = TOK_IDENT - 1,
|
||||||
TOK_VOID,
|
|
||||||
TOK_CHAR,
|
|
||||||
TOK_IF,
|
|
||||||
TOK_ELSE,
|
|
||||||
TOK_WHILE,
|
|
||||||
TOK_BREAK,
|
|
||||||
TOK_RETURN,
|
|
||||||
TOK_FOR,
|
|
||||||
TOK_EXTERN,
|
|
||||||
TOK_STATIC,
|
|
||||||
TOK_UNSIGNED,
|
|
||||||
TOK_GOTO,
|
|
||||||
TOK_DO,
|
|
||||||
TOK_CONTINUE,
|
|
||||||
TOK_SWITCH,
|
|
||||||
TOK_CASE,
|
|
||||||
|
|
||||||
/* ignored types Must have contiguous values */
|
|
||||||
TOK_CONST,
|
|
||||||
TOK_VOLATILE,
|
|
||||||
TOK_LONG,
|
|
||||||
TOK_REGISTER,
|
|
||||||
TOK_SIGNED,
|
|
||||||
TOK___SIGNED__, /* gcc keyword */
|
|
||||||
TOK_AUTO,
|
|
||||||
TOK_INLINE,
|
|
||||||
TOK___INLINE__, /* gcc keyword */
|
|
||||||
TOK_RESTRICT,
|
|
||||||
|
|
||||||
/* unsupported type */
|
|
||||||
TOK_FLOAT,
|
|
||||||
TOK_DOUBLE,
|
|
||||||
TOK_BOOL,
|
|
||||||
|
|
||||||
TOK_SHORT,
|
|
||||||
TOK_STRUCT,
|
|
||||||
TOK_UNION,
|
|
||||||
TOK_TYPEDEF,
|
|
||||||
TOK_DEFAULT,
|
|
||||||
TOK_ENUM,
|
|
||||||
TOK_SIZEOF,
|
|
||||||
TOK___ATTRIBUTE__,
|
|
||||||
|
|
||||||
/* preprocessor only */
|
|
||||||
TOK_UIDENT, /* first "user" ident (not keyword) */
|
|
||||||
TOK_DEFINE = TOK_UIDENT,
|
|
||||||
TOK_INCLUDE,
|
|
||||||
TOK_IFDEF,
|
|
||||||
TOK_IFNDEF,
|
|
||||||
TOK_ELIF,
|
|
||||||
TOK_ENDIF,
|
|
||||||
TOK_DEFINED,
|
|
||||||
TOK_UNDEF,
|
|
||||||
TOK_ERROR,
|
|
||||||
TOK_LINE,
|
|
||||||
|
|
||||||
#define DEF(id, str) id,
|
#define DEF(id, str) id,
|
||||||
#include "tcctok.h"
|
#include "tcctok.h"
|
||||||
#undef DEF
|
#undef DEF
|
||||||
};
|
};
|
||||||
|
|
||||||
char *tcc_keywords =
|
static const char *tcc_keywords =
|
||||||
"int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
|
|
||||||
"unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
|
|
||||||
"register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
|
|
||||||
"float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
|
|
||||||
"sizeof\0__attribute__\0"
|
|
||||||
/* the following are not keywords. They are included to ease parsing */
|
|
||||||
"define\0include\0ifdef\0ifndef\0elif\0endif\0"
|
|
||||||
"defined\0undef\0error\0line\0"
|
|
||||||
/* builtin functions */
|
|
||||||
#define DEF(id, str) str "\0"
|
#define DEF(id, str) str "\0"
|
||||||
#include "tcctok.h"
|
#include "tcctok.h"
|
||||||
#undef DEF
|
#undef DEF
|
||||||
;
|
;
|
||||||
|
|
||||||
|
#define TOK_UIDENT TOK_DEFINE
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
@ -590,13 +528,16 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
static char *pstrcpy(char *buf, int buf_size, const char *s);
|
static char *pstrcpy(char *buf, int buf_size, const char *s);
|
||||||
static char *pstrcat(char *buf, int buf_size, const char *s);
|
static char *pstrcat(char *buf, int buf_size, const char *s);
|
||||||
|
|
||||||
void sum(int l);
|
static void sum(int l);
|
||||||
void next(void);
|
static void next(void);
|
||||||
void next_nomacro(void);
|
static void next_nomacro(void);
|
||||||
|
static int parse_expr_type(void);
|
||||||
|
static int expr_type(void);
|
||||||
|
static int unary_type(void);
|
||||||
static int expr_const(void);
|
static int expr_const(void);
|
||||||
void expr_eq(void);
|
static void expr_eq(void);
|
||||||
void gexpr(void);
|
static void gexpr(void);
|
||||||
void decl(int l);
|
static void decl(int l);
|
||||||
static void decl_initializer(int t, Section *sec, unsigned long c,
|
static void decl_initializer(int t, Section *sec, unsigned long c,
|
||||||
int first, int size_only);
|
int first, int size_only);
|
||||||
static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
|
static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
|
||||||
|
@ -1301,12 +1242,12 @@ char *get_tok_str(int v, CValue *cv)
|
||||||
switch(v) {
|
switch(v) {
|
||||||
case TOK_CINT:
|
case TOK_CINT:
|
||||||
case TOK_CUINT:
|
case TOK_CUINT:
|
||||||
/* XXX: not quite exact, but useful for ## in macros */
|
/* XXX: not quite exact, but only useful for testing */
|
||||||
sprintf(p, "%u", cv->ui);
|
sprintf(p, "%u", cv->ui);
|
||||||
break;
|
break;
|
||||||
case TOK_CLLONG:
|
case TOK_CLLONG:
|
||||||
case TOK_CULLONG:
|
case TOK_CULLONG:
|
||||||
/* XXX: not quite exact, but useful for ## in macros */
|
/* XXX: not quite exact, but only useful for testing */
|
||||||
sprintf(p, "%Lu", cv->ull);
|
sprintf(p, "%Lu", cv->ull);
|
||||||
break;
|
break;
|
||||||
case TOK_CCHAR:
|
case TOK_CCHAR:
|
||||||
|
@ -1321,6 +1262,7 @@ char *get_tok_str(int v, CValue *cv)
|
||||||
len = cstr->size - 1;
|
len = cstr->size - 1;
|
||||||
for(i=0;i<len;i++)
|
for(i=0;i<len;i++)
|
||||||
add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
|
add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
|
||||||
|
cstr_ccat(&cstr_buf, '\0');
|
||||||
break;
|
break;
|
||||||
case TOK_STR:
|
case TOK_STR:
|
||||||
case TOK_LSTR:
|
case TOK_LSTR:
|
||||||
|
@ -2754,7 +2696,7 @@ static inline void next_nomacro1(void)
|
||||||
|
|
||||||
/* return next token without macro substitution. Can read input from
|
/* return next token without macro substitution. Can read input from
|
||||||
macro_ptr buffer */
|
macro_ptr buffer */
|
||||||
void next_nomacro()
|
static void next_nomacro(void)
|
||||||
{
|
{
|
||||||
if (macro_ptr) {
|
if (macro_ptr) {
|
||||||
redo:
|
redo:
|
||||||
|
@ -2772,7 +2714,7 @@ void next_nomacro()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* substitute args in macro_str and return allocated string */
|
/* substitute args in macro_str and return allocated string */
|
||||||
int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
||||||
{
|
{
|
||||||
int *st, last_tok, t, notfirst;
|
int *st, last_tok, t, notfirst;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
@ -2894,7 +2836,7 @@ static int *macro_twosharps(void)
|
||||||
p2 = get_tok_str(t, &cval);
|
p2 = get_tok_str(t, &cval);
|
||||||
cstr_cat(&cstr, p2);
|
cstr_cat(&cstr, p2);
|
||||||
cstr_ccat(&cstr, '\0');
|
cstr_ccat(&cstr, '\0');
|
||||||
|
|
||||||
if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
|
if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
|
||||||
(t >= TOK_IDENT || t == TOK_PPNUM)) {
|
(t >= TOK_IDENT || t == TOK_PPNUM)) {
|
||||||
if (tok == TOK_PPNUM) {
|
if (tok == TOK_PPNUM) {
|
||||||
|
@ -3130,7 +3072,7 @@ static void macro_subst(TokenString *tok_str,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return next token with macro substitution */
|
/* return next token with macro substitution */
|
||||||
void next(void)
|
static void next(void)
|
||||||
{
|
{
|
||||||
Sym *nested_list, *s;
|
Sym *nested_list, *s;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
|
@ -3670,7 +3612,7 @@ void vpop(void)
|
||||||
v = vtop->r & VT_VALMASK;
|
v = vtop->r & VT_VALMASK;
|
||||||
#ifdef TCC_TARGET_I386
|
#ifdef TCC_TARGET_I386
|
||||||
/* for x86, we need to pop the FP stack */
|
/* for x86, we need to pop the FP stack */
|
||||||
if (v == REG_ST0) {
|
if (v == REG_ST0 && !nocode_wanted) {
|
||||||
o(0xd9dd); /* fstp %st(1) */
|
o(0xd9dd); /* fstp %st(1) */
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -4045,8 +3987,12 @@ void gen_opic(int op)
|
||||||
vtop->c.i += fc;
|
vtop->c.i += fc;
|
||||||
} else {
|
} else {
|
||||||
general_case:
|
general_case:
|
||||||
/* call low level op generator */
|
if (!nocode_wanted) {
|
||||||
gen_opi(op);
|
/* call low level op generator */
|
||||||
|
gen_opi(op);
|
||||||
|
} else {
|
||||||
|
vtop--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4107,7 +4053,11 @@ void gen_opif(int op)
|
||||||
vtop--;
|
vtop--;
|
||||||
} else {
|
} else {
|
||||||
general_case:
|
general_case:
|
||||||
gen_opf(op);
|
if (!nocode_wanted) {
|
||||||
|
gen_opf(op);
|
||||||
|
} else {
|
||||||
|
vtop--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4355,7 +4305,7 @@ void gen_cast(int t)
|
||||||
dbt = t & (VT_BTYPE | VT_UNSIGNED);
|
dbt = t & (VT_BTYPE | VT_UNSIGNED);
|
||||||
sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
|
sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
|
||||||
|
|
||||||
if (sbt != dbt) {
|
if (sbt != dbt && !nocode_wanted) {
|
||||||
sf = is_float(sbt);
|
sf = is_float(sbt);
|
||||||
df = is_float(dbt);
|
df = is_float(dbt);
|
||||||
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
||||||
|
@ -4749,25 +4699,30 @@ void vstore(void)
|
||||||
/* if structure, only generate pointer */
|
/* if structure, only generate pointer */
|
||||||
/* structure assignment : generate memcpy */
|
/* structure assignment : generate memcpy */
|
||||||
/* XXX: optimize if small size */
|
/* XXX: optimize if small size */
|
||||||
vdup();
|
if (!nocode_wanted) {
|
||||||
gfunc_start(&gf, FUNC_CDECL);
|
vdup();
|
||||||
/* type size */
|
gfunc_start(&gf, FUNC_CDECL);
|
||||||
size = type_size(vtop->t, &align);
|
/* type size */
|
||||||
vpushi(size);
|
size = type_size(vtop->t, &align);
|
||||||
gfunc_param(&gf);
|
vpushi(size);
|
||||||
/* source */
|
gfunc_param(&gf);
|
||||||
vtop->t = VT_INT;
|
/* source */
|
||||||
gaddrof();
|
vtop->t = VT_INT;
|
||||||
gfunc_param(&gf);
|
gaddrof();
|
||||||
/* destination */
|
gfunc_param(&gf);
|
||||||
vswap();
|
/* destination */
|
||||||
vtop->t = VT_INT;
|
vswap();
|
||||||
gaddrof();
|
vtop->t = VT_INT;
|
||||||
gfunc_param(&gf);
|
gaddrof();
|
||||||
|
gfunc_param(&gf);
|
||||||
save_regs(0);
|
|
||||||
vpush_global_sym(func_old_type, TOK_memcpy);
|
save_regs(0);
|
||||||
gfunc_call(&gf);
|
vpush_global_sym(func_old_type, TOK_memcpy);
|
||||||
|
gfunc_call(&gf);
|
||||||
|
} else {
|
||||||
|
vswap();
|
||||||
|
vpop();
|
||||||
|
}
|
||||||
/* leave source on stack */
|
/* leave source on stack */
|
||||||
} else if (ft & VT_BITFIELD) {
|
} else if (ft & VT_BITFIELD) {
|
||||||
/* bitfield store handling */
|
/* bitfield store handling */
|
||||||
|
@ -4801,33 +4756,35 @@ void vstore(void)
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
rc = RC_INT;
|
if (!nocode_wanted) {
|
||||||
if (is_float(ft))
|
rc = RC_INT;
|
||||||
rc = RC_FLOAT;
|
if (is_float(ft))
|
||||||
r = gv(rc); /* generate value */
|
rc = RC_FLOAT;
|
||||||
/* if lvalue was saved on stack, must read it */
|
r = gv(rc); /* generate value */
|
||||||
if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
|
/* if lvalue was saved on stack, must read it */
|
||||||
SValue sv;
|
if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
|
||||||
t = get_reg(RC_INT);
|
SValue sv;
|
||||||
sv.t = VT_INT;
|
t = get_reg(RC_INT);
|
||||||
sv.r = VT_LOCAL | VT_LVAL;
|
sv.t = VT_INT;
|
||||||
sv.c.ul = vtop[-1].c.ul;
|
sv.r = VT_LOCAL | VT_LVAL;
|
||||||
load(t, &sv);
|
sv.c.ul = vtop[-1].c.ul;
|
||||||
vtop[-1].r = t | VT_LVAL;
|
load(t, &sv);
|
||||||
}
|
vtop[-1].r = t | VT_LVAL;
|
||||||
store(r, vtop - 1);
|
}
|
||||||
/* two word case handling : store second register at word + 4 */
|
store(r, vtop - 1);
|
||||||
if ((ft & VT_BTYPE) == VT_LLONG) {
|
/* two word case handling : store second register at word + 4 */
|
||||||
vswap();
|
if ((ft & VT_BTYPE) == VT_LLONG) {
|
||||||
/* convert to int to increment easily */
|
vswap();
|
||||||
vtop->t = VT_INT;
|
/* convert to int to increment easily */
|
||||||
gaddrof();
|
vtop->t = VT_INT;
|
||||||
vpushi(4);
|
gaddrof();
|
||||||
gen_op('+');
|
vpushi(4);
|
||||||
vtop->r |= VT_LVAL;
|
gen_op('+');
|
||||||
vswap();
|
vtop->r |= VT_LVAL;
|
||||||
/* XXX: it works because r2 is spilled last ! */
|
vswap();
|
||||||
store(vtop->r2, vtop - 1);
|
/* XXX: it works because r2 is spilled last ! */
|
||||||
|
store(vtop->r2, vtop - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vswap();
|
vswap();
|
||||||
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
|
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
|
||||||
|
@ -5188,6 +5145,11 @@ int parse_btype(int *type_ptr, AttributeDef *ad)
|
||||||
case TOK___ATTRIBUTE__:
|
case TOK___ATTRIBUTE__:
|
||||||
parse_attribute(ad);
|
parse_attribute(ad);
|
||||||
break;
|
break;
|
||||||
|
/* GNUC typeof */
|
||||||
|
case TOK_TYPEOF:
|
||||||
|
next();
|
||||||
|
u = parse_expr_type();
|
||||||
|
goto basic_type1;
|
||||||
default:
|
default:
|
||||||
s = sym_find(tok);
|
s = sym_find(tok);
|
||||||
if (!s || !(s->t & VT_TYPEDEF))
|
if (!s || !(s->t & VT_TYPEDEF))
|
||||||
|
@ -5367,7 +5329,7 @@ static void indir(void)
|
||||||
{
|
{
|
||||||
if ((vtop->t & VT_BTYPE) != VT_PTR)
|
if ((vtop->t & VT_BTYPE) != VT_PTR)
|
||||||
expect("pointer");
|
expect("pointer");
|
||||||
if (vtop->r & VT_LVAL)
|
if ((vtop->r & VT_LVAL) && !nocode_wanted)
|
||||||
gv(RC_INT);
|
gv(RC_INT);
|
||||||
vtop->t = pointed_type(vtop->t);
|
vtop->t = pointed_type(vtop->t);
|
||||||
/* an array is never an lvalue */
|
/* an array is never an lvalue */
|
||||||
|
@ -5394,10 +5356,31 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
|
||||||
} else {
|
} else {
|
||||||
gen_assign_cast(arg->t);
|
gen_assign_cast(arg->t);
|
||||||
}
|
}
|
||||||
gfunc_param(gf);
|
if (!nocode_wanted) {
|
||||||
|
gfunc_param(gf);
|
||||||
|
} else {
|
||||||
|
vpop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unary(void)
|
/* parse an expression of the form '(type)' or '(expr)' and return its
|
||||||
|
type */
|
||||||
|
static int parse_expr_type(void)
|
||||||
|
{
|
||||||
|
int ft, n;
|
||||||
|
AttributeDef ad;
|
||||||
|
|
||||||
|
skip('(');
|
||||||
|
if (parse_btype(&ft, &ad)) {
|
||||||
|
ft = type_decl(&ad, &n, ft, TYPE_ABSTRACT);
|
||||||
|
} else {
|
||||||
|
ft = expr_type();
|
||||||
|
}
|
||||||
|
skip(')');
|
||||||
|
return ft;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unary(void)
|
||||||
{
|
{
|
||||||
int n, t, ft, align, size, r;
|
int n, t, ft, align, size, r;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
@ -5515,25 +5498,17 @@ void unary(void)
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
gen_op('+');
|
gen_op('+');
|
||||||
} else
|
} else
|
||||||
if (t == TOK_SIZEOF) {
|
if (t == TOK_SIZEOF || t == TOK_ALIGNOF) {
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
next();
|
ft = parse_expr_type();
|
||||||
if (parse_btype(&t, &ad)) {
|
|
||||||
t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
|
|
||||||
} else {
|
|
||||||
/* XXX: some code could be generated: add eval
|
|
||||||
flag */
|
|
||||||
gexpr();
|
|
||||||
t = vtop->t;
|
|
||||||
vpop();
|
|
||||||
}
|
|
||||||
skip(')');
|
|
||||||
} else {
|
} else {
|
||||||
unary();
|
ft = unary_type();
|
||||||
t = vtop->t;
|
|
||||||
vpop();
|
|
||||||
}
|
}
|
||||||
vpushi(type_size(t, &t));
|
size = type_size(ft, &align);
|
||||||
|
if (t == TOK_SIZEOF)
|
||||||
|
vpushi(size);
|
||||||
|
else
|
||||||
|
vpushi(align);
|
||||||
} else
|
} else
|
||||||
if (t == TOK_INC || t == TOK_DEC) {
|
if (t == TOK_INC || t == TOK_DEC) {
|
||||||
unary();
|
unary();
|
||||||
|
@ -5627,8 +5602,10 @@ void unary(void)
|
||||||
}
|
}
|
||||||
/* get return type */
|
/* get return type */
|
||||||
s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
|
s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
|
||||||
save_regs(0); /* save used temporary registers */
|
if (!nocode_wanted) {
|
||||||
gfunc_start(&gf, s->r);
|
save_regs(0); /* save used temporary registers */
|
||||||
|
gfunc_start(&gf, s->r);
|
||||||
|
}
|
||||||
next();
|
next();
|
||||||
sa = s->next; /* first parameter */
|
sa = s->next; /* first parameter */
|
||||||
#ifdef INVERT_FUNC_PARAMS
|
#ifdef INVERT_FUNC_PARAMS
|
||||||
|
@ -5693,7 +5670,10 @@ void unary(void)
|
||||||
problems */
|
problems */
|
||||||
vset(VT_INT, VT_LOCAL, loc);
|
vset(VT_INT, VT_LOCAL, loc);
|
||||||
ret.c = vtop->c;
|
ret.c = vtop->c;
|
||||||
gfunc_param(&gf);
|
if (!nocode_wanted)
|
||||||
|
gfunc_param(&gf);
|
||||||
|
else
|
||||||
|
vtop--;
|
||||||
} else {
|
} else {
|
||||||
ret.t = s->t;
|
ret.t = s->t;
|
||||||
ret.r2 = VT_CONST;
|
ret.r2 = VT_CONST;
|
||||||
|
@ -5723,7 +5703,10 @@ void unary(void)
|
||||||
if (sa)
|
if (sa)
|
||||||
error("too few arguments to function");
|
error("too few arguments to function");
|
||||||
skip(')');
|
skip(')');
|
||||||
gfunc_call(&gf);
|
if (!nocode_wanted)
|
||||||
|
gfunc_call(&gf);
|
||||||
|
else
|
||||||
|
vtop--;
|
||||||
/* return value */
|
/* return value */
|
||||||
vsetc(ret.t, ret.r, &ret.c);
|
vsetc(ret.t, ret.r, &ret.c);
|
||||||
vtop->r2 = ret.r2;
|
vtop->r2 = ret.r2;
|
||||||
|
@ -5733,7 +5716,7 @@ void unary(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uneq(void)
|
static void uneq(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
|
@ -5756,7 +5739,7 @@ void uneq(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sum(int l)
|
static void sum(int l)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
|
@ -5784,7 +5767,7 @@ void sum(int l)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only used if non constant */
|
/* only used if non constant */
|
||||||
void eand(void)
|
static void eand(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
|
@ -5804,7 +5787,7 @@ void eand(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void eor(void)
|
static void eor(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
|
@ -5825,7 +5808,7 @@ void eor(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: better constant handling */
|
/* XXX: better constant handling */
|
||||||
void expr_eq(void)
|
static void expr_eq(void)
|
||||||
{
|
{
|
||||||
int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
|
int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
|
||||||
SValue sv;
|
SValue sv;
|
||||||
|
@ -5925,7 +5908,7 @@ void expr_eq(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gexpr(void)
|
static void gexpr(void)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
expr_eq();
|
expr_eq();
|
||||||
|
@ -5936,6 +5919,35 @@ void gexpr(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* parse an expression and return its type without any side effect. */
|
||||||
|
static int expr_type(void)
|
||||||
|
{
|
||||||
|
int a, t;
|
||||||
|
|
||||||
|
a = nocode_wanted;
|
||||||
|
nocode_wanted = 1;
|
||||||
|
gexpr();
|
||||||
|
t = vtop->t;
|
||||||
|
vpop();
|
||||||
|
nocode_wanted = a;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a unary expression and return its type without any side
|
||||||
|
effect. */
|
||||||
|
static int unary_type(void)
|
||||||
|
{
|
||||||
|
int a, t;
|
||||||
|
|
||||||
|
a = nocode_wanted;
|
||||||
|
nocode_wanted = 1;
|
||||||
|
unary();
|
||||||
|
t = vtop->t;
|
||||||
|
vpop();
|
||||||
|
nocode_wanted = a;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse a constant expression and return value in vtop. */
|
/* parse a constant expression and return value in vtop. */
|
||||||
static void expr_const1(void)
|
static void expr_const1(void)
|
||||||
{
|
{
|
||||||
|
@ -5960,7 +5972,7 @@ static int expr_const(void)
|
||||||
|
|
||||||
/* return the label token if current token is a label, otherwise
|
/* return the label token if current token is a label, otherwise
|
||||||
return zero */
|
return zero */
|
||||||
int is_label(void)
|
static int is_label(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
CValue c;
|
CValue c;
|
||||||
|
@ -5985,7 +5997,7 @@ int is_label(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
|
static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
|
||||||
{
|
{
|
||||||
int a, b, c, d;
|
int a, b, c, d;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
@ -6819,8 +6831,52 @@ void analyse_function(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* parse an old style function declaration list */
|
||||||
|
/* XXX: check multiple parameter */
|
||||||
|
static void func_decl_list(Sym *func_sym)
|
||||||
|
{
|
||||||
|
AttributeDef ad;
|
||||||
|
int b, v, t;
|
||||||
|
Sym *s;
|
||||||
|
/* parse each declaration */
|
||||||
|
while (tok != '{' && tok != ';' && tok != TOK_EOF) {
|
||||||
|
if (!parse_btype(&b, &ad))
|
||||||
|
expect("declaration list");
|
||||||
|
if (((b & VT_BTYPE) == VT_ENUM ||
|
||||||
|
(b & VT_BTYPE) == VT_STRUCT) &&
|
||||||
|
tok == ';') {
|
||||||
|
/* we accept no variable after */
|
||||||
|
} else {
|
||||||
|
for(;;) {
|
||||||
|
t = type_decl(&ad, &v, b, TYPE_DIRECT);
|
||||||
|
/* find parameter in function parameter list */
|
||||||
|
s = func_sym->next;
|
||||||
|
while (s != NULL) {
|
||||||
|
if ((s->v & ~SYM_FIELD) == v)
|
||||||
|
goto found;
|
||||||
|
s = s->next;
|
||||||
|
}
|
||||||
|
error("declaration for parameter '%s' but no such parameter",
|
||||||
|
get_tok_str(v, NULL));
|
||||||
|
found:
|
||||||
|
/* check that no storage specifier except 'register' was given */
|
||||||
|
if (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;
|
||||||
|
/* accept other parameters */
|
||||||
|
if (tok == ',')
|
||||||
|
next();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
|
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
|
||||||
void decl(int l)
|
static void decl(int l)
|
||||||
{
|
{
|
||||||
int t, b, v, has_init, r;
|
int t, b, v, has_init, r;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
@ -6856,6 +6912,14 @@ void decl(int l)
|
||||||
printf("type = '%s'\n", buf);
|
printf("type = '%s'\n", buf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if ((t & VT_BTYPE) == VT_FUNC) {
|
||||||
|
/* if old style function prototype, we accept a
|
||||||
|
declaration list */
|
||||||
|
sym = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
|
||||||
|
if (sym->c == FUNC_OLD)
|
||||||
|
func_decl_list(sym);
|
||||||
|
}
|
||||||
|
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
#ifdef CONFIG_REG_VARS
|
#ifdef CONFIG_REG_VARS
|
||||||
TokenString func_str;
|
TokenString func_str;
|
||||||
|
@ -7392,7 +7456,7 @@ int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
|
|
||||||
TCCState *tcc_new(void)
|
TCCState *tcc_new(void)
|
||||||
{
|
{
|
||||||
char *p, *r;
|
const char *p, *r;
|
||||||
TCCState *s;
|
TCCState *s;
|
||||||
|
|
||||||
s = tcc_mallocz(sizeof(TCCState));
|
s = tcc_mallocz(sizeof(TCCState));
|
||||||
|
|
Loading…
Reference in a new issue