aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c179
1 files changed, 68 insertions, 111 deletions
diff --git a/tccgen.c b/tccgen.c
index 387b986..1a89d4a 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -90,9 +90,6 @@ static void vla_runtime_type_size(CType *type, int *a);
static void vla_sp_save(void);
static int is_compatible_parameter_types(CType *type1, CType *type2);
static void expr_type(CType *type);
-static int is_putz;
-static int is_force;
-
ST_FUNC void vpush64(int ty, unsigned long long v);
ST_FUNC void vpush(CType *type);
ST_FUNC int gvtst(int inv, int t);
@@ -1020,7 +1017,6 @@ ST_FUNC void lexpand_nr(void)
}
#endif
-#ifndef TCC_TARGET_X86_64
/* build a long long from two ints */
static void lbuild(int t)
{
@@ -1029,7 +1025,6 @@ static void lbuild(int t)
vtop[-1].type.t = t;
vpop();
}
-#endif
/* rotate n first stack elements to the bottom
I1 ... In -> I2 ... In I1 [top is right]
@@ -1091,8 +1086,8 @@ static void gv_dup(void)
{
int rc, t, r, r1;
SValue sv;
+
t = vtop->type.t;
-#ifndef TCC_TARGET_X86_64
if ((t & VT_BTYPE) == VT_LLONG) {
lexpand();
gv_dup();
@@ -1102,14 +1097,15 @@ static void gv_dup(void)
vrotb(4);
/* stack: H L L1 H1 */
lbuild(t);
- vrott(3);
+ vrotb(3);
+ vrotb(3);
vswap();
lbuild(t);
vswap();
- } else
-#endif
- {
+ } else {
/* duplicate value */
+ rc = RC_INT;
+ sv.type.t = VT_INT;
if (is_float(t)) {
rc = RC_FLOAT;
#ifdef TCC_TARGET_X86_64
@@ -1117,9 +1113,8 @@ static void gv_dup(void)
rc = RC_ST0;
}
#endif
- }else
- rc = RC_INT;
- sv.type.t = t;
+ sv.type.t = t;
+ }
r = gv(rc);
r1 = get_reg(rc);
sv.r = r;
@@ -1989,30 +1984,11 @@ static void gen_cast(CType *type)
;
#endif
else if (dbt != VT_LLONG) {
- int s, dt, warr = 0;
- long long ll;
- dt = dbt & VT_BTYPE;
- ll = vtop->c.ll;
- if (dt == VT_BYTE){
- if((ll != (unsigned char)ll) && (ll != (char)ll))
- warr = 1;
+ int s = 0;
+ if ((dbt & VT_BTYPE) == VT_BYTE)
s = 24;
- }else if (dt == VT_SHORT){
- if((ll != (unsigned short)ll) && (ll != (short)ll))
- warr = 1;
+ else if ((dbt & VT_BTYPE) == VT_SHORT)
s = 16;
- }else{
- if((ll != (unsigned int)ll) && (ll != (int)ll))
- warr = 1;
- s = 0;
- }
- if(warr && !is_force){
- if(dt == VT_ENUM){
- tcc_warning("large integer implicitly truncated to unsigned type");
- dbt = VT_UNSIGNED;
- }else
- tcc_warning("overflow in implicit constant conversion");
- }
if(dbt & VT_UNSIGNED)
vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
else
@@ -2465,8 +2441,6 @@ static void gen_assign_cast(CType *dt)
if (sbt == VT_PTR || sbt == VT_FUNC) {
tcc_warning("assignment makes integer from pointer without a cast");
}
- if (sbt == VT_STRUCT)
- goto error;
/* XXX: more tests */
break;
case VT_STRUCT:
@@ -2489,15 +2463,14 @@ static void gen_assign_cast(CType *dt)
/* store vtop in lvalue pushed on stack */
ST_FUNC void vstore(void)
{
- int sbt, dbt, ft, cc, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
+ int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
ft = vtop[-1].type.t;
sbt = vtop->type.t & VT_BTYPE;
dbt = ft & VT_BTYPE;
- cc = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
(sbt == VT_INT && dbt == VT_SHORT))
- && !(vtop->type.t & VT_BITFIELD) && !cc) {
+ && !(vtop->type.t & VT_BITFIELD)) {
/* optimize char/short casts */
delayed_cast = VT_MUSTCAST;
vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
@@ -2591,6 +2564,7 @@ ST_FUNC void vstore(void)
/* pop off shifted source from "duplicate source..." above */
vpop();
+
} else {
#ifdef CONFIG_TCC_BCHECK
/* bound check case */
@@ -2865,7 +2839,7 @@ static void struct_decl(CType *type, int u, int tdef)
s = struct_find(v);
if (s) {
if (s->type.t != a)
- tcc_error("invalid type: '%s'", get_tok_str(v, NULL));
+ tcc_error("invalid type");
goto do_decl;
} else if (tok >= TOK_IDENT && !tdef)
tcc_error("unknown struct/union/enum");
@@ -2937,7 +2911,7 @@ static void struct_decl(CType *type, int u, int tdef)
if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
expect("identifier");
if (type_size(&type1, &align) < 0) {
- if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY))
+ if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c)
flexible = 1;
else
tcc_error("field '%s' has incomplete type",
@@ -3056,8 +3030,6 @@ static void struct_decl(CType *type, int u, int tdef)
skip(';');
}
skip('}');
- if (!c && flexible)
- tcc_error("flexible array member '%s' in otherwise empty struct", get_tok_str(v, NULL));
/* store size and alignment */
s->c = (c + maxalign - 1) & -maxalign;
s->r = maxalign;
@@ -3742,9 +3714,7 @@ ST_FUNC void unary(void)
return;
}
unary();
- is_force = 1;
gen_cast(&type);
- is_force = 0;
}
} else if (tok == '{') {
/* save all registers */
@@ -3823,8 +3793,6 @@ ST_FUNC void unary(void)
if (!(type.t & VT_VLA)) {
if (size < 0)
tcc_error("sizeof applied to an incomplete type");
- if(type.t & VT_BITFIELD)
- tcc_error("'%s' applied to a bit-field", get_tok_str(t, NULL));
vpushs(size);
} else {
vla_runtime_type_size(&type, &align);
@@ -3999,7 +3967,7 @@ ST_FUNC void unary(void)
#endif
)
tcc_warning("implicit declaration of function '%s'", name);
- s = external_sym(t, &func_old_type, 0, NULL);
+ s = external_global_sym(t, &func_old_type, 0);
}
if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
(VT_STATIC | VT_INLINE | VT_FUNC)) {
@@ -5048,11 +5016,11 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
nb_elems = 1;
if (gnu_ext && (l = is_label()) != 0)
goto struct_field;
- s = type->ref;
while (tok == '[' || tok == '.') {
if (tok == '[') {
if (!(type->t & VT_ARRAY))
expect("array type");
+ s = type->ref;
next();
index = expr_const();
if (index < 0 || (s->c >= 0 && index >= s->c))
@@ -5086,6 +5054,7 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
struct_field:
if ((type->t & VT_BTYPE) != VT_STRUCT)
expect("struct/union type");
+ s = type->ref;
l |= SYM_FIELD;
f = s->next;
while (f) {
@@ -5115,30 +5084,17 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
} else {
if (type->t & VT_ARRAY) {
index = *cur_index;
- if (s->c >= 0 && index >= s->c){
- if(!size_only)
- tcc_warning("excess elements in array initializer");
- type = NULL;
- size_only = 1;
- }else{
- type = pointed_type(type);
- c += index * type_size(type, &align);
- }
+ type = pointed_type(type);
+ c += index * type_size(type, &align);
} else {
f = *cur_field;
- if (f){
- /* XXX: fix this mess by using explicit storage field */
- type1 = f->type;
- type1.t |= (type->t & ~VT_TYPE);
- type = &type1;
- c += f->c;
- }else{
- if(!size_only)
- tcc_warning("excess elements in %s initializer",
- get_tok_str(s->type.t, NULL));
- type = NULL;
- size_only = 1;
- }
+ if (!f)
+ tcc_error("too many field init");
+ /* XXX: fix this mess by using explicit storage field */
+ type1 = f->type;
+ type1.t |= (type->t & ~VT_TYPE);
+ type = &type1;
+ c += f->c;
}
}
decl_initializer(type, sec, c, 0, size_only);
@@ -5298,8 +5254,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
Sym *s, *f;
CType *t1;
- if(!type)
- goto Ignore;
if (type->t & VT_VLA) {
int a;
@@ -5390,10 +5344,14 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
index = 0;
while (tok != '}') {
decl_designator(type, sec, c, &index, NULL, size_only);
+ if (n >= 0 && index >= n)
+ tcc_error("index too large");
/* must put zero in holes (note that doing it that way
ensures that it even works with designators) */
- if (!is_putz && array_length < index)
- is_putz = 1;
+ if (!size_only && array_length < index) {
+ init_putz(t1, sec, c + array_length * size1,
+ (index - array_length) * size1);
+ }
index++;
if (index > array_length)
array_length = index;
@@ -5410,8 +5368,10 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
if (!no_oblock)
skip('}');
/* put zeros at the end */
- if (!is_putz && n >= 0 && array_length < n)
- is_putz = 1;
+ if (!size_only && n >= 0 && array_length < n) {
+ init_putz(t1, sec, c + array_length * size1,
+ (n - array_length) * size1);
+ }
/* patch type size if needed */
if (n < 0)
s->c = array_length;
@@ -5457,44 +5417,46 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
n = s->c;
while (tok != '}') {
decl_designator(type, sec, c, NULL, &f, size_only);
- if(f){
- index = f->c;
- if (!is_putz && array_length < index)
- is_putz = 1;
- index = index + type_size(&f->type, &align1);
- if (index > array_length)
- array_length = index;
+ index = f->c;
+ if (!size_only && array_length < index) {
+ init_putz(type, sec, c + array_length,
+ index - array_length);
+ }
+ index = index + type_size(&f->type, &align1);
+ if (index > array_length)
+ array_length = index;
- /* gr: skip fields from same union - ugly. */
- while (f->next) {
- ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t);
- /* test for same offset */
- if (f->next->c != f->c)
+ /* gr: skip fields from same union - ugly. */
+ while (f->next) {
+ ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t);
+ /* test for same offset */
+ if (f->next->c != f->c)
+ break;
+ /* if yes, test for bitfield shift */
+ if ((f->type.t & VT_BITFIELD) && (f->next->type.t & VT_BITFIELD)) {
+ int bit_pos_1 = (f->type.t >> VT_STRUCT_SHIFT) & 0x3f;
+ int bit_pos_2 = (f->next->type.t >> VT_STRUCT_SHIFT) & 0x3f;
+ //printf("bitfield %d %d\n", bit_pos_1, bit_pos_2);
+ if (bit_pos_1 != bit_pos_2)
break;
- /* if yes, test for bitfield shift */
- if ((f->type.t & VT_BITFIELD) && (f->next->type.t & VT_BITFIELD)) {
- int bit_pos_1 = (f->type.t >> VT_STRUCT_SHIFT) & 0x3f;
- int bit_pos_2 = (f->next->type.t >> VT_STRUCT_SHIFT) & 0x3f;
- //printf("bitfield %d %d\n", bit_pos_1, bit_pos_2);
- if (bit_pos_1 != bit_pos_2)
- break;
- }
- f = f->next;
}
-
f = f->next;
- if (no_oblock && f == NULL)
- break;
}
+
+ f = f->next;
+ if (no_oblock && f == NULL)
+ break;
if (tok == '}')
break;
skip(',');
}
+ /* put zeros at the end */
+ if (!size_only && array_length < n) {
+ init_putz(type, sec, c + array_length,
+ n - array_length);
+ }
if (!no_oblock)
skip('}');
- /* put zeros at the end */
- if (!is_putz && array_length < n)
- is_putz = 1;
while (par_count) {
skip(')');
par_count--;
@@ -5504,7 +5466,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
decl_initializer(type, sec, c, first, size_only);
skip('}');
} else if (size_only) {
-Ignore:
/* just skip expression */
parlevel = parlevel1 = 0;
while ((parlevel > 0 || parlevel1 > 0 ||
@@ -5549,7 +5510,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
Sym *flexible_array;
flexible_array = NULL;
- is_putz = 0;
if ((type->t & VT_BTYPE) == VT_STRUCT) {
Sym *field = type->ref->next;
if (field) {
@@ -5568,8 +5528,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
literals). It also simplifies local
initializers handling */
tok_str_new(&init_str);
- if (size < 0 || ((((type->t & VT_BTYPE) == VT_STRUCT) || (type->t & VT_ARRAY)) &&
- has_init && (tok < TOK_IDENT))){
+ if (size < 0 || (flexible_array && has_init)) {
if (!has_init)
tcc_error("unknown type size");
/* get all init string */
@@ -5760,8 +5719,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
#endif
}
if (has_init || (type->t & VT_VLA)) {
- if(is_putz)
- init_putz(type, sec, addr, size);
decl_initializer(type, sec, addr, 1, 0);
/* restore parse state if needed */
if (init_str.str) {