Align struct members

This commit is contained in:
Rui Ueyama 2020-08-30 17:21:54 +09:00
parent d16f54ba0a
commit c821c4f709
5 changed files with 23 additions and 11 deletions

View File

@ -150,6 +150,7 @@ typedef enum {
struct Type {
TypeKind kind;
int size; // sizeof() value
int align; // alignment
// Pointer-to or array-of type. We intentionally use the same member
// to represent pointer/array duality in C.
@ -199,3 +200,4 @@ void add_type(Node *node);
//
void codegen(Var *prog, FILE *out);
int align_to(int n, int align);

View File

@ -33,7 +33,7 @@ static void pop(char *arg) {
// Round up `n` to the nearest multiple of `align`. For instance,
// align_to(5, 8) returns 8 and align_to(11, 8) returns 16.
static int align_to(int n, int align) {
int align_to(int n, int align) {
return (n + align - 1) / align * align;
}

View File

@ -592,14 +592,19 @@ static Type *struct_decl(Token **rest, Token *tok) {
Type *ty = calloc(1, sizeof(Type));
ty->kind = TY_STRUCT;
struct_members(rest, tok, ty);
ty->align = 1;
// Assign offsets within the struct to members.
int offset = 0;
for (Member *mem = ty->members; mem; mem = mem->next) {
offset = align_to(offset, mem->ty->align);
mem->offset = offset;
offset += mem->ty->size;
if (ty->align < mem->ty->align)
ty->align = mem->ty->align;
}
ty->size = offset;
ty->size = align_to(offset, ty->align);
return ty;
}

View File

@ -24,8 +24,9 @@ int main() {
ASSERT(32, ({ struct {int a;} x[4]; sizeof(x); }));
ASSERT(48, ({ struct {int a[3];} x[2]; sizeof(x); }));
ASSERT(2, ({ struct {char a; char b;} x; sizeof(x); }));
ASSERT(9, ({ struct {char a; int b;} x; sizeof(x); }));
ASSERT(0, ({ struct {} x; sizeof(x); }));
ASSERT(16, ({ struct {char a; int b;} x; sizeof(x); }));
ASSERT(16, ({ struct {int a; char b;} x; sizeof(x); }));
printf("OK\n");
return 0;

20
type.c
View File

@ -1,7 +1,15 @@
#include "chibicc.h"
Type *ty_char = &(Type){TY_CHAR, 1};
Type *ty_int = &(Type){TY_INT, 8};
Type *ty_char = &(Type){TY_CHAR, 1, 1};
Type *ty_int = &(Type){TY_INT, 8, 8};
static Type *new_type(TypeKind kind, int size, int align) {
Type *ty = calloc(1, sizeof(Type));
ty->kind = kind;
ty->size = size;
ty->align = align;
return ty;
}
bool is_integer(Type *ty) {
return ty->kind == TY_CHAR || ty->kind == TY_INT;
@ -14,9 +22,7 @@ Type *copy_type(Type *ty) {
}
Type *pointer_to(Type *base) {
Type *ty = calloc(1, sizeof(Type));
ty->kind = TY_PTR;
ty->size = 8;
Type *ty = new_type(TY_PTR, 8, 8);
ty->base = base;
return ty;
}
@ -29,9 +35,7 @@ Type *func_type(Type *return_ty) {
}
Type *array_of(Type *base, int len) {
Type *ty = calloc(1, sizeof(Type));
ty->kind = TY_ARRAY;
ty->size = base->size * len;
Type *ty = new_type(TY_ARRAY, base->size * len, base->align);
ty->base = base;
ty->array_len = len;
return ty;