Alien-TinyCC
view release on metacpan or search on metacpan
src/tccgen.c view on Meta::CPAN
break;
case TOK_CDECL1:
case TOK_CDECL2:
case TOK_CDECL3:
ad->func_call = FUNC_CDECL;
break;
case TOK_STDCALL1:
case TOK_STDCALL2:
case TOK_STDCALL3:
ad->func_call = FUNC_STDCALL;
break;
#ifdef TCC_TARGET_I386
case TOK_REGPARM1:
case TOK_REGPARM2:
skip('(');
n = expr_const();
if (n > 3)
n = 3;
else if (n < 0)
n = 0;
if (n > 0)
ad->func_call = FUNC_FASTCALL1 + n - 1;
skip(')');
break;
case TOK_FASTCALL1:
case TOK_FASTCALL2:
case TOK_FASTCALL3:
ad->func_call = FUNC_FASTCALLW;
break;
#endif
case TOK_MODE:
skip('(');
switch(tok) {
case TOK_MODE_DI:
ad->mode = VT_LLONG + 1;
break;
case TOK_MODE_HI:
ad->mode = VT_SHORT + 1;
break;
case TOK_MODE_SI:
ad->mode = VT_INT + 1;
break;
default:
tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL));
break;
}
next();
skip(')');
break;
case TOK_DLLEXPORT:
ad->func_export = 1;
break;
case TOK_DLLIMPORT:
ad->func_import = 1;
break;
default:
if (tcc_state->warn_unsupported)
tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL));
/* skip parameters */
if (tok == '(') {
int parenthesis = 0;
do {
if (tok == '(')
parenthesis++;
else if (tok == ')')
parenthesis--;
next();
} while (parenthesis && tok != -1);
}
break;
}
if (tok != ',')
break;
next();
}
skip(')');
skip(')');
}
}
/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
static void struct_decl(CType *type, int u, int tdef)
{
int a, v, size, align, maxalign, c, offset, flexible;
int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
Sym *s, *ss, *ass, **ps;
AttributeDef ad;
CType type1, btype;
a = tok; /* save decl type */
next();
if (tok != '{') {
v = tok;
next();
/* struct already defined ? return it */
if (v < TOK_IDENT)
expect("struct/union/enum name");
s = struct_find(v);
if (s) {
if (s->type.t != a)
tcc_error("invalid type");
goto do_decl;
} else if (tok >= TOK_IDENT && !tdef)
tcc_error("unknown struct/union/enum");
} else {
v = anon_sym++;
}
type1.t = a;
type1.ref = NULL;
/* we put an undefined size for struct/union */
s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
s->r = 0; /* default alignment is zero as gcc */
/* put struct/union/enum name in type */
do_decl:
type->t = u;
type->ref = s;
if (tok == '{') {
next();
if (s->c != -1)
tcc_error("struct/union/enum already defined");
/* cannot be empty */
c = 0;
/* non empty enums are not allowed */
if (a == TOK_ENUM) {
for(;;) {
v = tok;
if (v < TOK_UIDENT)
src/tccgen.c view on Meta::CPAN
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;
}
( run in 1.340 second using v1.01-cache-2.11-cpan-8450f2e95f3 )