Commit 71d335e5cc
Changed files (12)
doc/vim/syntax/zig.vim
@@ -8,15 +8,15 @@ if exists("b:current_syntax")
endif
let b:current_syntax = "zig"
-syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
+syn keyword zigStorage const var extern packed export pub noalias inline comptime nakedcc coldcc volatile
syn keyword zigStructure struct enum union
-syn keyword zigStatement goto break return continue asm defer
+syn keyword zigStatement goto break return continue asm defer unreachable
syn keyword zigConditional if else switch try
syn keyword zigRepeat while for
syn keyword zigConstant null undefined zeroes this
syn keyword zigKeyword fn use
-syn keyword zigType bool f32 f64 void unreachable type error
+syn keyword zigType bool f32 f64 void Unreachable type error
syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize
syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong c_long_double
doc/langref.md
@@ -17,9 +17,9 @@ GlobalVarDecl = VariableDeclaration ";"
VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
-StructMember = (StructField | FnDef | GlobalVarDecl)
+ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
-StructField = Symbol option(":" Expression) ",")
+ContainerField = Symbol option(":" Expression) ",")
UseDecl = "use" Expression ";"
@@ -155,7 +155,7 @@ GroupedExpression = "(" Expression ")"
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
-ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}"
+ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
```
src/all_types.hpp
@@ -621,11 +621,17 @@ enum ContainerKind {
ContainerKindUnion,
};
+enum ContainerLayout {
+ ContainerLayoutAuto,
+ ContainerLayoutExtern,
+ ContainerLayoutPacked,
+};
+
struct AstNodeContainerDecl {
ContainerKind kind;
ZigList<AstNode *> fields;
ZigList<AstNode *> decls;
- bool is_extern;
+ ContainerLayout layout;
};
struct AstNodeStructField {
@@ -820,7 +826,7 @@ struct TypeStructField {
};
struct TypeTableEntryStruct {
AstNode *decl_node;
- bool is_extern;
+ ContainerLayout layout;
bool is_packed;
uint32_t src_field_count;
uint32_t gen_field_count;
@@ -850,7 +856,7 @@ struct TypeTableEntryError {
struct TypeTableEntryEnum {
AstNode *decl_node;
- bool is_extern;
+ ContainerLayout layout;
uint32_t src_field_count;
uint32_t gen_field_count;
TypeEnumField *fields;
@@ -877,7 +883,7 @@ struct TypeTableEntryEnumTag {
struct TypeTableEntryUnion {
AstNode *decl_node;
- bool is_extern;
+ ContainerLayout layout;
uint32_t src_field_count;
uint32_t gen_field_count;
TypeStructField *fields;
src/analyze.cpp
@@ -823,22 +823,24 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
zig_unreachable();
}
-TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name, bool is_extern) {
+TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
+ AstNode *decl_node, const char *name, ContainerLayout layout)
+{
TypeTableEntryId type_id = container_to_type(kind);
TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope);
switch (kind) {
case ContainerKindStruct:
entry->data.structure.decl_node = decl_node;
- entry->data.structure.is_extern = is_extern;
+ entry->data.structure.layout = layout;
break;
case ContainerKindEnum:
entry->data.enumeration.decl_node = decl_node;
- entry->data.enumeration.is_extern = is_extern;
+ entry->data.enumeration.layout = layout;
break;
case ContainerKindUnion:
entry->data.unionation.decl_node = decl_node;
- entry->data.unionation.is_extern = is_extern;
+ entry->data.unionation.layout = layout;
break;
}
@@ -1328,7 +1330,8 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
}
assert(struct_type->di_type);
- LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, false);
+ bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
+ LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, packed);
assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0);
ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(gen_field_count);
src/analyze.hpp
@@ -26,7 +26,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
-TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name, bool is_extern);
+TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
+ AstNode *decl_node, const char *name, ContainerLayout layout);
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
src/ast_render.cpp
@@ -104,6 +104,15 @@ static const char *defer_string(ReturnKind kind) {
zig_unreachable();
}
+static const char *layout_string(ContainerLayout layout) {
+ switch (layout) {
+ case ContainerLayoutAuto: return "";
+ case ContainerLayoutExtern: return "extern ";
+ case ContainerLayoutPacked: return "packed ";
+ }
+ zig_unreachable();
+}
+
static const char *extern_string(bool is_extern) {
return is_extern ? "extern " : "";
}
@@ -970,8 +979,8 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
{
TypeTableEntry *type_entry = var->value.data.x_type;
if (type_entry->id == TypeTableEntryIdStruct) {
- const char *extern_str = extern_string(type_entry->data.structure.is_extern);
- fprintf(ar->f, "%sstruct {\n", extern_str);
+ const char *layout_str = layout_string(type_entry->data.structure.layout);
+ fprintf(ar->f, "%sstruct {\n", layout_str);
if (type_entry->data.structure.complete) {
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
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) {
}
fprintf(ar->f, "}");
} else if (type_entry->id == TypeTableEntryIdEnum) {
- const char *extern_str = extern_string(type_entry->data.enumeration.is_extern);
- fprintf(ar->f, "%senum {\n", extern_str);
+ const char *layout_str = layout_string(type_entry->data.enumeration.layout);
+ fprintf(ar->f, "%senum {\n", layout_str);
if (type_entry->data.enumeration.complete) {
for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) {
TypeEnumField *field = &type_entry->data.enumeration.fields[i];
src/ir.cpp
@@ -5283,8 +5283,9 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope,
TldContainer *tld_container = allocate<TldContainer>(1);
init_tld(&tld_container->base, TldIdContainer, name, visib_mod, node, parent_scope);
- TypeTableEntry *container_type = get_partial_container_type(irb->codegen, parent_scope, kind, node, buf_ptr(name),
- node->data.container_decl.is_extern);
+ ContainerLayout layout = node->data.container_decl.layout;
+ TypeTableEntry *container_type = get_partial_container_type(irb->codegen, parent_scope,
+ kind, node, buf_ptr(name), layout);
ScopeDecls *child_scope = get_container_scope(container_type);
tld_container->type_entry = container_type;
src/parseh.cpp
@@ -720,7 +720,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
const EnumDecl *enum_def = enum_decl->getDefinition();
if (!enum_def) {
TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
- ContainerKindEnum, c->source_node, buf_ptr(full_type_name), true);
+ ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
enum_type->data.enumeration.zero_bits_known = true;
c->enum_type_table.put(bare_name, enum_type);
c->decl_table.put(enum_decl, enum_type);
@@ -745,7 +745,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
if (pure_enum) {
TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
- ContainerKindEnum, c->source_node, buf_ptr(full_type_name), true);
+ ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
c->enum_type_table.put(bare_name, enum_type);
c->decl_table.put(enum_decl, enum_type);
@@ -885,7 +885,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
- ContainerKindStruct, c->source_node, buf_ptr(full_type_name), true);
+ ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
struct_type->data.structure.zero_bits_known = true;
c->struct_type_table.put(bare_name, struct_type);
src/parser.cpp
@@ -2275,21 +2275,24 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
}
/*
-ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}"
-StructMember = (StructField | FnDef | GlobalVarDecl)
-StructField = Symbol option(":" Expression) ",")
+ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
+ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
+ContainerField = Symbol option(":" Expression) ",")
*/
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *first_token = &pc->tokens->at(*token_index);
Token *container_kind_token;
- bool is_extern;
+ ContainerLayout layout;
if (first_token->id == TokenIdKeywordExtern) {
container_kind_token = &pc->tokens->at(*token_index + 1);
- is_extern = true;
+ layout = ContainerLayoutExtern;
+ } else if (first_token->id == TokenIdKeywordPacked) {
+ container_kind_token = &pc->tokens->at(*token_index + 1);
+ layout = ContainerLayoutPacked;
} else {
container_kind_token = first_token;
- is_extern = false;
+ layout = ContainerLayoutAuto;
}
ContainerKind kind;
@@ -2304,10 +2307,10 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
} else {
return nullptr;
}
- *token_index += is_extern ? 2 : 1;
+ *token_index += (layout == ContainerLayoutAuto) ? 1 : 2;
AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);
- node->data.container_decl.is_extern = is_extern;
+ node->data.container_decl.layout = layout;
node->data.container_decl.kind = kind;
ast_eat_token(pc, token_index, TokenIdLBrace);
src/tokenizer.cpp
@@ -128,6 +128,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"nakedcc", TokenIdKeywordNakedCC},
{"noalias", TokenIdKeywordNoAlias},
{"null", TokenIdKeywordNull},
+ {"packed", TokenIdKeywordPacked},
{"pub", TokenIdKeywordPub},
{"return", TokenIdKeywordReturn},
{"struct", TokenIdKeywordStruct},
@@ -1502,6 +1503,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordNakedCC: return "nakedcc";
case TokenIdKeywordNoAlias: return "noalias";
case TokenIdKeywordNull: return "null";
+ case TokenIdKeywordPacked: return "packed";
case TokenIdKeywordPub: return "pub";
case TokenIdKeywordReturn: return "return";
case TokenIdKeywordStruct: return "struct";
src/tokenizer.hpp
@@ -12,109 +12,110 @@
#include "bignum.hpp"
enum TokenId {
- TokenIdEof,
- TokenIdSymbol,
- TokenIdKeywordFn,
- TokenIdKeywordReturn,
- TokenIdKeywordVar,
- TokenIdKeywordConst,
- TokenIdKeywordExtern,
- TokenIdKeywordPub,
- TokenIdKeywordUse,
- TokenIdKeywordExport,
- TokenIdKeywordTrue,
- TokenIdKeywordFalse,
- TokenIdKeywordIf,
- TokenIdKeywordTry,
- TokenIdKeywordElse,
- TokenIdKeywordGoto,
- TokenIdKeywordAsm,
- TokenIdKeywordVolatile,
- TokenIdKeywordStruct,
- TokenIdKeywordEnum,
- TokenIdKeywordUnion,
- TokenIdKeywordWhile,
- TokenIdKeywordFor,
- TokenIdKeywordContinue,
- TokenIdKeywordBreak,
- TokenIdKeywordNull,
- TokenIdKeywordNoAlias,
- TokenIdKeywordSwitch,
- TokenIdKeywordUndefined,
- TokenIdKeywordError,
- TokenIdKeywordType,
- TokenIdKeywordInline,
- TokenIdKeywordCompTime,
- TokenIdKeywordDefer,
- TokenIdKeywordThis,
- TokenIdKeywordColdCC,
- TokenIdKeywordNakedCC,
- TokenIdLParen,
- TokenIdRParen,
- TokenIdComma,
- TokenIdStar,
- TokenIdStarStar,
- TokenIdLBrace,
- TokenIdRBrace,
- TokenIdLBracket,
- TokenIdRBracket,
- TokenIdStringLiteral,
- TokenIdCharLiteral,
- TokenIdSemicolon,
- TokenIdNumberLiteral,
- TokenIdPlus,
- TokenIdPlusPlus,
- TokenIdColon,
+ TokenIdAmpersand,
TokenIdArrow,
- TokenIdFatArrow,
- TokenIdDash,
- TokenIdNumberSign,
- TokenIdBoolOr,
- TokenIdBoolAnd,
+ TokenIdAtSign,
+ TokenIdBang,
TokenIdBinOr,
- TokenIdAmpersand,
TokenIdBinXor,
- TokenIdEq,
- TokenIdTimesEq,
- TokenIdTimesPercent,
- TokenIdTimesPercentEq,
- TokenIdDivEq,
- TokenIdModEq,
- TokenIdPlusEq,
- TokenIdPlusPercent,
- TokenIdPlusPercentEq,
- TokenIdMinusEq,
- TokenIdMinusPercent,
- TokenIdMinusPercentEq,
+ TokenIdBitAndEq,
+ TokenIdBitOrEq,
+ TokenIdBitShiftLeft,
TokenIdBitShiftLeftEq,
TokenIdBitShiftLeftPercent,
TokenIdBitShiftLeftPercentEq,
+ TokenIdBitShiftRight,
TokenIdBitShiftRightEq,
- TokenIdBitAndEq,
TokenIdBitXorEq,
- TokenIdBitOrEq,
+ TokenIdBoolAnd,
TokenIdBoolAndEq,
+ TokenIdBoolOr,
TokenIdBoolOrEq,
+ TokenIdCharLiteral,
TokenIdCmpEq,
- TokenIdBang,
- TokenIdTilde,
- TokenIdCmpNotEq,
- TokenIdCmpLessThan,
+ TokenIdCmpGreaterOrEq,
TokenIdCmpGreaterThan,
TokenIdCmpLessOrEq,
- TokenIdCmpGreaterOrEq,
- TokenIdBitShiftLeft,
- TokenIdBitShiftRight,
- TokenIdSlash,
- TokenIdPercent,
- TokenIdPercentPercent,
+ TokenIdCmpLessThan,
+ TokenIdCmpNotEq,
+ TokenIdColon,
+ TokenIdComma,
+ TokenIdDash,
+ TokenIdDivEq,
TokenIdDot,
+ TokenIdDoubleQuestion,
TokenIdEllipsis,
+ TokenIdEof,
+ TokenIdEq,
+ TokenIdFatArrow,
+ TokenIdKeywordAsm,
+ TokenIdKeywordBreak,
+ TokenIdKeywordColdCC,
+ TokenIdKeywordCompTime,
+ TokenIdKeywordConst,
+ TokenIdKeywordContinue,
+ TokenIdKeywordDefer,
+ TokenIdKeywordElse,
+ TokenIdKeywordEnum,
+ TokenIdKeywordError,
+ TokenIdKeywordExport,
+ TokenIdKeywordExtern,
+ TokenIdKeywordFalse,
+ TokenIdKeywordFn,
+ TokenIdKeywordFor,
+ TokenIdKeywordGoto,
+ TokenIdKeywordIf,
+ TokenIdKeywordInline,
+ TokenIdKeywordNakedCC,
+ TokenIdKeywordNoAlias,
+ TokenIdKeywordNull,
+ TokenIdKeywordPacked,
+ TokenIdKeywordPub,
+ TokenIdKeywordReturn,
+ TokenIdKeywordStruct,
+ TokenIdKeywordSwitch,
+ TokenIdKeywordThis,
+ TokenIdKeywordTrue,
+ TokenIdKeywordTry,
+ TokenIdKeywordType,
+ TokenIdKeywordUndefined,
+ TokenIdKeywordUnion,
+ TokenIdKeywordUse,
+ TokenIdKeywordVar,
+ TokenIdKeywordVolatile,
+ TokenIdKeywordWhile,
+ TokenIdLBrace,
+ TokenIdLBracket,
+ TokenIdLParen,
TokenIdMaybe,
- TokenIdDoubleQuestion,
TokenIdMaybeAssign,
- TokenIdAtSign,
+ TokenIdMinusEq,
+ TokenIdMinusPercent,
+ TokenIdMinusPercentEq,
+ TokenIdModEq,
+ TokenIdNumberLiteral,
+ TokenIdNumberSign,
+ TokenIdPercent,
TokenIdPercentDot,
+ TokenIdPercentPercent,
+ TokenIdPlus,
+ TokenIdPlusEq,
+ TokenIdPlusPercent,
+ TokenIdPlusPercentEq,
+ TokenIdPlusPlus,
+ TokenIdRBrace,
+ TokenIdRBracket,
+ TokenIdRParen,
+ TokenIdSemicolon,
+ TokenIdSlash,
+ TokenIdStar,
+ TokenIdStarStar,
+ TokenIdStringLiteral,
+ TokenIdSymbol,
+ TokenIdTilde,
+ TokenIdTimesEq,
+ TokenIdTimesPercent,
+ TokenIdTimesPercentEq,
};
struct TokenNumLit {
test/cases/struct.zig
@@ -208,3 +208,20 @@ fn passSliceOfEmptyStructToFn() {
fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {
slice.len
}
+
+const APackedStruct = packed struct {
+ x: u8,
+ y: u8,
+};
+
+fn packedStruct() {
+ @setFnTest(this);
+
+ var foo = APackedStruct {
+ .x = 1,
+ .y = 2,
+ };
+ foo.y += 1;
+ const four = foo.x + foo.y;
+ assert(four == 4);
+}