Make an array of at least 16 bytes long to have alignment of at least 16 bytes

Quote from AMD64 System V ABI: "An array uses the same alignment as
its elements, except that a local or global array variable of length
at least 16 bytes or a C99 variable-length array variable always has
alignment of at least 16 bytes."
This commit is contained in:
Rui Ueyama 2020-05-10 20:15:32 +09:00
parent 2c91da54df
commit 5257ee0f20
2 changed files with 16 additions and 2 deletions

View File

@ -1102,8 +1102,15 @@ static void assign_lvar_offsets(Obj *prog) {
if (var->offset)
continue;
// AMD64 System V ABI has a special alignment rule for an array of
// length at least 16 bytes. We need to align such array to at least
// 16-byte boundaries. See p.14 of
// https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-draft.pdf.
int align = (var->ty->kind == TY_ARRAY && var->ty->size >= 16)
? MAX(16, var->align) : var->align;
bottom += var->ty->size;
bottom = align_to(bottom, var->align);
bottom = align_to(bottom, align);
var->offset = -bottom;
}
@ -1121,7 +1128,9 @@ static void emit_data(Obj *prog) {
else
println(" .globl %s", var->name);
println(" .align %d", var->align);
int align = (var->ty->kind == TY_ARRAY && var->ty->size >= 16)
? MAX(16, var->align) : var->align;
println(" .align %d", align);
if (var->init_data) {
println(" .data");

View File

@ -39,6 +39,11 @@ int main() {
ASSERT(1, _Alignof(char) << 63 >> 63);
ASSERT(1, ({ char x; _Alignof(x) << 63 >> 63; }));
ASSERT(0, ({ char x[16]; (unsigned long)&x % 16; }));
ASSERT(0, ({ char x[17]; (unsigned long)&x % 16; }));
ASSERT(0, ({ char x[100]; (unsigned long)&x % 16; }));
ASSERT(0, ({ char x[101]; (unsigned long)&x % 16; }));
printf("OK\n");
return 0;
}