mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-19 07:20:50 +00:00
[qfcc] Adjust ivar offsets to preserve alignment
As a class's ivars are built up by inheritance, but with only that class's ivars in the symbol table, is is necessary to include an offset based on the super class's ivars in order to ensure alignments are respected. This is achieved via the new `base` parameter to build_struct(), which is used to offset the current size while calculating the aligned offset of the symbols. The parameter is ignored for unions, as they always start at 0. The ivars for the current class still have a base offset of 0 until they are actually added to the class. Fixes #29
This commit is contained in:
parent
f4ae24e0e0
commit
6253d775e6
3 changed files with 11 additions and 6 deletions
|
@ -46,7 +46,8 @@ typedef struct {
|
|||
struct symbol_s *find_struct (int su, struct symbol_s *tag,
|
||||
struct type_s *type);
|
||||
struct symbol_s *build_struct (int su, struct symbol_s *tag,
|
||||
struct symtab_s *symtab, struct type_s *type);
|
||||
struct symtab_s *symtab, struct type_s *type,
|
||||
int base);
|
||||
struct symbol_s *find_enum (struct symbol_s *tag);
|
||||
struct symtab_s *start_enum (struct symbol_s *enm);
|
||||
struct symbol_s *finish_enum (struct symbol_s *sym);
|
||||
|
|
|
@ -846,7 +846,7 @@ struct_specifier
|
|||
current_symtab = symtab->parent;
|
||||
|
||||
if ($1) {
|
||||
sym = build_struct ($1, $2, symtab, 0);
|
||||
sym = build_struct ($1, $2, symtab, 0, 0);
|
||||
$$ = make_spec (sym->type, 0, 0, 0);
|
||||
if (!sym->table)
|
||||
symtab_addsymbol (current_symtab, sym);
|
||||
|
@ -2051,7 +2051,11 @@ ivar_decl_list
|
|||
tab->parent = 0;
|
||||
|
||||
tab = $$->parent; // preserve the ivars inheritance chain
|
||||
build_struct ('s', 0, $$, 0);
|
||||
int base = 0;
|
||||
if ($<class>0->super_class) {
|
||||
base = type_size ($<class>0->super_class->type);
|
||||
}
|
||||
build_struct ('s', 0, $$, 0, base);
|
||||
$$->parent = tab;
|
||||
current_visibility = vis_public;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ find_struct (int su, symbol_t *tag, type_t *type)
|
|||
}
|
||||
|
||||
symbol_t *
|
||||
build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type)
|
||||
build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type, int base)
|
||||
{
|
||||
symbol_t *sym = find_struct (su, tag, type);
|
||||
symbol_t *s;
|
||||
|
@ -131,7 +131,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type)
|
|||
s->type->t.class->name);
|
||||
}
|
||||
if (su == 's') {
|
||||
symtab->size = RUP (symtab->size, s->type->alignment);
|
||||
symtab->size = RUP (symtab->size + base, s->type->alignment) - base;
|
||||
s->s.offset = symtab->size;
|
||||
symtab->size += type_size (s->type);
|
||||
} else {
|
||||
|
@ -304,7 +304,7 @@ make_structure (const char *name, int su, struct_def_t *defs, type_t *type)
|
|||
internal_error (0, "duplicate symbol: %s", defs->name);
|
||||
defs++;
|
||||
}
|
||||
sym = build_struct (su, sym, strct, type);
|
||||
sym = build_struct (su, sym, strct, type, 0);
|
||||
return sym;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue