Skip to content

Commit

Permalink
Add __attribute__((packed))
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Oct 15, 2020
1 parent 364fab6 commit 86e9f21
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 9 deletions.
1 change: 1 addition & 0 deletions chibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ struct Type {
// Struct
Member *members;
bool is_flexible;
bool is_packed;

// Function type
Type *return_ty;
Expand Down
36 changes: 27 additions & 9 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2595,8 +2595,26 @@ static void struct_members(Token **rest, Token *tok, Type *ty) {
ty->members = head.next;
}

// struct-union-decl = ident? ("{" struct-members)?
// attribute = ("__attribute__" "(" "(" "packed" ")" ")")?
static Token *attribute(Token *tok, Type *ty) {
if (!equal(tok, "__attribute__"))
return tok;

tok = tok->next;
tok = skip(tok, "(");
tok = skip(tok, "(");
tok = skip(tok, "packed");
tok = skip(tok, ")");
tok = skip(tok, ")");
ty->is_packed = true;
return tok;
}

// struct-union-decl = attribute? ident? ("{" struct-members)?
static Type *struct_union_decl(Token **rest, Token *tok) {
Type *ty = struct_type();
tok = attribute(tok, ty);

// Read a tag.
Token *tag = NULL;
if (tok->kind == TK_IDENT) {
Expand All @@ -2607,11 +2625,10 @@ static Type *struct_union_decl(Token **rest, Token *tok) {
if (tag && !equal(tok, "{")) {
*rest = tok;

Type *ty = find_tag(tag);
if (ty)
return ty;
Type *ty2 = find_tag(tag);
if (ty2)
return ty2;

ty = struct_type();
ty->size = -1;
push_tag_scope(tag, ty);
return ty;
Expand All @@ -2620,8 +2637,8 @@ static Type *struct_union_decl(Token **rest, Token *tok) {
tok = skip(tok, "{");

// Construct a struct object.
Type *ty = struct_type();
struct_members(rest, tok, ty);
struct_members(&tok, tok, ty);
*rest = attribute(tok, ty);

if (tag) {
// If this is a redefinition, overwrite a previous type.
Expand Down Expand Up @@ -2663,12 +2680,13 @@ static Type *struct_decl(Token **rest, Token *tok) {
mem->bit_offset = bits % (sz * 8);
bits += mem->bit_width;
} else {
bits = align_to(bits, mem->align * 8);
if (!ty->is_packed)
bits = align_to(bits, mem->align * 8);
mem->offset = bits / 8;
bits += mem->ty->size * 8;
}

if (ty->align < mem->align)
if (!ty->is_packed && ty->align < mem->align)
ty->align = mem->align;
}

Expand Down
21 changes: 21 additions & 0 deletions test/attribute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "test.h"
#include "stddef.h"

int main() {
ASSERT(5, ({ struct { char a; int b; } __attribute__((packed)) x; sizeof(x); }));
ASSERT(0, offsetof(struct __attribute__((packed)) { char a; int b; }, a));
ASSERT(1, offsetof(struct __attribute__((packed)) { char a; int b; }, b));

ASSERT(5, ({ struct __attribute__((packed)) { char a; int b; } x; sizeof(x); }));
ASSERT(0, offsetof(struct { char a; int b; } __attribute__((packed)), a));
ASSERT(1, offsetof(struct { char a; int b; } __attribute__((packed)), b));

ASSERT(9, ({ typedef struct { char a; int b[2]; } __attribute__((packed)) T; sizeof(T); }));
ASSERT(9, ({ typedef struct __attribute__((packed)) { char a; int b[2]; } T; sizeof(T); }));

ASSERT(1, offsetof(struct __attribute__((packed)) T { char a; int b[2]; }, b));
ASSERT(1, _Alignof(struct __attribute__((packed)) { char a; int b[2]; }));

printf("OK\n");
return 0;
}
1 change: 1 addition & 0 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ static bool is_keyword(Token *tok) {
"unsigned", "const", "volatile", "auto", "register", "restrict",
"__restrict", "__restrict__", "_Noreturn", "float", "double",
"typeof", "asm", "_Thread_local", "__thread", "_Atomic",
"__attribute__",
};

for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)
Expand Down

0 comments on commit 86e9f21

Please sign in to comment.