Skip to content

Commit 71d335e

Browse files
committed
implement packed structs
closes #183
1 parent cd7713b commit 71d335e

File tree

12 files changed

+161
-118
lines changed

12 files changed

+161
-118
lines changed

doc/langref.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ GlobalVarDecl = VariableDeclaration ";"
1717
1818
VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
1919
20-
StructMember = (StructField | FnDef | GlobalVarDecl)
20+
ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2121
22-
StructField = Symbol option(":" Expression) ",")
22+
ContainerField = Symbol option(":" Expression) ",")
2323
2424
UseDecl = "use" Expression ";"
2525
@@ -155,7 +155,7 @@ GroupedExpression = "(" Expression ")"
155155
156156
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
157157
158-
ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}"
158+
ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
159159
160160
```
161161

doc/vim/syntax/zig.vim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ if exists("b:current_syntax")
88
endif
99
let b:current_syntax = "zig"
1010

11-
syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
11+
syn keyword zigStorage const var extern packed export pub noalias inline comptime nakedcc coldcc volatile
1212
syn keyword zigStructure struct enum union
13-
syn keyword zigStatement goto break return continue asm defer
13+
syn keyword zigStatement goto break return continue asm defer unreachable
1414
syn keyword zigConditional if else switch try
1515
syn keyword zigRepeat while for
1616

1717
syn keyword zigConstant null undefined zeroes this
1818
syn keyword zigKeyword fn use
19-
syn keyword zigType bool f32 f64 void unreachable type error
19+
syn keyword zigType bool f32 f64 void Unreachable type error
2020
syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize
2121
syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong c_long_double
2222

src/all_types.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,11 +621,17 @@ enum ContainerKind {
621621
ContainerKindUnion,
622622
};
623623

624+
enum ContainerLayout {
625+
ContainerLayoutAuto,
626+
ContainerLayoutExtern,
627+
ContainerLayoutPacked,
628+
};
629+
624630
struct AstNodeContainerDecl {
625631
ContainerKind kind;
626632
ZigList<AstNode *> fields;
627633
ZigList<AstNode *> decls;
628-
bool is_extern;
634+
ContainerLayout layout;
629635
};
630636

631637
struct AstNodeStructField {
@@ -820,7 +826,7 @@ struct TypeStructField {
820826
};
821827
struct TypeTableEntryStruct {
822828
AstNode *decl_node;
823-
bool is_extern;
829+
ContainerLayout layout;
824830
bool is_packed;
825831
uint32_t src_field_count;
826832
uint32_t gen_field_count;
@@ -850,7 +856,7 @@ struct TypeTableEntryError {
850856

851857
struct TypeTableEntryEnum {
852858
AstNode *decl_node;
853-
bool is_extern;
859+
ContainerLayout layout;
854860
uint32_t src_field_count;
855861
uint32_t gen_field_count;
856862
TypeEnumField *fields;
@@ -877,7 +883,7 @@ struct TypeTableEntryEnumTag {
877883

878884
struct TypeTableEntryUnion {
879885
AstNode *decl_node;
880-
bool is_extern;
886+
ContainerLayout layout;
881887
uint32_t src_field_count;
882888
uint32_t gen_field_count;
883889
TypeStructField *fields;

src/analyze.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -823,22 +823,24 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
823823
zig_unreachable();
824824
}
825825

826-
TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name, bool is_extern) {
826+
TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
827+
AstNode *decl_node, const char *name, ContainerLayout layout)
828+
{
827829
TypeTableEntryId type_id = container_to_type(kind);
828830
TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope);
829831

830832
switch (kind) {
831833
case ContainerKindStruct:
832834
entry->data.structure.decl_node = decl_node;
833-
entry->data.structure.is_extern = is_extern;
835+
entry->data.structure.layout = layout;
834836
break;
835837
case ContainerKindEnum:
836838
entry->data.enumeration.decl_node = decl_node;
837-
entry->data.enumeration.is_extern = is_extern;
839+
entry->data.enumeration.layout = layout;
838840
break;
839841
case ContainerKindUnion:
840842
entry->data.unionation.decl_node = decl_node;
841-
entry->data.unionation.is_extern = is_extern;
843+
entry->data.unionation.layout = layout;
842844
break;
843845
}
844846

@@ -1328,7 +1330,8 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
13281330
}
13291331
assert(struct_type->di_type);
13301332

1331-
LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, false);
1333+
bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
1334+
LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, packed);
13321335
assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0);
13331336

13341337
ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(gen_field_count);

src/analyze.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
2626
TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
2727
TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
2828
TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
29-
TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name, bool is_extern);
29+
TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
30+
AstNode *decl_node, const char *name, ContainerLayout layout);
3031
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
3132
TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
3233
TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);

src/ast_render.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ static const char *defer_string(ReturnKind kind) {
104104
zig_unreachable();
105105
}
106106

107+
static const char *layout_string(ContainerLayout layout) {
108+
switch (layout) {
109+
case ContainerLayoutAuto: return "";
110+
case ContainerLayoutExtern: return "extern ";
111+
case ContainerLayoutPacked: return "packed ";
112+
}
113+
zig_unreachable();
114+
}
115+
107116
static const char *extern_string(bool is_extern) {
108117
return is_extern ? "extern " : "";
109118
}
@@ -970,8 +979,8 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
970979
{
971980
TypeTableEntry *type_entry = var->value.data.x_type;
972981
if (type_entry->id == TypeTableEntryIdStruct) {
973-
const char *extern_str = extern_string(type_entry->data.structure.is_extern);
974-
fprintf(ar->f, "%sstruct {\n", extern_str);
982+
const char *layout_str = layout_string(type_entry->data.structure.layout);
983+
fprintf(ar->f, "%sstruct {\n", layout_str);
975984
if (type_entry->data.structure.complete) {
976985
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
977986
TypeStructField *field = &type_entry->data.structure.fields[i];
@@ -982,8 +991,8 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
982991
}
983992
fprintf(ar->f, "}");
984993
} else if (type_entry->id == TypeTableEntryIdEnum) {
985-
const char *extern_str = extern_string(type_entry->data.enumeration.is_extern);
986-
fprintf(ar->f, "%senum {\n", extern_str);
994+
const char *layout_str = layout_string(type_entry->data.enumeration.layout);
995+
fprintf(ar->f, "%senum {\n", layout_str);
987996
if (type_entry->data.enumeration.complete) {
988997
for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) {
989998
TypeEnumField *field = &type_entry->data.enumeration.fields[i];

src/ir.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5283,8 +5283,9 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope,
52835283
TldContainer *tld_container = allocate<TldContainer>(1);
52845284
init_tld(&tld_container->base, TldIdContainer, name, visib_mod, node, parent_scope);
52855285

5286-
TypeTableEntry *container_type = get_partial_container_type(irb->codegen, parent_scope, kind, node, buf_ptr(name),
5287-
node->data.container_decl.is_extern);
5286+
ContainerLayout layout = node->data.container_decl.layout;
5287+
TypeTableEntry *container_type = get_partial_container_type(irb->codegen, parent_scope,
5288+
kind, node, buf_ptr(name), layout);
52885289
ScopeDecls *child_scope = get_container_scope(container_type);
52895290

52905291
tld_container->type_entry = container_type;

src/parseh.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
720720
const EnumDecl *enum_def = enum_decl->getDefinition();
721721
if (!enum_def) {
722722
TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
723-
ContainerKindEnum, c->source_node, buf_ptr(full_type_name), true);
723+
ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
724724
enum_type->data.enumeration.zero_bits_known = true;
725725
c->enum_type_table.put(bare_name, enum_type);
726726
c->decl_table.put(enum_decl, enum_type);
@@ -745,7 +745,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
745745

746746
if (pure_enum) {
747747
TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
748-
ContainerKindEnum, c->source_node, buf_ptr(full_type_name), true);
748+
ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
749749
c->enum_type_table.put(bare_name, enum_type);
750750
c->decl_table.put(enum_decl, enum_type);
751751

@@ -885,7 +885,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
885885

886886

887887
TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
888-
ContainerKindStruct, c->source_node, buf_ptr(full_type_name), true);
888+
ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
889889
struct_type->data.structure.zero_bits_known = true;
890890

891891
c->struct_type_table.put(bare_name, struct_type);

src/parser.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,21 +2275,24 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
22752275
}
22762276

22772277
/*
2278-
ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}"
2279-
StructMember = (StructField | FnDef | GlobalVarDecl)
2280-
StructField = Symbol option(":" Expression) ",")
2278+
ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
2279+
ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2280+
ContainerField = Symbol option(":" Expression) ",")
22812281
*/
22822282
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {
22832283
Token *first_token = &pc->tokens->at(*token_index);
22842284
Token *container_kind_token;
22852285

2286-
bool is_extern;
2286+
ContainerLayout layout;
22872287
if (first_token->id == TokenIdKeywordExtern) {
22882288
container_kind_token = &pc->tokens->at(*token_index + 1);
2289-
is_extern = true;
2289+
layout = ContainerLayoutExtern;
2290+
} else if (first_token->id == TokenIdKeywordPacked) {
2291+
container_kind_token = &pc->tokens->at(*token_index + 1);
2292+
layout = ContainerLayoutPacked;
22902293
} else {
22912294
container_kind_token = first_token;
2292-
is_extern = false;
2295+
layout = ContainerLayoutAuto;
22932296
}
22942297

22952298
ContainerKind kind;
@@ -2304,10 +2307,10 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
23042307
} else {
23052308
return nullptr;
23062309
}
2307-
*token_index += is_extern ? 2 : 1;
2310+
*token_index += (layout == ContainerLayoutAuto) ? 1 : 2;
23082311

23092312
AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);
2310-
node->data.container_decl.is_extern = is_extern;
2313+
node->data.container_decl.layout = layout;
23112314
node->data.container_decl.kind = kind;
23122315

23132316
ast_eat_token(pc, token_index, TokenIdLBrace);

src/tokenizer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ static const struct ZigKeyword zig_keywords[] = {
128128
{"nakedcc", TokenIdKeywordNakedCC},
129129
{"noalias", TokenIdKeywordNoAlias},
130130
{"null", TokenIdKeywordNull},
131+
{"packed", TokenIdKeywordPacked},
131132
{"pub", TokenIdKeywordPub},
132133
{"return", TokenIdKeywordReturn},
133134
{"struct", TokenIdKeywordStruct},
@@ -1502,6 +1503,7 @@ const char * token_name(TokenId id) {
15021503
case TokenIdKeywordNakedCC: return "nakedcc";
15031504
case TokenIdKeywordNoAlias: return "noalias";
15041505
case TokenIdKeywordNull: return "null";
1506+
case TokenIdKeywordPacked: return "packed";
15051507
case TokenIdKeywordPub: return "pub";
15061508
case TokenIdKeywordReturn: return "return";
15071509
case TokenIdKeywordStruct: return "struct";

0 commit comments

Comments
 (0)