From a3104a4a78089f3260c0dd3f4a96012c6d73a63b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Oct 2021 21:26:59 -0700 Subject: stage2: fix comptime stores and sentinel-terminated arrays * ZIR: the `array_type_sentinel` now has a source node attached to it for proper error reporting. * Refactor: move `Module.arrayType` to `Type.array` * Value: the `bytes` and `array` tags now include the sentinel, if the type has one. This simplifies comptime evaluation logic. * Sema: fix `zirStructInitEmpty` to properly handle when the type is void or a sentinel-terminated array. This handles the syntax `void{}` and `[0:X]T{}`. * Sema: fix the logic for reporting "cannot store runtime value in compile time variable" as well as for emitting a runtime store when a pointer value is comptime known but it is a global variable. * Sema: implement elemVal for double pointer to array. This can happen with this code for example: `var a: *[1]u8 = undefined; _ = a[0];` * Sema: Rework the `storePtrVal` function to properly handle nested structs and arrays. - Also it now handles comptime stores through a bitcasted pointer. When the pointer element type and the type according to the Decl don't match, the element value is bitcasted before storage. --- src/Module.zig | 100 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 30 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 0a2f71f024..ee9b3e50bc 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1885,6 +1885,55 @@ pub const SrcLoc = struct { const token_starts = tree.tokens.items(.start); return token_starts[tok_index]; }, + + .node_offset_array_type_len => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_tags = tree.nodes.items(.tag); + const parent_node = src_loc.declRelativeToNodeIndex(node_off); + + const full: Ast.full.ArrayType = switch (node_tags[parent_node]) { + .array_type => tree.arrayType(parent_node), + .array_type_sentinel => tree.arrayTypeSentinel(parent_node), + else => unreachable, + }; + const node = full.ast.elem_count; + const main_tokens = tree.nodes.items(.main_token); + const tok_index = main_tokens[node]; + const token_starts = tree.tokens.items(.start); + return token_starts[tok_index]; + }, + .node_offset_array_type_sentinel => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_tags = tree.nodes.items(.tag); + const parent_node = src_loc.declRelativeToNodeIndex(node_off); + + const full: Ast.full.ArrayType = switch (node_tags[parent_node]) { + .array_type => tree.arrayType(parent_node), + .array_type_sentinel => tree.arrayTypeSentinel(parent_node), + else => unreachable, + }; + const node = full.ast.sentinel; + const main_tokens = tree.nodes.items(.main_token); + const tok_index = main_tokens[node]; + const token_starts = tree.tokens.items(.start); + return token_starts[tok_index]; + }, + .node_offset_array_type_elem => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_tags = tree.nodes.items(.tag); + const parent_node = src_loc.declRelativeToNodeIndex(node_off); + + const full: Ast.full.ArrayType = switch (node_tags[parent_node]) { + .array_type => tree.arrayType(parent_node), + .array_type_sentinel => tree.arrayTypeSentinel(parent_node), + else => unreachable, + }; + const node = full.ast.elem_type; + const main_tokens = tree.nodes.items(.main_token); + const tok_index = main_tokens[node]; + const token_starts = tree.tokens.items(.start); + return token_starts[tok_index]; + }, } } @@ -2085,6 +2134,24 @@ pub const LazySrcLoc = union(enum) { /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. /// The Decl is determined contextually. node_offset_lib_name: i32, + /// The source location points to the len expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the len expression. + /// The Decl is determined contextually. + node_offset_array_type_len: i32, + /// The source location points to the sentinel expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the sentinel expression. + /// The Decl is determined contextually. + node_offset_array_type_sentinel: i32, + /// The source location points to the elem expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the elem expression. + /// The Decl is determined contextually. + node_offset_array_type_elem: i32, /// Upgrade to a `SrcLoc` based on the `Decl` provided. pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc { @@ -2130,6 +2197,9 @@ pub const LazySrcLoc = union(enum) { .node_offset_fn_type_ret_ty, .node_offset_anyframe_type, .node_offset_lib_name, + .node_offset_array_type_len, + .node_offset_array_type_sentinel, + .node_offset_array_type_elem, => .{ .file_scope = decl.getFileScope(), .parent_decl_node = decl.src_node, @@ -4125,36 +4195,6 @@ pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type { } } -pub fn arrayType( - arena: *Allocator, - len: u64, - sentinel: ?Value, - elem_type: Type, -) Allocator.Error!Type { - if (elem_type.eql(Type.initTag(.u8))) { - if (sentinel) |some| { - if (some.eql(Value.initTag(.zero), elem_type)) { - return Type.Tag.array_u8_sentinel_0.create(arena, len); - } - } else { - return Type.Tag.array_u8.create(arena, len); - } - } - - if (sentinel) |some| { - return Type.Tag.array_sentinel.create(arena, .{ - .len = len, - .sentinel = some, - .elem_type = elem_type, - }); - } - - return Type.Tag.array.create(arena, .{ - .len = len, - .elem_type = elem_type, - }); -} - pub fn errorUnionType( arena: *Allocator, error_set: Type, -- cgit v1.2.3