From 3ec10ea174d5738098e9bd1ef709b552603cc3b4 Mon Sep 17 00:00:00 2001 From: Tetralux Date: Thu, 22 Aug 2019 20:41:33 +0000 Subject: [PATCH] parsing of align(N) on struct fields --- src/all_types.hpp | 2 ++ src/analyze.cpp | 16 ++++++++++++++-- src/parser.cpp | 8 +++++--- std/zig/ast.zig | 1 + std/zig/parse.zig | 15 +++++++++------ 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 559ebe8cda..2394bcb73b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -849,6 +849,8 @@ struct AstNodeStructField { Buf *name; AstNode *type; AstNode *value; + // populated if the "align(A)" is present + AstNode *align_expr; }; struct AstNodeStringLiteral { diff --git a/src/analyze.cpp b/src/analyze.cpp index a06bba3f2a..aa625b6e22 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2255,9 +2255,21 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { if (field->gen_index == SIZE_MAX) continue; - size_t this_field_align; - if (packed) { + uint32_t this_field_align; + + // TODO: Sets the field alignment in the type, but doesn't do anything + // to actually make that happen yet. + AstNode *align_expr = field->decl_node->data.struct_field.align_expr; + if (align_expr != nullptr) { + if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, &this_field_align)) { + field->type_entry = g->builtin_types.entry_invalid; + } else { + field->align = this_field_align; + } + } else if (packed) { // TODO: https://github.com/ziglang/zig/issues/1512 + // TODO: Validate requested alignment is possible, given packed, + // and given other field alignments. this_field_align = 1; // TODO If we have no type_entry for the field, we've already failed to // compile the program correctly. This stage1 compiler needs a deeper diff --git a/src/parser.cpp b/src/parser.cpp index 1e7e36d0bd..6cd6c2f045 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { return res; } -// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? +// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? static AstNode *ast_parse_container_field(ParseContext *pc) { Token *identifier = eat_token_if(pc, TokenIdSymbol); if (identifier == nullptr) return nullptr; AstNode *type_expr = nullptr; - if (eat_token_if(pc, TokenIdColon) != nullptr) + if (eat_token_if(pc, TokenIdColon) != nullptr) { type_expr = ast_expect(pc, ast_parse_type_expr); + } + AstNode *align_expr = ast_parse_byte_align(pc); AstNode *expr = nullptr; if (eat_token_if(pc, TokenIdEq) != nullptr) expr = ast_expect(pc, ast_parse_expr); - AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); res->data.struct_field.name = token_buf(identifier); res->data.struct_field.type = type_expr; res->data.struct_field.value = expr; + res->data.struct_field.align_expr = align_expr; return res; } diff --git a/std/zig/ast.zig b/std/zig/ast.zig index e5781da035..c2f369ff4a 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -761,6 +761,7 @@ pub const Node = struct { name_token: TokenIndex, type_expr: ?*Node, value_expr: ?*Node, + align_expr: ?*Node, pub fn iterate(self: *ContainerField, index: usize) ?*Node { var i = index; diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 0a2fbb4fa1..0511b6dce0 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { return &node.base; } -/// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? +/// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const name_token = eatToken(it, .Identifier) orelse return null; - const type_expr = if (eatToken(it, .Colon)) |_| - try expectNode(arena, it, tree, parseTypeExpr, AstError{ + var align_expr: ?*Node = null; + var type_expr: ?*Node = null; + if (eatToken(it, .Colon)) |_| { + type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{ .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index }, - }) - else - null; + }); + align_expr = try parseByteAlign(arena, it, tree); + } const value_expr = if (eatToken(it, .Equal)) |_| try expectNode(arena, it, tree, parseExpr, AstError{ @@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No .name_token = name_token, .type_expr = type_expr, .value_expr = value_expr, + .align_expr = align_expr, }; return &node.base; }