authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 11:39:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 11:39:24-05:00
log71d335e5ccc5c7c37ac40debf78ad3aa096b22d3
treeb64024a77a76bf26ed77596125c046321edfb4ff
parentcd7713b1788aeeadf6c46def38d4ef4fa313fe75

implement packed structs

closes #183

12 files changed, 161 insertions(+), 118 deletions(-)

doc/langref.md+3-3
......@@ -17,9 +17,9 @@ GlobalVarDecl = VariableDeclaration ";"
1717
1818VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
1919
20StructMember = (StructField | FnDef | GlobalVarDecl)
20ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2121
22StructField = Symbol option(":" Expression) ",")
22ContainerField = Symbol option(":" Expression) ",")
2323
2424UseDecl = "use" Expression ";"
2525
......@@ -155,7 +155,7 @@ GroupedExpression = "(" Expression ")"
155155
156156KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
157157
158ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}"
158ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
159159
160160```
161161
doc/vim/syntax/zig.vim+3-3
......@@ -8,15 +8,15 @@ if exists("b:current_syntax")
88endif
99let b:current_syntax = "zig"
1010
11syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
11syn keyword zigStorage const var extern packed export pub noalias inline comptime nakedcc coldcc volatile
1212syn keyword zigStructure struct enum union
13syn keyword zigStatement goto break return continue asm defer
13syn keyword zigStatement goto break return continue asm defer unreachable
1414syn keyword zigConditional if else switch try
1515syn keyword zigRepeat while for
1616
1717syn keyword zigConstant null undefined zeroes this
1818syn keyword zigKeyword fn use
19syn keyword zigType bool f32 f64 void unreachable type error
19syn keyword zigType bool f32 f64 void Unreachable type error
2020syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize
2121syn 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+10-4
......@@ -621,11 +621,17 @@ enum ContainerKind {
621621 ContainerKindUnion,
622622};
623623
624enum ContainerLayout {
625 ContainerLayoutAuto,
626 ContainerLayoutExtern,
627 ContainerLayoutPacked,
628};
629
624630struct AstNodeContainerDecl {
625631 ContainerKind kind;
626632 ZigList<AstNode *> fields;
627633 ZigList<AstNode *> decls;
628 bool is_extern;
634 ContainerLayout layout;
629635};
630636
631637struct AstNodeStructField {
......@@ -820,7 +826,7 @@ struct TypeStructField {
820826};
821827struct 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
851857struct 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
878884struct 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+8-5
......@@ -823,22 +823,24 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
823823 zig_unreachable();
824824}
825825
826TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name, bool is_extern) {
826TypeTableEntry *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+2-1
......@@ -26,7 +26,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
2626TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
2727TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
2828TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
29TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name, bool is_extern);
29TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
30 AstNode *decl_node, const char *name, ContainerLayout layout);
3031TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
3132TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
3233TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
src/ast_render.cpp+13-4
......@@ -104,6 +104,15 @@ static const char *defer_string(ReturnKind kind) {
104104 zig_unreachable();
105105}
106106
107static 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
107116static 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+3-2
......@@ -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+3-3
......@@ -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+11-8
......@@ -2275,21 +2275,24 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
22752275}
22762276
22772277/*
2278ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}"
2279StructMember = (StructField | FnDef | GlobalVarDecl)
2280StructField = Symbol option(":" Expression) ",")
2278ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
2279ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2280ContainerField = Symbol option(":" Expression) ",")
22812281*/
22822282static 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+2
......@@ -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";
src/tokenizer.hpp+86-85
......@@ -12,109 +12,110 @@
1212#include "bignum.hpp"
1313
1414enum TokenId {
15 TokenIdEof,
16 TokenIdSymbol,
17 TokenIdKeywordFn,
18 TokenIdKeywordReturn,
19 TokenIdKeywordVar,
20 TokenIdKeywordConst,
21 TokenIdKeywordExtern,
22 TokenIdKeywordPub,
23 TokenIdKeywordUse,
24 TokenIdKeywordExport,
25 TokenIdKeywordTrue,
26 TokenIdKeywordFalse,
27 TokenIdKeywordIf,
28 TokenIdKeywordTry,
29 TokenIdKeywordElse,
30 TokenIdKeywordGoto,
31 TokenIdKeywordAsm,
32 TokenIdKeywordVolatile,
33 TokenIdKeywordStruct,
34 TokenIdKeywordEnum,
35 TokenIdKeywordUnion,
36 TokenIdKeywordWhile,
37 TokenIdKeywordFor,
38 TokenIdKeywordContinue,
39 TokenIdKeywordBreak,
40 TokenIdKeywordNull,
41 TokenIdKeywordNoAlias,
42 TokenIdKeywordSwitch,
43 TokenIdKeywordUndefined,
44 TokenIdKeywordError,
45 TokenIdKeywordType,
46 TokenIdKeywordInline,
47 TokenIdKeywordCompTime,
48 TokenIdKeywordDefer,
49 TokenIdKeywordThis,
50 TokenIdKeywordColdCC,
51 TokenIdKeywordNakedCC,
52 TokenIdLParen,
53 TokenIdRParen,
54 TokenIdComma,
55 TokenIdStar,
56 TokenIdStarStar,
57 TokenIdLBrace,
58 TokenIdRBrace,
59 TokenIdLBracket,
60 TokenIdRBracket,
61 TokenIdStringLiteral,
62 TokenIdCharLiteral,
63 TokenIdSemicolon,
64 TokenIdNumberLiteral,
65 TokenIdPlus,
66 TokenIdPlusPlus,
67 TokenIdColon,
15 TokenIdAmpersand,
6816 TokenIdArrow,
69 TokenIdFatArrow,
70 TokenIdDash,
71 TokenIdNumberSign,
72 TokenIdBoolOr,
73 TokenIdBoolAnd,
17 TokenIdAtSign,
18 TokenIdBang,
7419 TokenIdBinOr,
75 TokenIdAmpersand,
7620 TokenIdBinXor,
77 TokenIdEq,
78 TokenIdTimesEq,
79 TokenIdTimesPercent,
80 TokenIdTimesPercentEq,
81 TokenIdDivEq,
82 TokenIdModEq,
83 TokenIdPlusEq,
84 TokenIdPlusPercent,
85 TokenIdPlusPercentEq,
86 TokenIdMinusEq,
87 TokenIdMinusPercent,
88 TokenIdMinusPercentEq,
21 TokenIdBitAndEq,
22 TokenIdBitOrEq,
23 TokenIdBitShiftLeft,
8924 TokenIdBitShiftLeftEq,
9025 TokenIdBitShiftLeftPercent,
9126 TokenIdBitShiftLeftPercentEq,
27 TokenIdBitShiftRight,
9228 TokenIdBitShiftRightEq,
93 TokenIdBitAndEq,
9429 TokenIdBitXorEq,
95 TokenIdBitOrEq,
30 TokenIdBoolAnd,
9631 TokenIdBoolAndEq,
32 TokenIdBoolOr,
9733 TokenIdBoolOrEq,
34 TokenIdCharLiteral,
9835 TokenIdCmpEq,
99 TokenIdBang,
100 TokenIdTilde,
101 TokenIdCmpNotEq,
102 TokenIdCmpLessThan,
36 TokenIdCmpGreaterOrEq,
10337 TokenIdCmpGreaterThan,
10438 TokenIdCmpLessOrEq,
105 TokenIdCmpGreaterOrEq,
106 TokenIdBitShiftLeft,
107 TokenIdBitShiftRight,
108 TokenIdSlash,
109 TokenIdPercent,
110 TokenIdPercentPercent,
39 TokenIdCmpLessThan,
40 TokenIdCmpNotEq,
41 TokenIdColon,
42 TokenIdComma,
43 TokenIdDash,
44 TokenIdDivEq,
11145 TokenIdDot,
46 TokenIdDoubleQuestion,
11247 TokenIdEllipsis,
48 TokenIdEof,
49 TokenIdEq,
50 TokenIdFatArrow,
51 TokenIdKeywordAsm,
52 TokenIdKeywordBreak,
53 TokenIdKeywordColdCC,
54 TokenIdKeywordCompTime,
55 TokenIdKeywordConst,
56 TokenIdKeywordContinue,
57 TokenIdKeywordDefer,
58 TokenIdKeywordElse,
59 TokenIdKeywordEnum,
60 TokenIdKeywordError,
61 TokenIdKeywordExport,
62 TokenIdKeywordExtern,
63 TokenIdKeywordFalse,
64 TokenIdKeywordFn,
65 TokenIdKeywordFor,
66 TokenIdKeywordGoto,
67 TokenIdKeywordIf,
68 TokenIdKeywordInline,
69 TokenIdKeywordNakedCC,
70 TokenIdKeywordNoAlias,
71 TokenIdKeywordNull,
72 TokenIdKeywordPacked,
73 TokenIdKeywordPub,
74 TokenIdKeywordReturn,
75 TokenIdKeywordStruct,
76 TokenIdKeywordSwitch,
77 TokenIdKeywordThis,
78 TokenIdKeywordTrue,
79 TokenIdKeywordTry,
80 TokenIdKeywordType,
81 TokenIdKeywordUndefined,
82 TokenIdKeywordUnion,
83 TokenIdKeywordUse,
84 TokenIdKeywordVar,
85 TokenIdKeywordVolatile,
86 TokenIdKeywordWhile,
87 TokenIdLBrace,
88 TokenIdLBracket,
89 TokenIdLParen,
11390 TokenIdMaybe,
114 TokenIdDoubleQuestion,
11591 TokenIdMaybeAssign,
116 TokenIdAtSign,
92 TokenIdMinusEq,
93 TokenIdMinusPercent,
94 TokenIdMinusPercentEq,
95 TokenIdModEq,
96 TokenIdNumberLiteral,
97 TokenIdNumberSign,
98 TokenIdPercent,
11799 TokenIdPercentDot,
100 TokenIdPercentPercent,
101 TokenIdPlus,
102 TokenIdPlusEq,
103 TokenIdPlusPercent,
104 TokenIdPlusPercentEq,
105 TokenIdPlusPlus,
106 TokenIdRBrace,
107 TokenIdRBracket,
108 TokenIdRParen,
109 TokenIdSemicolon,
110 TokenIdSlash,
111 TokenIdStar,
112 TokenIdStarStar,
113 TokenIdStringLiteral,
114 TokenIdSymbol,
115 TokenIdTilde,
116 TokenIdTimesEq,
117 TokenIdTimesPercent,
118 TokenIdTimesPercentEq,
118119};
119120
120121struct TokenNumLit {
test/cases/struct.zig+17
......@@ -208,3 +208,20 @@ fn passSliceOfEmptyStructToFn() {
208208fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {
209209 slice.len
210210}
211
212const APackedStruct = packed struct {
213 x: u8,
214 y: u8,
215};
216
217fn packedStruct() {
218 @setFnTest(this);
219
220 var foo = APackedStruct {
221 .x = 1,
222 .y = 2,
223 };
224 foo.y += 1;
225 const four = foo.x + foo.y;
226 assert(four == 4);
227}