Alien-TinyCC
view release on metacpan or search on metacpan
src/tccgen.c view on Meta::CPAN
case '+':
next();
/* in order to force cast, we add zero */
unary();
if ((vtop->type.t & VT_BTYPE) == VT_PTR)
tcc_error("pointer not accepted for unary plus");
vpushi(0);
gen_op('+');
break;
case TOK_SIZEOF:
case TOK_ALIGNOF1:
case TOK_ALIGNOF2:
t = tok;
next();
in_sizeof++;
unary_type(&type); // Perform a in_sizeof = 0;
size = type_size(&type, &align);
if (t == TOK_SIZEOF) {
if (!(type.t & VT_VLA)) {
if (size < 0)
tcc_error("sizeof applied to an incomplete type");
vpushs(size);
} else {
vla_runtime_type_size(&type, &align);
}
} else {
vpushs(align);
}
vtop->type.t |= VT_UNSIGNED;
break;
case TOK_builtin_types_compatible_p:
{
CType type1, type2;
next();
skip('(');
parse_type(&type1);
skip(',');
parse_type(&type2);
skip(')');
type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
vpushi(is_compatible_types(&type1, &type2));
}
break;
case TOK_builtin_constant_p:
{
int saved_nocode_wanted, res;
next();
skip('(');
saved_nocode_wanted = nocode_wanted;
nocode_wanted = 1;
gexpr();
res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
vpop();
nocode_wanted = saved_nocode_wanted;
skip(')');
vpushi(res);
}
break;
case TOK_builtin_frame_address:
{
int level;
CType type;
next();
skip('(');
if (tok != TOK_CINT || tokc.i < 0) {
tcc_error("__builtin_frame_address only takes positive integers");
}
level = tokc.i;
next();
skip(')');
type.t = VT_VOID;
mk_pointer(&type);
vset(&type, VT_LOCAL, 0); /* local frame */
while (level--) {
mk_pointer(&vtop->type);
indir(); /* -> parent frame */
}
}
break;
#ifdef TCC_TARGET_X86_64
#ifdef TCC_TARGET_PE
case TOK_builtin_va_start:
{
next();
skip('(');
expr_eq();
skip(',');
expr_eq();
skip(')');
if ((vtop->r & VT_VALMASK) != VT_LOCAL)
tcc_error("__builtin_va_start expects a local variable");
vtop->r &= ~(VT_LVAL | VT_REF);
vtop->type = char_pointer_type;
vstore();
}
break;
#else
case TOK_builtin_va_arg_types:
{
CType type;
next();
skip('(');
parse_type(&type);
skip(')');
vpushi(classify_x86_64_va_arg(&type));
}
break;
#endif
#endif
case TOK_INC:
case TOK_DEC:
t = tok;
next();
unary();
inc(0, t);
break;
case '-':
next();
vpushi(0);
unary();
gen_op('-');
break;
case TOK_LAND:
if (!gnu_ext)
goto tok_identifier;
next();
/* allow to take the address of a label */
if (tok < TOK_UIDENT)
expect("label identifier");
s = label_find(tok);
if (!s) {
s = label_push(&global_label_stack, tok, LABEL_FORWARD);
} else {
if (s->r == LABEL_DECLARED)
s->r = LABEL_FORWARD;
}
src/tccgen.c view on Meta::CPAN
expr_cond();
const_wanted = a;
}
/* parse an integer constant and return its value. */
ST_FUNC int expr_const(void)
{
int c;
expr_const1();
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
expect("constant expression");
c = vtop->c.i;
vpop();
return c;
}
/* return the label token if current token is a label, otherwise
return zero */
static int is_label(void)
{
int last_tok;
/* fast test first */
if (tok < TOK_UIDENT)
return 0;
/* no need to save tokc because tok is an identifier */
last_tok = tok;
next();
if (tok == ':') {
next();
return last_tok;
} else {
unget_tok(last_tok);
return 0;
}
}
static void label_or_decl(int l)
{
int last_tok;
/* fast test first */
if (tok >= TOK_UIDENT)
{
/* no need to save tokc because tok is an identifier */
last_tok = tok;
next();
if (tok == ':') {
unget_tok(last_tok);
return;
}
unget_tok(last_tok);
}
decl(l);
}
static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
int case_reg, int is_expr)
{
int a, b, c, d;
Sym *s, *frame_bottom;
/* generate line number info */
if (tcc_state->do_debug &&
(last_line_num != file->line_num || last_ind != ind)) {
put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
last_ind = ind;
last_line_num = file->line_num;
}
if (is_expr) {
/* default return value is (void) */
vpushi(0);
vtop->type.t = VT_VOID;
}
if (tok == TOK_IF) {
/* if test */
next();
skip('(');
gexpr();
skip(')');
a = gtst(1, 0);
block(bsym, csym, case_sym, def_sym, case_reg, 0);
c = tok;
if (c == TOK_ELSE) {
next();
d = gjmp(0);
gsym(a);
block(bsym, csym, case_sym, def_sym, case_reg, 0);
gsym(d); /* patch else jmp */
} else
gsym(a);
} else if (tok == TOK_WHILE) {
next();
d = ind;
skip('(');
gexpr();
skip(')');
a = gtst(1, 0);
b = 0;
block(&a, &b, case_sym, def_sym, case_reg, 0);
gjmp_addr(d);
gsym(a);
gsym_addr(b, d);
} else if (tok == '{') {
Sym *llabel;
int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
next();
/* record local declaration stack position */
s = local_stack;
frame_bottom = sym_push2(&local_stack, SYM_FIELD, 0, 0);
frame_bottom->next = scope_stack_bottom;
scope_stack_bottom = frame_bottom;
llabel = local_label_stack;
/* save VLA state */
block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
if (saved_vla_sp_loc != &vla_sp_root_loc)
vla_sp_loc = &block_vla_sp_loc;
saved_vla_flags = vla_flags;
vla_flags |= VLA_NEED_NEW_FRAME;
/* handle local labels declarations */
if (tok == TOK_LABEL) {
next();
for(;;) {
if (tok < TOK_UIDENT)
expect("label identifier");
label_push(&local_label_stack, tok, LABEL_DECLARED);
next();
if (tok == ',') {
next();
} else {
skip(';');
break;
}
}
}
while (tok != '}') {
label_or_decl(VT_LOCAL);
if (tok != '}') {
if (is_expr)
vpop();
block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
}
}
/* pop locally defined labels */
label_pop(&local_label_stack, llabel);
if(is_expr) {
/* XXX: this solution makes only valgrind happy...
triggered by gcc.c-torture/execute/20000917-1.c */
Sym *p;
switch(vtop->type.t & VT_BTYPE) {
case VT_PTR:
case VT_STRUCT:
case VT_ENUM:
case VT_FUNC:
for(p=vtop->type.ref;p;p=p->prev)
if(p->prev==s)
tcc_error("unsupported expression type");
}
}
/* pop locally defined symbols */
scope_stack_bottom = scope_stack_bottom->next;
sym_pop(&local_stack, s);
/* Pop VLA frames and restore stack pointer if required */
if (saved_vla_sp_loc != &vla_sp_root_loc)
*saved_vla_sp_loc = block_vla_sp_loc;
if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ? &vla_sp_root_loc : &block_vla_sp_loc)) {
vla_sp_loc = saved_vla_sp_loc;
gen_vla_sp_restore(*vla_sp_loc);
}
vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);
next();
} else if (tok == TOK_RETURN) {
next();
if (tok != ';') {
gexpr();
gen_assign_cast(&func_vt);
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
CType type, ret_type;
int ret_align;
if (gfunc_sret(&func_vt, &ret_type, &ret_align)) {
/* if returning structure, must copy it to implicit
first pointer arg location */
type = func_vt;
mk_pointer(&type);
vset(&type, VT_LOCAL | VT_LVAL, func_vc);
indir();
vswap();
/* copy structure value to pointer */
vstore();
} else {
/* returning structure packed into registers */
int size, addr, align;
size = type_size(&func_vt,&align);
if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1)))
&& (align & (ret_align-1))) {
loc = (loc - size) & -align;
addr = loc;
type = func_vt;
vset(&type, VT_LOCAL | VT_LVAL, addr);
vswap();
vstore();
vset(&ret_type, VT_LOCAL | VT_LVAL, addr);
}
vtop->type = ret_type;
if (is_float(ret_type.t))
gv(rc_fret(ret_type.t));
else
gv(RC_IRET);
}
} else if (is_float(func_vt.t)) {
gv(rc_fret(func_vt.t));
} else {
gv(RC_IRET);
}
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
}
skip(';');
rsym = gjmp(rsym); /* jmp */
} else if (tok == TOK_BREAK) {
/* compute jump */
if (!bsym)
tcc_error("cannot break");
*bsym = gjmp(*bsym);
next();
skip(';');
} else if (tok == TOK_CONTINUE) {
/* compute jump */
if (!csym)
tcc_error("cannot continue");
*csym = gjmp(*csym);
next();
skip(';');
} else if (tok == TOK_FOR) {
int e;
next();
skip('(');
s = local_stack;
frame_bottom = sym_push2(&local_stack, SYM_FIELD, 0, 0);
frame_bottom->next = scope_stack_bottom;
scope_stack_bottom = frame_bottom;
if (tok != ';') {
/* c99 for-loop init decl? */
if (!decl0(VT_LOCAL, 1)) {
/* no, regular for-loop init expr */
gexpr();
vpop();
}
}
skip(';');
d = ind;
c = ind;
a = 0;
b = 0;
if (tok != ';') {
gexpr();
a = gtst(1, 0);
}
skip(';');
if (tok != ')') {
e = gjmp(0);
c = ind;
gexpr();
vpop();
gjmp_addr(d);
gsym(e);
}
skip(')');
block(&a, &b, case_sym, def_sym, case_reg, 0);
gjmp_addr(c);
gsym(a);
gsym_addr(b, c);
scope_stack_bottom = scope_stack_bottom->next;
sym_pop(&local_stack, s);
} else
if (tok == TOK_DO) {
next();
a = 0;
b = 0;
d = ind;
block(&a, &b, case_sym, def_sym, case_reg, 0);
skip(TOK_WHILE);
skip('(');
gsym(b);
gexpr();
c = gtst(0, 0);
gsym_addr(c, d);
skip(')');
gsym(a);
skip(';');
} else
if (tok == TOK_SWITCH) {
next();
skip('(');
gexpr();
/* XXX: other types than integer */
case_reg = gv(RC_INT);
vpop();
skip(')');
a = 0;
b = gjmp(0); /* jump to first case */
( run in 0.961 second using v1.01-cache-2.11-cpan-df04353d9ac )