mirror of
https://github.com/frida/tinycc
synced 2025-01-13 07:09:17 +03:00
Fix more struct inits
anonymous struct members were somewhat broken as the testcase demonstrates. The reason is the jumping through hoops to fiddle with the offsets I once introduced to avoid having to track a cumulative offset. That's now not necessary anymore and actively harmful, doing the obvious thing is now better.
This commit is contained in:
parent
94846d3eef
commit
0344c0b6a0
65
tccgen.c
65
tccgen.c
@ -3588,7 +3588,7 @@ redo:
|
|||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sym * find_field (CType *type, int v)
|
static Sym * find_field (CType *type, int v, int *cumofs)
|
||||||
{
|
{
|
||||||
Sym *s = type->ref;
|
Sym *s = type->ref;
|
||||||
v |= SYM_FIELD;
|
v |= SYM_FIELD;
|
||||||
@ -3596,28 +3596,18 @@ static Sym * find_field (CType *type, int v)
|
|||||||
if ((s->v & SYM_FIELD) &&
|
if ((s->v & SYM_FIELD) &&
|
||||||
(s->type.t & VT_BTYPE) == VT_STRUCT &&
|
(s->type.t & VT_BTYPE) == VT_STRUCT &&
|
||||||
(s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
|
(s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
|
||||||
Sym *ret = find_field (&s->type, v);
|
Sym *ret = find_field (&s->type, v, cumofs);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
*cumofs += s->c;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (s->v == v)
|
if (s->v == v)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void struct_add_offset (Sym *s, int offset)
|
|
||||||
{
|
|
||||||
while ((s = s->next) != NULL) {
|
|
||||||
if ((s->v & SYM_FIELD) &&
|
|
||||||
(s->type.t & VT_BTYPE) == VT_STRUCT &&
|
|
||||||
(s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
|
|
||||||
struct_add_offset(s->type.ref, offset);
|
|
||||||
} else
|
|
||||||
s->c += offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void struct_layout(CType *type, AttributeDef *ad)
|
static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
{
|
{
|
||||||
int size, align, maxalign, offset, c, bit_pos, bit_size;
|
int size, align, maxalign, offset, c, bit_pos, bit_size;
|
||||||
@ -3767,41 +3757,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (f->v & SYM_FIRST_ANOM && (f->type.t & VT_BTYPE) == VT_STRUCT) {
|
|
||||||
Sym *ass;
|
|
||||||
/* An anonymous struct/union. Adjust member offsets
|
|
||||||
to reflect the real offset of our containing struct.
|
|
||||||
Also set the offset of this anon member inside
|
|
||||||
the outer struct to be zero. Via this it
|
|
||||||
works when accessing the field offset directly
|
|
||||||
(from base object), as well as when recursing
|
|
||||||
members in initializer handling. */
|
|
||||||
int v2 = f->type.ref->v;
|
|
||||||
if (!(v2 & SYM_FIELD) &&
|
|
||||||
(v2 & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
|
|
||||||
Sym **pps;
|
|
||||||
/* This happens only with MS extensions. The
|
|
||||||
anon member has a named struct type, so it
|
|
||||||
potentially is shared with other references.
|
|
||||||
We need to unshare members so we can modify
|
|
||||||
them. */
|
|
||||||
ass = f->type.ref;
|
|
||||||
f->type.ref = sym_push(anon_sym++ | SYM_FIELD,
|
|
||||||
&f->type.ref->type, 0,
|
|
||||||
f->type.ref->c);
|
|
||||||
pps = &f->type.ref->next;
|
|
||||||
while ((ass = ass->next) != NULL) {
|
|
||||||
*pps = sym_push(ass->v, &ass->type, 0, ass->c);
|
|
||||||
pps = &((*pps)->next);
|
|
||||||
}
|
|
||||||
*pps = NULL;
|
|
||||||
}
|
|
||||||
struct_add_offset(f->type.ref, offset);
|
|
||||||
f->c = 0;
|
|
||||||
} else {
|
|
||||||
f->c = offset;
|
f->c = offset;
|
||||||
}
|
|
||||||
|
|
||||||
f->r = 0;
|
f->r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5331,7 +5287,7 @@ special_math_val:
|
|||||||
inc(1, tok);
|
inc(1, tok);
|
||||||
next();
|
next();
|
||||||
} else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) {
|
} else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) {
|
||||||
int qualifiers;
|
int qualifiers, cumofs = 0;
|
||||||
/* field */
|
/* field */
|
||||||
if (tok == TOK_ARROW)
|
if (tok == TOK_ARROW)
|
||||||
indir();
|
indir();
|
||||||
@ -5346,12 +5302,12 @@ special_math_val:
|
|||||||
next();
|
next();
|
||||||
if (tok == TOK_CINT || tok == TOK_CUINT)
|
if (tok == TOK_CINT || tok == TOK_CUINT)
|
||||||
expect("field name");
|
expect("field name");
|
||||||
s = find_field(&vtop->type, tok);
|
s = find_field(&vtop->type, tok, &cumofs);
|
||||||
if (!s)
|
if (!s)
|
||||||
tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, &tokc));
|
tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, &tokc));
|
||||||
/* add field offset to pointer */
|
/* add field offset to pointer */
|
||||||
vtop->type = char_pointer_type; /* change type to 'char *' */
|
vtop->type = char_pointer_type; /* change type to 'char *' */
|
||||||
vpushi(s->c);
|
vpushi(cumofs + s->c);
|
||||||
gen_op('+');
|
gen_op('+');
|
||||||
/* change type to field type, and set to lvalue */
|
/* change type to field type, and set to lvalue */
|
||||||
vtop->type = s->type;
|
vtop->type = s->type;
|
||||||
@ -6674,19 +6630,20 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
|
|||||||
c += index * elem_size;
|
c += index * elem_size;
|
||||||
nb_elems = index_last - index + 1;
|
nb_elems = index_last - index + 1;
|
||||||
} else {
|
} else {
|
||||||
|
int cumofs = 0;
|
||||||
next();
|
next();
|
||||||
l = tok;
|
l = tok;
|
||||||
struct_field:
|
struct_field:
|
||||||
next();
|
next();
|
||||||
if ((type->t & VT_BTYPE) != VT_STRUCT)
|
if ((type->t & VT_BTYPE) != VT_STRUCT)
|
||||||
expect("struct/union type");
|
expect("struct/union type");
|
||||||
f = find_field(type, l);
|
f = find_field(type, l, &cumofs);
|
||||||
if (!f)
|
if (!f)
|
||||||
expect("field");
|
expect("field");
|
||||||
if (cur_field)
|
if (cur_field)
|
||||||
*cur_field = f;
|
*cur_field = f;
|
||||||
type = &f->type;
|
type = &f->type;
|
||||||
c += f->c;
|
c += cumofs + f->c;
|
||||||
}
|
}
|
||||||
cur_field = NULL;
|
cur_field = NULL;
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,13 @@ union UV guv = {{6,5}};
|
|||||||
union UV guv2 = {{.b = 7, .a = 8}};
|
union UV guv2 = {{.b = 7, .a = 8}};
|
||||||
union UV guv3 = {.b = 8, .a = 7};
|
union UV guv3 = {.b = 8, .a = 7};
|
||||||
|
|
||||||
|
struct SSU {
|
||||||
|
int y;
|
||||||
|
struct { int x; };
|
||||||
|
};
|
||||||
|
struct SSU gssu1 = { .y = 5, .x = 3 };
|
||||||
|
struct SSU gssu2 = { 5, 3 };
|
||||||
|
|
||||||
/* Under -fms-extensions also the following is valid:
|
/* Under -fms-extensions also the following is valid:
|
||||||
union UV2 {
|
union UV2 {
|
||||||
struct Anon {u8 a,b;}; // unnamed member, but tagged struct, ...
|
struct Anon {u8 a,b;}; // unnamed member, but tagged struct, ...
|
||||||
@ -166,6 +173,8 @@ void foo (struct W *w, struct pkthdr *phdr_)
|
|||||||
int elt = 0x42;
|
int elt = 0x42;
|
||||||
/* Range init, overlapping */
|
/* Range init, overlapping */
|
||||||
struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 };
|
struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 };
|
||||||
|
struct SSU lssu1 = { 5, 3 };
|
||||||
|
struct SSU lssu2 = { .y = 5, .x = 3 };
|
||||||
print(ls);
|
print(ls);
|
||||||
print(ls2);
|
print(ls2);
|
||||||
print(lt);
|
print(lt);
|
||||||
@ -182,6 +191,8 @@ void foo (struct W *w, struct pkthdr *phdr_)
|
|||||||
print(lv2);
|
print(lv2);
|
||||||
print(lv3);
|
print(lv3);
|
||||||
print(lt2);
|
print(lt2);
|
||||||
|
print(lssu1);
|
||||||
|
print(lssu2);
|
||||||
print(flow);
|
print(flow);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -272,6 +283,8 @@ int main()
|
|||||||
print(guv.b);
|
print(guv.b);
|
||||||
print(guv2);
|
print(guv2);
|
||||||
print(guv3);
|
print(guv3);
|
||||||
|
print(gssu1);
|
||||||
|
print(gssu2);
|
||||||
print(phdr);
|
print(phdr);
|
||||||
foo(&gw, &phdr);
|
foo(&gw, &phdr);
|
||||||
//printf("q: %s\n", q);
|
//printf("q: %s\n", q);
|
||||||
|
@ -17,6 +17,8 @@ guv: 6 5 0 0
|
|||||||
guv.b: 5
|
guv.b: 5
|
||||||
guv2: 8 7 0 0
|
guv2: 8 7 0 0
|
||||||
guv3: 7 8 0 0
|
guv3: 7 8 0 0
|
||||||
|
gssu1: 5 0 0 0 3 0 0 0
|
||||||
|
gssu2: 5 0 0 0 3 0 0 0
|
||||||
phdr: 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0
|
phdr: 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0
|
||||||
ls: 1 2 3 4
|
ls: 1 2 3 4
|
||||||
ls2: 1 2 3 4
|
ls2: 1 2 3 4
|
||||||
@ -34,6 +36,8 @@ lv: 3 4 5 6 68 61 68 61 0 0 0 0 0 0 0 0 0 0 0 0 2d 2e
|
|||||||
lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30
|
lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30
|
||||||
lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
|
lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
|
||||||
lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1
|
lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1
|
||||||
|
lssu1: 5 0 0 0 3 0 0 0
|
||||||
|
lssu2: 5 0 0 0 3 0 0 0
|
||||||
flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0
|
flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0
|
||||||
one
|
one
|
||||||
two
|
two
|
||||||
|
Loading…
Reference in New Issue
Block a user