Commit 3ec10ea174

Tetralux <tetralux@teknik.io>
2019-08-22 22:41:33
parsing of align(N) on struct fields
1 parent ec7d7a5
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 {
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
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;
 }
 
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;
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;
 }