authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-12 16:44:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-15 19:06:39-07:00
logbcfebb4b2b17dcac445fc5dedbbd259cc8c2f306
tree48950201c23c8ccde48e2e31c91464c7e96e6163
parent429cd2b5dd27bec15a4a3351114ce1bcd12d8d01

stage2: improvements aimed at std lib integration

* AstGen: emit decl lookup ZIR instructions rather than directly looking up decls in AstGen. This is necessary because we want to reuse the same immutable ZIR code for multiple generic instantiations (and comptime function calls). * AstGen: fix using members_len instead of fields_len for struct decls. * structs: the struct_decl ZIR instruction is now also a block. This is so that the type expressions, default field value expressions, and alignment expressions can be evaluated in a scope that contains the decls from the struct namespace itself. * Add "std" and "builtin" packages to the builtin package. * Don't try to build glibc, musl, or mingw-w64 when using `-ofmt=c`. * builtin.zig is generated without `usingnamespace`. * builtin.zig takes advantage of `std.zig.fmtId` for CPU features. * A first pass at implementing `usingnamespace`. It's problematic and should either be deleted, or polished, before merging this branch. * Sema: allow explicitly specifying the namespace in which to look up Decls. This is used by `struct_decl` in order to put the decls from the struct namespace itself in scope when evaluating the type expressions, default value expressions, and alignment expressions. * Module: fix `analyzeNamespace` assuming that it is the top-level root declaration node. * Sema: implement comptime and runtime cmp operator. * Sema: implement peer type resolution for enums and enum literals. * Pull in the changes from master branch: 262e09c482d98a78531c049a18b7f24146fe157f. * ZIR: complete out simple_ptr_type debug printing

12 files changed, 475 insertions(+), 153 deletions(-)

BRANCH_TODO+5
...@@ -1,4 +1,8 @@...@@ -1,4 +1,8 @@
1 * get rid of failed_root_src_file1 * get rid of failed_root_src_file
2 * handle decl collision with usingnamespace
3 * the decl doing the looking up needs to create a decl dependency
4 on each usingnamespace decl
5 * handle usingnamespace cycles
26
37
4 const container_name_hash: Scope.NameHash = if (found_pkg) |pkg|8 const container_name_hash: Scope.NameHash = if (found_pkg) |pkg|
...@@ -94,3 +98,4 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd...@@ -94,3 +98,4 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd
94 return std.fmt.allocPrint(mod.gpa, "{s}:{d}:{d}", .{ base_name, loc.line, loc.column });98 return std.fmt.allocPrint(mod.gpa, "{s}:{d}:{d}", .{ base_name, loc.line, loc.column });
95}99}
96100
101
build.zig+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const builtin = @import("builtin");
2const std = @import("std");1const std = @import("std");
2const builtin = std.builtin;
3const Builder = std.build.Builder;3const Builder = std.build.Builder;
4const tests = @import("test/tests.zig");4const tests = @import("test/tests.zig");
5const BufMap = std.BufMap;5const BufMap = std.BufMap;
src/AstGen.zig+42-22
...@@ -1254,6 +1254,8 @@ fn blockExprStmts(...@@ -1254,6 +1254,8 @@ fn blockExprStmts(
1254 .coerce_result_ptr,1254 .coerce_result_ptr,
1255 .decl_ref,1255 .decl_ref,
1256 .decl_val,1256 .decl_val,
1257 .decl_ref_named,
1258 .decl_val_named,
1257 .load,1259 .load,
1258 .div,1260 .div,
1259 .elem_ptr,1261 .elem_ptr,
...@@ -1817,7 +1819,7 @@ pub fn structDeclInner(...@@ -1817,7 +1819,7 @@ pub fn structDeclInner(
1817 tag: zir.Inst.Tag,1819 tag: zir.Inst.Tag,
1818) InnerError!zir.Inst.Ref {1820) InnerError!zir.Inst.Ref {
1819 if (container_decl.ast.members.len == 0) {1821 if (container_decl.ast.members.len == 0) {
1820 return gz.addPlNode(tag, node, zir.Inst.StructDecl{ .fields_len = 0 });1822 return gz.addPlNode(tag, node, zir.Inst.StructDecl{ .fields_len = 0, .body_len = 0 });
1821 }1823 }
18221824
1823 const astgen = gz.astgen;1825 const astgen = gz.astgen;
...@@ -1826,12 +1828,21 @@ pub fn structDeclInner(...@@ -1826,12 +1828,21 @@ pub fn structDeclInner(
1826 const tree = gz.tree();1828 const tree = gz.tree();
1827 const node_tags = tree.nodes.items(.tag);1829 const node_tags = tree.nodes.items(.tag);
18281830
1831 // The struct_decl instruction introduces a scope in which the decls of the struct
1832 // are in scope, so that field types, alignments, and default value expressions
1833 // can refer to decls within the struct itself.
1834 var block_scope: GenZir = .{
1835 .parent = scope,
1836 .astgen = astgen,
1837 .force_comptime = true,
1838 };
1839 defer block_scope.instructions.deinit(gpa);
1840
1841 // We don't know which members are fields until we iterate, so cannot do
1842 // an accurate ensureCapacity yet.
1829 var fields_data = ArrayListUnmanaged(u32){};1843 var fields_data = ArrayListUnmanaged(u32){};
1830 defer fields_data.deinit(gpa);1844 defer fields_data.deinit(gpa);
18311845
1832 // field_name and field_type are both mandatory
1833 try fields_data.ensureCapacity(gpa, container_decl.ast.members.len * 2);
1834
1835 // We only need this if there are greater than 16 fields.1846 // We only need this if there are greater than 16 fields.
1836 var bit_bag = ArrayListUnmanaged(u32){};1847 var bit_bag = ArrayListUnmanaged(u32){};
1837 defer bit_bag.deinit(gpa);1848 defer bit_bag.deinit(gpa);
...@@ -1857,7 +1868,7 @@ pub fn structDeclInner(...@@ -1857,7 +1868,7 @@ pub fn structDeclInner(
1857 const field_name = try gz.identAsString(member.ast.name_token);1868 const field_name = try gz.identAsString(member.ast.name_token);
1858 fields_data.appendAssumeCapacity(field_name);1869 fields_data.appendAssumeCapacity(field_name);
18591870
1860 const field_type = try typeExpr(gz, scope, member.ast.type_expr);1871 const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
1861 fields_data.appendAssumeCapacity(@enumToInt(field_type));1872 fields_data.appendAssumeCapacity(@enumToInt(field_type));
18621873
1863 const have_align = member.ast.align_expr != 0;1874 const have_align = member.ast.align_expr != 0;
...@@ -1867,31 +1878,40 @@ pub fn structDeclInner(...@@ -1867,31 +1878,40 @@ pub fn structDeclInner(
1867 (@as(u32, @boolToInt(have_value)) << 31);1878 (@as(u32, @boolToInt(have_value)) << 31);
18681879
1869 if (have_align) {1880 if (have_align) {
1870 const align_inst = try comptimeExpr(gz, scope, .{ .ty = .u32_type }, member.ast.align_expr);1881 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
1871 fields_data.appendAssumeCapacity(@enumToInt(align_inst));1882 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
1872 }1883 }
1873 if (have_value) {1884 if (have_value) {
1874 const default_inst = try comptimeExpr(gz, scope, .{ .ty = field_type }, member.ast.value_expr);1885 const default_inst = try expr(&block_scope, &block_scope.base, .{ .ty = field_type }, member.ast.value_expr);
1875 fields_data.appendAssumeCapacity(@enumToInt(default_inst));1886 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
1876 }1887 }
18771888
1878 field_index += 1;1889 field_index += 1;
1879 }1890 }
1880 if (field_index == 0) {1891 if (field_index == 0) {
1881 return gz.addPlNode(tag, node, zir.Inst.StructDecl{ .fields_len = 0 });1892 return gz.addPlNode(tag, node, zir.Inst.StructDecl{ .fields_len = 0, .body_len = 0 });
1882 }1893 }
1883 const empty_slot_count = 16 - (field_index % 16);1894 const empty_slot_count = 16 - (field_index % 16);
1884 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);1895 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
18851896
1886 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{1897 const decl_inst = try gz.addBlock(tag, node);
1887 .fields_len = @intCast(u32, container_decl.ast.members.len),1898 try gz.instructions.append(gpa, decl_inst);
1888 });1899 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
1900
1889 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +1901 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
1890 bit_bag.items.len + 1 + fields_data.items.len);1902 @typeInfo(zir.Inst.StructDecl).Struct.fields.len +
1903 bit_bag.items.len + 1 + fields_data.items.len +
1904 block_scope.instructions.items.len);
1905 const zir_datas = astgen.instructions.items(.data);
1906 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(zir.Inst.StructDecl{
1907 .body_len = @intCast(u32, block_scope.instructions.items.len),
1908 .fields_len = @intCast(u32, field_index),
1909 });
1910 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
1891 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.1911 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
1892 astgen.extra.appendAssumeCapacity(cur_bit_bag);1912 astgen.extra.appendAssumeCapacity(cur_bit_bag);
1893 astgen.extra.appendSliceAssumeCapacity(fields_data.items);1913 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
1894 return result;1914 return astgen.indexToRef(decl_inst);
1895}1915}
18961916
1897fn containerDecl(1917fn containerDecl(
...@@ -3722,16 +3742,16 @@ fn identifier(...@@ -3722,16 +3742,16 @@ fn identifier(
3722 };3742 };
3723 }3743 }
37243744
3725 const decl = mod.lookupIdentifier(scope, ident_name) orelse {3745 // We can't look up Decls until Sema because the same ZIR code is supposed to be
3726 // TODO insert a "dependency on the non-existence of a decl" here to make this3746 // used for multiple generic instantiations, and this may refer to a different Decl
3727 // compile error go away when the decl is introduced. This data should be in a global3747 // depending on the scope, determined by the generic instantiation.
3728 // sparse map since it is only relevant when a compile error occurs.3748 const str_index = try gz.identAsString(ident_token);
3729 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
3730 };
3731 const decl_index = try mod.declareDeclDependency(astgen.decl, decl);
3732 switch (rl) {3749 switch (rl) {
3733 .ref, .none_or_ref => return gz.addDecl(.decl_ref, decl_index, ident),3750 .ref, .none_or_ref => return gz.addStrTok(.decl_ref_named, str_index, ident_token),
3734 else => return rvalue(gz, scope, rl, try gz.addDecl(.decl_val, decl_index, ident), ident),3751 else => {
3752 const result = try gz.addStrTok(.decl_val_named, str_index, ident_token);
3753 return rvalue(gz, scope, rl, result, ident);
3754 },
3735 }3755 }
3736}3756}
37373757
src/Compilation.zig+25-19
...@@ -531,7 +531,7 @@ pub const InitOptions = struct {...@@ -531,7 +531,7 @@ pub const InitOptions = struct {
531 /// is externally modified - essentially anything other than zig-cache - then531 /// is externally modified - essentially anything other than zig-cache - then
532 /// this flag would be set to disable this machinery to avoid false positives.532 /// this flag would be set to disable this machinery to avoid false positives.
533 disable_lld_caching: bool = false,533 disable_lld_caching: bool = false,
534 object_format: ?std.builtin.ObjectFormat = null,534 object_format: ?std.Target.ObjectFormat = null,
535 optimize_mode: std.builtin.Mode = .Debug,535 optimize_mode: std.builtin.Mode = .Debug,
536 keep_source_files_loaded: bool = false,536 keep_source_files_loaded: bool = false,
537 clang_argv: []const []const u8 = &[0][]const u8{},537 clang_argv: []const []const u8 = &[0][]const u8{},
...@@ -1041,6 +1041,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1041,6 +1041,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
10411041
1042 try std_pkg.add(gpa, "builtin", builtin_pkg);1042 try std_pkg.add(gpa, "builtin", builtin_pkg);
1043 try std_pkg.add(gpa, "root", root_pkg);1043 try std_pkg.add(gpa, "root", root_pkg);
1044 try std_pkg.add(gpa, "std", std_pkg);
1045
1046 try builtin_pkg.add(gpa, "std", std_pkg);
1047 try builtin_pkg.add(gpa, "builtin", builtin_pkg);
1044 }1048 }
10451049
1046 // TODO when we implement serialization and deserialization of incremental1050 // TODO when we implement serialization and deserialization of incremental
...@@ -2993,7 +2997,8 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {...@@ -2993,7 +2997,8 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {
2993 .Exe => true,2997 .Exe => true,
2994 };2998 };
2995 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and2999 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
2996 comp.bin_file.options.libc_installation == null;3000 comp.bin_file.options.libc_installation == null and
3001 comp.bin_file.options.object_format != .c;
2997}3002}
29983003
2999fn wantBuildGLibCFromSource(comp: Compilation) bool {3004fn wantBuildGLibCFromSource(comp: Compilation) bool {
...@@ -3017,6 +3022,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {...@@ -3017,6 +3022,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
3017 };3022 };
3018 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and3023 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
3019 comp.bin_file.options.libc_installation == null and3024 comp.bin_file.options.libc_installation == null and
3025 comp.bin_file.options.object_format != .c and
3020 target_util.libcNeedsLibUnwind(comp.getTarget());3026 target_util.libcNeedsLibUnwind(comp.getTarget());
3021}3027}
30223028
...@@ -3068,26 +3074,21 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3068,26 +3074,21 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
30683074
3069 @setEvalBranchQuota(4000);3075 @setEvalBranchQuota(4000);
3070 try buffer.writer().print(3076 try buffer.writer().print(
3071 \\usingnamespace @import("std").builtin;3077 \\const std = @import("std");
3072 \\/// Deprecated
3073 \\pub const arch = Target.current.cpu.arch;
3074 \\/// Deprecated
3075 \\pub const endian = Target.current.cpu.arch.endian();
3076 \\
3077 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer3078 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
3078 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.3079 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
3079 \\pub const zig_version = try @import("std").SemanticVersion.parse("{s}");3080 \\pub const zig_version = try std.SemanticVersion.parse("{s}");
3080 \\pub const zig_is_stage2 = {};3081 \\pub const zig_is_stage2 = {};
3081 \\3082 \\
3082 \\pub const output_mode = OutputMode.{};3083 \\pub const output_mode = std.builtin.OutputMode.{};
3083 \\pub const link_mode = LinkMode.{};3084 \\pub const link_mode = std.builtin.LinkMode.{};
3084 \\pub const is_test = {};3085 \\pub const is_test = {};
3085 \\pub const single_threaded = {};3086 \\pub const single_threaded = {};
3086 \\pub const abi = Abi.{};3087 \\pub const abi = std.Target.Abi.{};
3087 \\pub const cpu: Cpu = Cpu{{3088 \\pub const cpu: std.Target.Cpu = .{{
3088 \\ .arch = .{},3089 \\ .arch = .{},
3089 \\ .model = &Target.{}.cpu.{},3090 \\ .model = &std.Target.{}.cpu.{},
3090 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{3091 \\ .features = std.Target.{}.featureSet(&[_]std.Target.{}.Feature{{
3091 \\3092 \\
3092 , .{3093 , .{
3093 build_options.version,3094 build_options.version,
...@@ -3115,7 +3116,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3115,7 +3116,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
3115 try buffer.writer().print(3116 try buffer.writer().print(
3116 \\ }}),3117 \\ }}),
3117 \\}};3118 \\}};
3118 \\pub const os = Os{{3119 \\pub const os = std.Target.Os{{
3119 \\ .tag = .{},3120 \\ .tag = .{},
3120 \\ .version_range = .{{3121 \\ .version_range = .{{
3121 ,3122 ,
...@@ -3202,8 +3203,13 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3202,8 +3203,13 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
3202 (comp.bin_file.options.skip_linker_dependencies and comp.bin_file.options.parent_compilation_link_libc);3203 (comp.bin_file.options.skip_linker_dependencies and comp.bin_file.options.parent_compilation_link_libc);
32033204
3204 try buffer.writer().print(3205 try buffer.writer().print(
3205 \\pub const object_format = ObjectFormat.{};3206 \\pub const target = std.Target{{
3206 \\pub const mode = Mode.{};3207 \\ .cpu = cpu,
3208 \\ .os = os,
3209 \\ .abi = abi,
3210 \\}};
3211 \\pub const object_format = std.Target.ObjectFormat.{};
3212 \\pub const mode = std.builtin.Mode.{};
3207 \\pub const link_libc = {};3213 \\pub const link_libc = {};
3208 \\pub const link_libcpp = {};3214 \\pub const link_libcpp = {};
3209 \\pub const have_error_return_tracing = {};3215 \\pub const have_error_return_tracing = {};
...@@ -3211,7 +3217,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3211,7 +3217,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
3211 \\pub const position_independent_code = {};3217 \\pub const position_independent_code = {};
3212 \\pub const position_independent_executable = {};3218 \\pub const position_independent_executable = {};
3213 \\pub const strip_debug_info = {};3219 \\pub const strip_debug_info = {};
3214 \\pub const code_model = CodeModel.{};3220 \\pub const code_model = std.builtin.CodeModel.{};
3215 \\3221 \\
3216 , .{3222 , .{
3217 std.zig.fmtId(@tagName(comp.bin_file.options.object_format)),3223 std.zig.fmtId(@tagName(comp.bin_file.options.object_format)),
src/Module.zig+130-10
...@@ -657,6 +657,7 @@ pub const Scope = struct {...@@ -657,6 +657,7 @@ pub const Scope = struct {
657 /// Direct children of the namespace. Used during an update to detect657 /// Direct children of the namespace. Used during an update to detect
658 /// which decls have been added/removed from source.658 /// which decls have been added/removed from source.
659 decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},659 decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
660 usingnamespace_set: std.AutoHashMapUnmanaged(*Namespace, bool) = .{},
660661
661 pub fn deinit(ns: *Namespace, gpa: *Allocator) void {662 pub fn deinit(ns: *Namespace, gpa: *Allocator) void {
662 ns.decls.deinit(gpa);663 ns.decls.deinit(gpa);
...@@ -2540,6 +2541,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {...@@ -2540,6 +2541,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
2540 .code = code,2541 .code = code,
2541 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, code.instructions.len),2542 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, code.instructions.len),
2542 .owner_decl = decl,2543 .owner_decl = decl,
2544 .namespace = decl.namespace,
2543 .func = null,2545 .func = null,
2544 .owner_func = null,2546 .owner_func = null,
2545 .param_inst_list = &.{},2547 .param_inst_list = &.{},
...@@ -2560,7 +2562,73 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {...@@ -2560,7 +2562,73 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
2560 decl.generation = mod.generation;2562 decl.generation = mod.generation;
2561 return true;2563 return true;
2562 },2564 },
2563 .@"usingnamespace" => @panic("TODO usingnamespace decl"),2565 .@"usingnamespace" => {
2566 decl.analysis = .in_progress;
2567
2568 const type_expr = node_datas[decl_node].lhs;
2569 const is_pub = blk: {
2570 const main_tokens = tree.nodes.items(.main_token);
2571 const token_tags = tree.tokens.items(.tag);
2572 const main_token = main_tokens[decl_node];
2573 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
2574 };
2575
2576 // A usingnamespace decl does not store any value so we can
2577 // deinit this arena after analysis is done.
2578 var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa);
2579 defer analysis_arena.deinit();
2580
2581 var code: zir.Code = blk: {
2582 var astgen = try AstGen.init(mod, decl, &analysis_arena.allocator);
2583 defer astgen.deinit();
2584
2585 var gen_scope: Scope.GenZir = .{
2586 .force_comptime = true,
2587 .parent = &decl.namespace.base,
2588 .astgen = &astgen,
2589 };
2590 defer gen_scope.instructions.deinit(mod.gpa);
2591
2592 const ns_type = try AstGen.typeExpr(&gen_scope, &gen_scope.base, type_expr);
2593 _ = try gen_scope.addBreak(.break_inline, 0, ns_type);
2594
2595 const code = try gen_scope.finish();
2596 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
2597 code.dump(mod.gpa, "usingnamespace_type", &gen_scope.base, 0) catch {};
2598 }
2599 break :blk code;
2600 };
2601 defer code.deinit(mod.gpa);
2602
2603 var sema: Sema = .{
2604 .mod = mod,
2605 .gpa = mod.gpa,
2606 .arena = &analysis_arena.allocator,
2607 .code = code,
2608 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, code.instructions.len),
2609 .owner_decl = decl,
2610 .namespace = decl.namespace,
2611 .func = null,
2612 .owner_func = null,
2613 .param_inst_list = &.{},
2614 };
2615 var block_scope: Scope.Block = .{
2616 .parent = null,
2617 .sema = &sema,
2618 .src_decl = decl,
2619 .instructions = .{},
2620 .inlining = null,
2621 .is_comptime = true,
2622 };
2623 defer block_scope.instructions.deinit(mod.gpa);
2624
2625 const ty = try sema.rootAsType(&block_scope);
2626 try decl.namespace.usingnamespace_set.put(mod.gpa, ty.getNamespace().?, is_pub);
2627
2628 decl.analysis = .complete;
2629 decl.generation = mod.generation;
2630 return true;
2631 },
2564 else => unreachable,2632 else => unreachable,
2565 }2633 }
2566}2634}
...@@ -2765,6 +2833,7 @@ fn astgenAndSemaFn(...@@ -2765,6 +2833,7 @@ fn astgenAndSemaFn(
2765 .code = fn_type_code,2833 .code = fn_type_code,
2766 .inst_map = try fn_type_scope_arena.allocator.alloc(*ir.Inst, fn_type_code.instructions.len),2834 .inst_map = try fn_type_scope_arena.allocator.alloc(*ir.Inst, fn_type_code.instructions.len),
2767 .owner_decl = decl,2835 .owner_decl = decl,
2836 .namespace = decl.namespace,
2768 .func = null,2837 .func = null,
2769 .owner_func = null,2838 .owner_func = null,
2770 .param_inst_list = &.{},2839 .param_inst_list = &.{},
...@@ -3064,6 +3133,7 @@ fn astgenAndSemaVarDecl(...@@ -3064,6 +3133,7 @@ fn astgenAndSemaVarDecl(
3064 .code = code,3133 .code = code,
3065 .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),3134 .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),
3066 .owner_decl = decl,3135 .owner_decl = decl,
3136 .namespace = decl.namespace,
3067 .func = null,3137 .func = null,
3068 .owner_func = null,3138 .owner_func = null,
3069 .param_inst_list = &.{},3139 .param_inst_list = &.{},
...@@ -3125,6 +3195,7 @@ fn astgenAndSemaVarDecl(...@@ -3125,6 +3195,7 @@ fn astgenAndSemaVarDecl(
3125 .code = code,3195 .code = code,
3126 .inst_map = try type_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),3196 .inst_map = try type_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),
3127 .owner_decl = decl,3197 .owner_decl = decl,
3198 .namespace = decl.namespace,
3128 .func = null,3199 .func = null,
3129 .owner_func = null,3200 .owner_func = null,
3130 .param_inst_list = &.{},3201 .param_inst_list = &.{},
...@@ -3387,6 +3458,7 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*...@@ -3387,6 +3458,7 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*
3387 .code = code,3458 .code = code,
3388 .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),3459 .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),
3389 .owner_decl = top_decl,3460 .owner_decl = top_decl,
3461 .namespace = top_decl.namespace,
3390 .func = null,3462 .func = null,
3391 .owner_func = null,3463 .owner_func = null,
3392 .param_inst_list = &.{},3464 .param_inst_list = &.{},
...@@ -3411,7 +3483,7 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*...@@ -3411,7 +3483,7 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*
3411 struct_decl.contents_hash = top_decl.contents_hash;3483 struct_decl.contents_hash = top_decl.contents_hash;
3412 new_file.namespace = struct_ty.getNamespace().?;3484 new_file.namespace = struct_ty.getNamespace().?;
3413 new_file.namespace.parent = null;3485 new_file.namespace.parent = null;
3414 new_file.namespace.parent_name_hash = tmp_namespace.parent_name_hash;3486 //new_file.namespace.parent_name_hash = tmp_namespace.parent_name_hash;
34153487
3416 // Transfer the dependencies to `owner_decl`.3488 // Transfer the dependencies to `owner_decl`.
3417 assert(top_decl.dependants.count() == 0);3489 assert(top_decl.dependants.count() == 0);
...@@ -3422,24 +3494,31 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*...@@ -3422,24 +3494,31 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*
3422 _ = try mod.declareDeclDependency(struct_decl, dep);3494 _ = try mod.declareDeclDependency(struct_decl, dep);
3423 }3495 }
34243496
3425 try mod.analyzeFile(new_file);
3426 return new_file;3497 return new_file;
3427}3498}
34283499
3429pub fn analyzeFile(mod: *Module, file: *Scope.File) !void {3500pub fn analyzeFile(mod: *Module, file: *Scope.File) !void {
3430 return mod.analyzeNamespace(file.namespace);3501 // We call `getAstTree` here so that `analyzeFile` has the error set that includes
3502 // file system operations, but `analyzeNamespace` does not.
3503 const tree = try mod.getAstTree(file.namespace.file_scope);
3504 const decls = tree.rootDecls();
3505 return mod.analyzeNamespace(file.namespace, decls);
3431}3506}
34323507
3433pub fn analyzeNamespace(mod: *Module, namespace: *Scope.Namespace) !void {3508pub fn analyzeNamespace(
3509 mod: *Module,
3510 namespace: *Scope.Namespace,
3511 decls: []const ast.Node.Index,
3512) InnerError!void {
3434 const tracy = trace(@src());3513 const tracy = trace(@src());
3435 defer tracy.end();3514 defer tracy.end();
34363515
3437 // We may be analyzing it for the first time, or this may be3516 // We may be analyzing it for the first time, or this may be
3438 // an incremental update. This code handles both cases.3517 // an incremental update. This code handles both cases.
3439 const tree = try mod.getAstTree(namespace.file_scope);3518 assert(namespace.file_scope.status == .loaded_success); // Caller must ensure tree loaded.
3519 const tree: *const ast.Tree = &namespace.file_scope.tree;
3440 const node_tags = tree.nodes.items(.tag);3520 const node_tags = tree.nodes.items(.tag);
3441 const node_datas = tree.nodes.items(.data);3521 const node_datas = tree.nodes.items(.data);
3442 const decls = tree.rootDecls();
34433522
3444 try mod.comp.work_queue.ensureUnusedCapacity(decls.len);3523 try mod.comp.work_queue.ensureUnusedCapacity(decls.len);
3445 try namespace.decls.ensureCapacity(mod.gpa, decls.len);3524 try namespace.decls.ensureCapacity(mod.gpa, decls.len);
...@@ -3612,7 +3691,20 @@ pub fn analyzeNamespace(mod: *Module, namespace: *Scope.Namespace) !void {...@@ -3612,7 +3691,20 @@ pub fn analyzeNamespace(mod: *Module, namespace: *Scope.Namespace) !void {
3612 }3691 }
3613 },3692 },
3614 .@"usingnamespace" => {3693 .@"usingnamespace" => {
3615 log.err("TODO: analyze usingnamespace decl", .{});3694 const name_index = mod.getNextAnonNameIndex();
3695 const name = try std.fmt.allocPrint(mod.gpa, "__usingnamespace_{d}", .{name_index});
3696 defer mod.gpa.free(name);
3697
3698 const name_hash = namespace.fullyQualifiedNameHash(name);
3699 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
3700
3701 const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash);
3702 namespace.decls.putAssumeCapacity(new_decl, {});
3703
3704 mod.ensureDeclAnalyzed(new_decl) catch |err| switch (err) {
3705 error.OutOfMemory => return error.OutOfMemory,
3706 error.AnalysisFail => continue,
3707 };
3616 },3708 },
3617 else => unreachable,3709 else => unreachable,
3618 };3710 };
...@@ -3900,6 +3992,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {...@@ -3900,6 +3992,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
3900 .code = func.zir,3992 .code = func.zir,
3901 .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),3993 .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),
3902 .owner_decl = decl,3994 .owner_decl = decl,
3995 .namespace = decl.namespace,
3903 .func = func,3996 .func = func,
3904 .owner_func = func,3997 .owner_func = func,
3905 .param_inst_list = param_inst_list,3998 .param_inst_list = param_inst_list,
...@@ -4001,6 +4094,10 @@ fn createNewDecl(...@@ -4001,6 +4094,10 @@ fn createNewDecl(
4001 const new_decl = try mod.allocateNewDecl(namespace, src_node, contents_hash);4094 const new_decl = try mod.allocateNewDecl(namespace, src_node, contents_hash);
4002 errdefer mod.gpa.destroy(new_decl);4095 errdefer mod.gpa.destroy(new_decl);
4003 new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name);4096 new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name);
4097 log.debug("insert Decl {s} with hash {}", .{
4098 new_decl.name,
4099 std.fmt.fmtSliceHexLower(&name_hash),
4100 });
4004 mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl);4101 mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl);
4005 return new_decl;4102 return new_decl;
4006}4103}
...@@ -4245,7 +4342,7 @@ fn getNextAnonNameIndex(mod: *Module) usize {...@@ -4245,7 +4342,7 @@ fn getNextAnonNameIndex(mod: *Module) usize {
4245pub fn lookupIdentifier(mod: *Module, scope: *Scope, ident_name: []const u8) ?*Decl {4342pub fn lookupIdentifier(mod: *Module, scope: *Scope, ident_name: []const u8) ?*Decl {
4246 var namespace = scope.namespace();4343 var namespace = scope.namespace();
4247 while (true) {4344 while (true) {
4248 if (mod.lookupInNamespace(namespace, ident_name)) |decl| {4345 if (mod.lookupInNamespace(namespace, ident_name, false)) |decl| {
4249 return decl;4346 return decl;
4250 }4347 }
4251 namespace = namespace.parent orelse break;4348 namespace = namespace.parent orelse break;
...@@ -4259,9 +4356,32 @@ pub fn lookupInNamespace(...@@ -4259,9 +4356,32 @@ pub fn lookupInNamespace(
4259 mod: *Module,4356 mod: *Module,
4260 namespace: *Scope.Namespace,4357 namespace: *Scope.Namespace,
4261 ident_name: []const u8,4358 ident_name: []const u8,
4359 only_pub_usingnamespaces: bool,
4262) ?*Decl {4360) ?*Decl {
4263 const name_hash = namespace.fullyQualifiedNameHash(ident_name);4361 const name_hash = namespace.fullyQualifiedNameHash(ident_name);
4264 return mod.decl_table.get(name_hash);4362 log.debug("lookup Decl {s} with hash {}", .{
4363 ident_name,
4364 std.fmt.fmtSliceHexLower(&name_hash),
4365 });
4366 // TODO handle decl collision with usingnamespace
4367 // TODO the decl doing the looking up needs to create a decl dependency
4368 // on each usingnamespace decl here.
4369 if (mod.decl_table.get(name_hash)) |decl| {
4370 return decl;
4371 }
4372 {
4373 var it = namespace.usingnamespace_set.iterator();
4374 while (it.next()) |entry| {
4375 const other_ns = entry.key;
4376 const other_is_pub = entry.value;
4377 if (only_pub_usingnamespaces and !other_is_pub) continue;
4378 // TODO handle cycles
4379 if (mod.lookupInNamespace(other_ns, ident_name, true)) |decl| {
4380 return decl;
4381 }
4382 }
4383 }
4384 return null;
4265}4385}
42664386
4267pub fn makeIntType(arena: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Type {4387pub fn makeIntType(arena: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Type {
src/Sema.zig+186-66
...@@ -17,6 +17,8 @@ inst_map: []*Inst,...@@ -17,6 +17,8 @@ inst_map: []*Inst,
17/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.17/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.
18/// This `Decl` owns the arena memory of this `Sema`.18/// This `Decl` owns the arena memory of this `Sema`.
19owner_decl: *Decl,19owner_decl: *Decl,
20/// How to look up decl names.
21namespace: *Scope.Namespace,
20/// For an inline or comptime function call, this will be the root parent function22/// For an inline or comptime function call, this will be the root parent function
21/// which contains the callsite. Corresponds to `owner_decl`.23/// which contains the callsite. Corresponds to `owner_decl`.
22owner_func: ?*Module.Fn,24owner_func: ?*Module.Fn,
...@@ -169,7 +171,9 @@ pub fn analyzeBody(...@@ -169,7 +171,9 @@ pub fn analyzeBody(
169 .cmp_neq => try sema.zirCmp(block, inst, .neq),171 .cmp_neq => try sema.zirCmp(block, inst, .neq),
170 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),172 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
171 .decl_ref => try sema.zirDeclRef(block, inst),173 .decl_ref => try sema.zirDeclRef(block, inst),
174 .decl_ref_named => try sema.zirDeclRefNamed(block, inst),
172 .decl_val => try sema.zirDeclVal(block, inst),175 .decl_val => try sema.zirDeclVal(block, inst),
176 .decl_val_named => try sema.zirDeclValNamed(block, inst),
173 .load => try sema.zirLoad(block, inst),177 .load => try sema.zirLoad(block, inst),
174 .div => try sema.zirArithmetic(block, inst),178 .div => try sema.zirArithmetic(block, inst),
175 .elem_ptr => try sema.zirElemPtr(block, inst),179 .elem_ptr => try sema.zirElemPtr(block, inst),
...@@ -535,68 +539,10 @@ fn zirStructDecl(...@@ -535,68 +539,10 @@ fn zirStructDecl(
535 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;539 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
536 const src = inst_data.src();540 const src = inst_data.src();
537 const extra = sema.code.extraData(zir.Inst.StructDecl, inst_data.payload_index);541 const extra = sema.code.extraData(zir.Inst.StructDecl, inst_data.payload_index);
542 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
538 const fields_len = extra.data.fields_len;543 const fields_len = extra.data.fields_len;
539 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
540544
541 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);545 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
542 errdefer new_decl_arena.deinit();
543
544 var fields_map: std.StringArrayHashMapUnmanaged(Module.Struct.Field) = .{};
545 try fields_map.ensureCapacity(&new_decl_arena.allocator, fields_len);
546
547 {
548 var field_index: usize = extra.end + bit_bags_count;
549 var bit_bag_index: usize = extra.end;
550 var cur_bit_bag: u32 = undefined;
551 var field_i: u32 = 0;
552 while (field_i < fields_len) : (field_i += 1) {
553 if (field_i % 16 == 0) {
554 cur_bit_bag = sema.code.extra[bit_bag_index];
555 bit_bag_index += 1;
556 }
557 const has_align = @truncate(u1, cur_bit_bag) != 0;
558 cur_bit_bag >>= 1;
559 const has_default = @truncate(u1, cur_bit_bag) != 0;
560 cur_bit_bag >>= 1;
561
562 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[field_index]);
563 field_index += 1;
564 const field_type_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
565 field_index += 1;
566
567 // This string needs to outlive the ZIR code.
568 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
569 // TODO: if we need to report an error here, use a source location
570 // that points to this type expression rather than the struct.
571 // But only resolve the source location if we need to emit a compile error.
572 const field_ty = try sema.resolveType(block, src, field_type_ref);
573
574 const gop = fields_map.getOrPutAssumeCapacity(field_name);
575 assert(!gop.found_existing);
576 gop.entry.value = .{
577 .ty = field_ty,
578 .abi_align = Value.initTag(.abi_align_default),
579 .default_val = Value.initTag(.unreachable_value),
580 };
581
582 if (has_align) {
583 const align_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
584 field_index += 1;
585 // TODO: if we need to report an error here, use a source location
586 // that points to this alignment expression rather than the struct.
587 // But only resolve the source location if we need to emit a compile error.
588 gop.entry.value.abi_align = (try sema.resolveInstConst(block, src, align_ref)).val;
589 }
590 if (has_default) {
591 const default_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
592 field_index += 1;
593 // TODO: if we need to report an error here, use a source location
594 // that points to this default value expression rather than the struct.
595 // But only resolve the source location if we need to emit a compile error.
596 gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;
597 }
598 }
599 }
600546
601 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);547 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
602 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);548 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
...@@ -607,7 +553,7 @@ fn zirStructDecl(...@@ -607,7 +553,7 @@ fn zirStructDecl(
607 });553 });
608 struct_obj.* = .{554 struct_obj.* = .{
609 .owner_decl = sema.owner_decl,555 .owner_decl = sema.owner_decl,
610 .fields = fields_map,556 .fields = .{},
611 .node_offset = inst_data.src_node,557 .node_offset = inst_data.src_node,
612 .namespace = .{558 .namespace = .{
613 .parent = sema.owner_decl.namespace,559 .parent = sema.owner_decl.namespace,
...@@ -616,6 +562,128 @@ fn zirStructDecl(...@@ -616,6 +562,128 @@ fn zirStructDecl(
616 .file_scope = block.getFileScope(),562 .file_scope = block.getFileScope(),
617 },563 },
618 };564 };
565
566 {
567 const ast = std.zig.ast;
568 const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node);
569 const tree: *const ast.Tree = &struct_obj.namespace.file_scope.tree;
570 const node_tags = tree.nodes.items(.tag);
571 var buf: [2]ast.Node.Index = undefined;
572 const members: []const ast.Node.Index = switch (node_tags[node]) {
573 .container_decl,
574 .container_decl_trailing,
575 => tree.containerDecl(node).ast.members,
576
577 .container_decl_two,
578 .container_decl_two_trailing,
579 => tree.containerDeclTwo(&buf, node).ast.members,
580
581 .container_decl_arg,
582 .container_decl_arg_trailing,
583 => tree.containerDeclArg(node).ast.members,
584
585 .root => tree.rootDecls(),
586 else => unreachable,
587 };
588 try sema.mod.analyzeNamespace(&struct_obj.namespace, members);
589 }
590
591 if (fields_len == 0) {
592 assert(body.len == 0);
593 return sema.analyzeDeclVal(block, src, new_decl);
594 }
595
596 try struct_obj.fields.ensureCapacity(&new_decl_arena.allocator, fields_len);
597
598 {
599 // We create a block for the field type instructions because they
600 // may need to reference Decls from inside the struct namespace.
601 // Within the field type, default value, and alignment expressions, the "owner decl"
602 // should be the struct itself. Thus we need a new Sema.
603 var struct_sema: Sema = .{
604 .mod = sema.mod,
605 .gpa = sema.mod.gpa,
606 .arena = &new_decl_arena.allocator,
607 .code = sema.code,
608 .inst_map = sema.inst_map,
609 .owner_decl = new_decl,
610 .namespace = &struct_obj.namespace,
611 .owner_func = null,
612 .func = null,
613 .param_inst_list = &.{},
614 .branch_quota = sema.branch_quota,
615 .branch_count = sema.branch_count,
616 };
617
618 var struct_block: Scope.Block = .{
619 .parent = null,
620 .sema = &struct_sema,
621 .src_decl = new_decl,
622 .instructions = .{},
623 .inlining = null,
624 .is_comptime = true,
625 };
626 defer assert(struct_block.instructions.items.len == 0); // should all be comptime instructions
627
628 _ = try struct_sema.analyzeBody(&struct_block, body);
629
630 sema.branch_count = struct_sema.branch_count;
631 sema.branch_quota = struct_sema.branch_quota;
632 }
633 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
634 const body_end = extra.end + body.len;
635 var field_index: usize = body_end + bit_bags_count;
636 var bit_bag_index: usize = body_end;
637 var cur_bit_bag: u32 = undefined;
638 var field_i: u32 = 0;
639 while (field_i < fields_len) : (field_i += 1) {
640 if (field_i % 16 == 0) {
641 cur_bit_bag = sema.code.extra[bit_bag_index];
642 bit_bag_index += 1;
643 }
644 const has_align = @truncate(u1, cur_bit_bag) != 0;
645 cur_bit_bag >>= 1;
646 const has_default = @truncate(u1, cur_bit_bag) != 0;
647 cur_bit_bag >>= 1;
648
649 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[field_index]);
650 field_index += 1;
651 const field_type_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
652 field_index += 1;
653
654 // This string needs to outlive the ZIR code.
655 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
656 // TODO: if we need to report an error here, use a source location
657 // that points to this type expression rather than the struct.
658 // But only resolve the source location if we need to emit a compile error.
659 const field_ty = try sema.resolveType(block, src, field_type_ref);
660
661 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
662 assert(!gop.found_existing);
663 gop.entry.value = .{
664 .ty = field_ty,
665 .abi_align = Value.initTag(.abi_align_default),
666 .default_val = Value.initTag(.unreachable_value),
667 };
668
669 if (has_align) {
670 const align_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
671 field_index += 1;
672 // TODO: if we need to report an error here, use a source location
673 // that points to this alignment expression rather than the struct.
674 // But only resolve the source location if we need to emit a compile error.
675 gop.entry.value.abi_align = (try sema.resolveInstConst(block, src, align_ref)).val;
676 }
677 if (has_default) {
678 const default_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
679 field_index += 1;
680 // TODO: if we need to report an error here, use a source location
681 // that points to this default value expression rather than the struct.
682 // But only resolve the source location if we need to emit a compile error.
683 gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;
684 }
685 }
686
619 return sema.analyzeDeclVal(block, src, new_decl);687 return sema.analyzeDeclVal(block, src, new_decl);
620}688}
621689
...@@ -1447,6 +1515,34 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -1447,6 +1515,34 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
1447 return sema.analyzeDeclVal(block, src, decl);1515 return sema.analyzeDeclVal(block, src, decl);
1448}1516}
14491517
1518fn zirDeclRefNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1519 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
1520 const src = inst_data.src();
1521 const decl_name = inst_data.get(sema.code);
1522 const decl = try sema.lookupIdentifier(block, src, decl_name);
1523 return sema.analyzeDeclRef(block, src, decl);
1524}
1525
1526fn zirDeclValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1527 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
1528 const src = inst_data.src();
1529 const decl_name = inst_data.get(sema.code);
1530 const decl = try sema.lookupIdentifier(block, src, decl_name);
1531 return sema.analyzeDeclVal(block, src, decl);
1532}
1533
1534fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []const u8) !*Decl {
1535 const mod = sema.mod;
1536 const decl = mod.lookupIdentifier(&sema.namespace.base, name) orelse {
1537 // TODO insert a "dependency on the non-existence of a decl" here to make this
1538 // compile error go away when the decl is introduced. This data should be in a global
1539 // sparse map since it is only relevant when a compile error occurs.
1540 return mod.fail(&block.base, src, "use of undeclared identifier '{s}'", .{name});
1541 };
1542 _ = try mod.declareDeclDependency(sema.owner_decl, decl);
1543 return decl;
1544}
1545
1450fn zirCallNone(1546fn zirCallNone(
1451 sema: *Sema,1547 sema: *Sema,
1452 block: *Scope.Block,1548 block: *Scope.Block,
...@@ -1587,6 +1683,7 @@ fn analyzeCall(...@@ -1587,6 +1683,7 @@ fn analyzeCall(
1587 .code = module_fn.zir,1683 .code = module_fn.zir,
1588 .inst_map = try sema.gpa.alloc(*ir.Inst, module_fn.zir.instructions.len),1684 .inst_map = try sema.gpa.alloc(*ir.Inst, module_fn.zir.instructions.len),
1589 .owner_decl = sema.owner_decl,1685 .owner_decl = sema.owner_decl,
1686 .namespace = sema.owner_decl.namespace,
1590 .owner_func = sema.owner_func,1687 .owner_func = sema.owner_func,
1591 .func = module_fn,1688 .func = module_fn,
1592 .param_inst_list = casted_args,1689 .param_inst_list = casted_args,
...@@ -3647,7 +3744,7 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -3647,7 +3744,7 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
3647 "expected struct, enum, union, or opaque, found '{}'",3744 "expected struct, enum, union, or opaque, found '{}'",
3648 .{container_type},3745 .{container_type},
3649 );3746 );
3650 if (mod.lookupInNamespace(namespace, decl_name)) |decl| {3747 if (mod.lookupInNamespace(namespace, decl_name, true)) |decl| {
3651 if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) {3748 if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) {
3652 return mod.constBool(arena, src, true);3749 return mod.constBool(arena, src, true);
3653 }3750 }
...@@ -3673,7 +3770,8 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!...@@ -3673,7 +3770,8 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!
3673 return mod.fail(&block.base, src, "unable to find '{s}'", .{operand});3770 return mod.fail(&block.base, src, "unable to find '{s}'", .{operand});
3674 },3771 },
3675 else => {3772 else => {
3676 // TODO: make sure this gets retried and not cached3773 // TODO: these errors are file system errors; make sure an update() will
3774 // retry this and not cache the file system error, which may be transient.
3677 return mod.fail(&block.base, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) });3775 return mod.fail(&block.base, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) });
3678 },3776 },
3679 };3777 };
...@@ -4069,8 +4167,21 @@ fn zirCmp(...@@ -4069,8 +4167,21 @@ fn zirCmp(
40694167
4070 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);4168 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
4071 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);4169 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
4072 try sema.requireRuntimeBlock(block, src); // TODO try to do it at comptime4170
4073 const bool_type = Type.initTag(.bool); // TODO handle vectors4171 if (casted_lhs.value()) |lhs_val| {
4172 if (casted_rhs.value()) |rhs_val| {
4173 if (lhs_val.isUndef() or rhs_val.isUndef()) {
4174 return sema.mod.constInst(sema.arena, src, .{
4175 .ty = resolved_type,
4176 .val = Value.initTag(.undef),
4177 });
4178 }
4179 const result = lhs_val.compare(op, rhs_val);
4180 return sema.mod.constBool(sema.arena, src, result);
4181 }
4182 }
4183
4184 try sema.requireRuntimeBlock(block, src);
4074 const tag: Inst.Tag = switch (op) {4185 const tag: Inst.Tag = switch (op) {
4075 .lt => .cmp_lt,4186 .lt => .cmp_lt,
4076 .lte => .cmp_lte,4187 .lte => .cmp_lte,
...@@ -4079,6 +4190,7 @@ fn zirCmp(...@@ -4079,6 +4190,7 @@ fn zirCmp(
4079 .gt => .cmp_gt,4190 .gt => .cmp_gt,
4080 .neq => .cmp_neq,4191 .neq => .cmp_neq,
4081 };4192 };
4193 const bool_type = Type.initTag(.bool); // TODO handle vectors
4082 return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs);4194 return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs);
4083}4195}
40844196
...@@ -4525,7 +4637,7 @@ fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void...@@ -4525,7 +4637,7 @@ fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void
45254637
4526fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {4638fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
4527 if (block.is_comptime) {4639 if (block.is_comptime) {
4528 return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{});4640 return sema.failWithNeededComptime(block, src);
4529 }4641 }
4530 try sema.requireFunctionBlock(block, src);4642 try sema.requireFunctionBlock(block, src);
4531}4643}
...@@ -4775,7 +4887,7 @@ fn analyzeNamespaceLookup(...@@ -4775,7 +4887,7 @@ fn analyzeNamespaceLookup(
4775) InnerError!?*Inst {4887) InnerError!?*Inst {
4776 const mod = sema.mod;4888 const mod = sema.mod;
4777 const gpa = sema.gpa;4889 const gpa = sema.gpa;
4778 if (mod.lookupInNamespace(namespace, decl_name)) |decl| {4890 if (mod.lookupInNamespace(namespace, decl_name, true)) |decl| {
4779 if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) {4891 if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) {
4780 const msg = msg: {4892 const msg = msg: {
4781 const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{4893 const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{
...@@ -5639,6 +5751,14 @@ fn resolvePeerTypes(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, instructi...@@ -5639,6 +5751,14 @@ fn resolvePeerTypes(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, instructi
5639 continue;5751 continue;
5640 }5752 }
56415753
5754 if (chosen.ty.zigTypeTag() == .Enum and candidate.ty.zigTypeTag() == .EnumLiteral) {
5755 continue;
5756 }
5757 if (chosen.ty.zigTypeTag() == .EnumLiteral and candidate.ty.zigTypeTag() == .Enum) {
5758 chosen = candidate;
5759 continue;
5760 }
5761
5642 // TODO error notes pointing out each type5762 // TODO error notes pointing out each type
5643 return sema.mod.fail(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen.ty, candidate.ty });5763 return sema.mod.fail(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen.ty, candidate.ty });
5644 }5764 }
src/codegen/spirv/spec.zig+1-1
...@@ -21,7 +21,7 @@...@@ -21,7 +21,7 @@
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS22// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
23// IN THE MATERIALS.23// IN THE MATERIALS.
24const Version = @import("builtin").Version;24const Version = @import("std").builtin.Version;
25pub const version = Version{ .major = 1, .minor = 5, .patch = 4 };25pub const version = Version{ .major = 1, .minor = 5, .patch = 4 };
26pub const magic_number: u32 = 0x07230203;26pub const magic_number: u32 = 0x07230203;
27pub const Opcode = extern enum(u16) {27pub const Opcode = extern enum(u16) {
src/link.zig+1-1
...@@ -30,7 +30,7 @@ pub const Options = struct {...@@ -30,7 +30,7 @@ pub const Options = struct {
30 target: std.Target,30 target: std.Target,
31 output_mode: std.builtin.OutputMode,31 output_mode: std.builtin.OutputMode,
32 link_mode: std.builtin.LinkMode,32 link_mode: std.builtin.LinkMode,
33 object_format: std.builtin.ObjectFormat,33 object_format: std.Target.ObjectFormat,
34 optimize_mode: std.builtin.Mode,34 optimize_mode: std.builtin.Mode,
35 machine_code_model: std.builtin.CodeModel,35 machine_code_model: std.builtin.CodeModel,
36 root_name: []const u8,36 root_name: []const u8,
src/stage1/codegen.cpp+24-18
...@@ -8921,10 +8921,10 @@ static const char *bool_to_str(bool b) {...@@ -8921,10 +8921,10 @@ static const char *bool_to_str(bool b) {
89218921
8922static const char *build_mode_to_str(BuildMode build_mode) {8922static const char *build_mode_to_str(BuildMode build_mode) {
8923 switch (build_mode) {8923 switch (build_mode) {
8924 case BuildModeDebug: return "Mode.Debug";8924 case BuildModeDebug: return "Debug";
8925 case BuildModeSafeRelease: return "Mode.ReleaseSafe";8925 case BuildModeSafeRelease: return "ReleaseSafe";
8926 case BuildModeFastRelease: return "Mode.ReleaseFast";8926 case BuildModeFastRelease: return "ReleaseFast";
8927 case BuildModeSmallRelease: return "Mode.ReleaseSmall";8927 case BuildModeSmallRelease: return "ReleaseSmall";
8928 }8928 }
8929 zig_unreachable();8929 zig_unreachable();
8930}8930}
...@@ -8995,7 +8995,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -8995,7 +8995,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
8995 g->have_err_ret_tracing = detect_err_ret_tracing(g);8995 g->have_err_ret_tracing = detect_err_ret_tracing(g);
89968996
8997 Buf *contents = buf_alloc();8997 Buf *contents = buf_alloc();
8998 buf_appendf(contents, "usingnamespace @import(\"std\").builtin;\n\n");8998 buf_appendf(contents,
8999 "const std = @import(\"std\");\n"
9000 );
89999001
9000 const char *cur_os = nullptr;9002 const char *cur_os = nullptr;
9001 {9003 {
...@@ -9089,19 +9091,23 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -9089,19 +9091,23 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
9089 static_assert(TargetSubsystemEfiRom == 6, "");9091 static_assert(TargetSubsystemEfiRom == 6, "");
9090 static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");9092 static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");
90919093
9092 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch`\n");9094 buf_appendf(contents, "pub const output_mode = std.builtin.OutputMode.Obj;\n");
9093 buf_append_str(contents, "pub const arch = Target.current.cpu.arch;\n");9095 buf_appendf(contents, "pub const link_mode = std.builtin.LinkMode.%s;\n", ZIG_QUOTE(ZIG_LINK_MODE));
9094 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");
9095 buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");
9096 buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");
9097 buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", ZIG_QUOTE(ZIG_LINK_MODE));
9098 buf_appendf(contents, "pub const is_test = false;\n");9096 buf_appendf(contents, "pub const is_test = false;\n");
9099 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));9097 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
9100 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);9098 buf_appendf(contents, "pub const abi = std.Target.Abi.%s;\n", cur_abi);
9101 buf_appendf(contents, "pub const cpu: Cpu = Target.Cpu.baseline(.%s);\n", cur_arch);9099 buf_appendf(contents, "pub const cpu = std.Target.Cpu.baseline(.%s);\n", cur_arch);
9102 buf_appendf(contents, "pub const os = Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);9100 buf_appendf(contents, "pub const os = std.Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);
9103 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);9101 buf_appendf(contents,
9104 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));9102 "pub const target = std.Target{\n"
9103 " .cpu = cpu,\n"
9104 " .os = os,\n"
9105 " .abi = abi,\n"
9106 "};\n"
9107 );
9108
9109 buf_appendf(contents, "pub const object_format = std.Target.ObjectFormat.%s;\n", cur_obj_fmt);
9110 buf_appendf(contents, "pub const mode = std.builtin.Mode.%s;\n", build_mode_to_str(g->build_mode));
9105 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));9111 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));
9106 buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->link_libcpp));9112 buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->link_libcpp));
9107 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));9113 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
...@@ -9109,13 +9115,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -9109,13 +9115,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
9109 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));9115 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
9110 buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));9116 buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));
9111 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));9117 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
9112 buf_appendf(contents, "pub const code_model = CodeModel.default;\n");9118 buf_appendf(contents, "pub const code_model = std.builtin.CodeModel.default;\n");
9113 buf_appendf(contents, "pub const zig_is_stage2 = false;\n");9119 buf_appendf(contents, "pub const zig_is_stage2 = false;\n");
91149120
9115 {9121 {
9116 TargetSubsystem detected_subsystem = detect_subsystem(g);9122 TargetSubsystem detected_subsystem = detect_subsystem(g);
9117 if (detected_subsystem != TargetSubsystemAuto) {9123 if (detected_subsystem != TargetSubsystemAuto) {
9118 buf_appendf(contents, "pub const explicit_subsystem = SubSystem.%s;\n", subsystem_to_str(detected_subsystem));9124 buf_appendf(contents, "pub const explicit_subsystem = std.builtin.SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
9119 }9125 }
9120 }9126 }
91219127
src/value.zig+19-8
...@@ -930,7 +930,11 @@ pub const Value = extern union {...@@ -930,7 +930,11 @@ pub const Value = extern union {
930930
931 /// Asserts the value is comparable.931 /// Asserts the value is comparable.
932 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {932 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {
933 return order(lhs, rhs).compare(op);933 return switch (op) {
934 .eq => lhs.eql(rhs),
935 .neq => !lhs.eql(rhs),
936 else => order(lhs, rhs).compare(op),
937 };
934 }938 }
935939
936 /// Asserts the value is comparable.940 /// Asserts the value is comparable.
...@@ -942,12 +946,19 @@ pub const Value = extern union {...@@ -942,12 +946,19 @@ pub const Value = extern union {
942 const a_tag = a.tag();946 const a_tag = a.tag();
943 const b_tag = b.tag();947 const b_tag = b.tag();
944 if (a_tag == b_tag) {948 if (a_tag == b_tag) {
945 if (a_tag == .void_value or a_tag == .null_value) {949 switch (a_tag) {
946 return true;950 .void_value, .null_value => return true,
947 } else if (a_tag == .enum_literal) {951 .enum_literal => {
948 const a_name = a.castTag(.enum_literal).?.data;952 const a_name = a.castTag(.enum_literal).?.data;
949 const b_name = b.castTag(.enum_literal).?.data;953 const b_name = b.castTag(.enum_literal).?.data;
950 return std.mem.eql(u8, a_name, b_name);954 return std.mem.eql(u8, a_name, b_name);
955 },
956 .enum_field_index => {
957 const a_field_index = a.castTag(.enum_field_index).?.data;
958 const b_field_index = b.castTag(.enum_field_index).?.data;
959 return a_field_index == b_field_index;
960 },
961 else => {},
951 }962 }
952 }963 }
953 if (a.isType() and b.isType()) {964 if (a.isType() and b.isType()) {
...@@ -958,7 +969,7 @@ pub const Value = extern union {...@@ -958,7 +969,7 @@ pub const Value = extern union {
958 const b_type = b.toType(&fib.allocator) catch unreachable;969 const b_type = b.toType(&fib.allocator) catch unreachable;
959 return a_type.eql(b_type);970 return a_type.eql(b_type);
960 }971 }
961 return compare(a, .eq, b);972 return order(a, b).compare(.eq);
962 }973 }
963974
964 pub fn hash_u32(self: Value) u32 {975 pub fn hash_u32(self: Value) u32 {
src/zir.zig+40-6
...@@ -294,6 +294,12 @@ pub const Inst = struct {...@@ -294,6 +294,12 @@ pub const Inst = struct {
294 /// Equivalent to a decl_ref followed by load.294 /// Equivalent to a decl_ref followed by load.
295 /// Uses the `pl_node` union field. `payload_index` is into `decls`.295 /// Uses the `pl_node` union field. `payload_index` is into `decls`.
296 decl_val,296 decl_val,
297 /// Same as `decl_ref` except instead of indexing into decls, uses
298 /// a name to identify the Decl. Uses the `str_tok` union field.
299 decl_ref_named,
300 /// Same as `decl_val` except instead of indexing into decls, uses
301 /// a name to identify the Decl. Uses the `str_tok` union field.
302 decl_val_named,
297 /// Load the value from a pointer. Assumes `x.*` syntax.303 /// Load the value from a pointer. Assumes `x.*` syntax.
298 /// Uses `un_node` field. AST node is the `x.*` syntax.304 /// Uses `un_node` field. AST node is the `x.*` syntax.
299 load,305 load,
...@@ -744,6 +750,8 @@ pub const Inst = struct {...@@ -744,6 +750,8 @@ pub const Inst = struct {
744 .dbg_stmt_node,750 .dbg_stmt_node,
745 .decl_ref,751 .decl_ref,
746 .decl_val,752 .decl_val,
753 .decl_ref_named,
754 .decl_val_named,
747 .load,755 .load,
748 .div,756 .div,
749 .elem_ptr,757 .elem_ptr,
...@@ -1507,17 +1515,19 @@ pub const Inst = struct {...@@ -1507,17 +1515,19 @@ pub const Inst = struct {
1507 };1515 };
15081516
1509 /// Trailing:1517 /// Trailing:
1510 /// 0. has_bits: u32 // for every 16 fields1518 /// 0. inst: Index // for every body_len
1519 /// 1. has_bits: u32 // for every 16 fields
1511 /// - sets of 2 bits:1520 /// - sets of 2 bits:
1512 /// 0b0X: whether corresponding field has an align expression1521 /// 0b0X: whether corresponding field has an align expression
1513 /// 0bX0: whether corresponding field has a default expression1522 /// 0bX0: whether corresponding field has a default expression
1514 /// 1. fields: { // for every fields_len1523 /// 2. fields: { // for every fields_len
1515 /// field_name: u32,1524 /// field_name: u32,
1516 /// field_type: Ref,1525 /// field_type: Ref,
1517 /// align: Ref, // if corresponding bit is set1526 /// align: Ref, // if corresponding bit is set
1518 /// default_value: Ref, // if corresponding bit is set1527 /// default_value: Ref, // if corresponding bit is set
1519 /// }1528 /// }
1520 pub const StructDecl = struct {1529 pub const StructDecl = struct {
1530 body_len: u32,
1521 fields_len: u32,1531 fields_len: u32,
1522 };1532 };
15231533
...@@ -1792,6 +1802,8 @@ const Writer = struct {...@@ -1792,6 +1802,8 @@ const Writer = struct {
17921802
1793 .error_value,1803 .error_value,
1794 .enum_literal,1804 .enum_literal,
1805 .decl_ref_named,
1806 .decl_val_named,
1795 => try self.writeStrTok(stream, inst),1807 => try self.writeStrTok(stream, inst),
17961808
1797 .fn_type => try self.writeFnType(stream, inst, false),1809 .fn_type => try self.writeFnType(stream, inst, false),
...@@ -1872,7 +1884,16 @@ const Writer = struct {...@@ -1872,7 +1884,16 @@ const Writer = struct {
1872 inst: Inst.Index,1884 inst: Inst.Index,
1873 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {1885 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1874 const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;1886 const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
1875 try stream.writeAll("TODO)");1887 const str_allowzero = if (inst_data.is_allowzero) "allowzero, " else "";
1888 const str_const = if (!inst_data.is_mutable) "const, " else "";
1889 const str_volatile = if (inst_data.is_volatile) "volatile, " else "";
1890 try self.writeInstRef(stream, inst_data.elem_type);
1891 try stream.print(", {s}{s}{s}{s})", .{
1892 str_allowzero,
1893 str_const,
1894 str_volatile,
1895 @tagName(inst_data.size),
1896 });
1876 }1897 }
18771898
1878 fn writePtrType(1899 fn writePtrType(
...@@ -1991,14 +2012,27 @@ const Writer = struct {...@@ -1991,14 +2012,27 @@ const Writer = struct {
1991 fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {2012 fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1992 const inst_data = self.code.instructions.items(.data)[inst].pl_node;2013 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1993 const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index);2014 const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index);
2015 const body = self.code.extra[extra.end..][0..extra.data.body_len];
1994 const fields_len = extra.data.fields_len;2016 const fields_len = extra.data.fields_len;
1995 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;2017
2018 if (fields_len == 0) {
2019 assert(body.len == 0);
2020 try stream.writeAll("{}, {}) ");
2021 try self.writeSrc(stream, inst_data.src());
2022 return;
2023 }
19962024
1997 try stream.writeAll("{\n");2025 try stream.writeAll("{\n");
1998 self.indent += 2;2026 self.indent += 2;
2027 try self.writeBody(stream, body);
19992028
2000 var field_index: usize = extra.end + bit_bags_count;2029 try stream.writeByteNTimes(' ', self.indent - 2);
2001 var bit_bag_index: usize = extra.end;2030 try stream.writeAll("}, {\n");
2031
2032 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
2033 const body_end = extra.end + body.len;
2034 var field_index: usize = body_end + bit_bags_count;
2035 var bit_bag_index: usize = body_end;
2002 var cur_bit_bag: u32 = undefined;2036 var cur_bit_bag: u32 = undefined;
2003 var field_i: u32 = 0;2037 var field_i: u32 = 0;
2004 while (field_i < fields_len) : (field_i += 1) {2038 while (field_i < fields_len) : (field_i += 1) {
test/tests.zig+1-1
...@@ -507,7 +507,7 @@ pub fn addPkgTests(...@@ -507,7 +507,7 @@ pub fn addPkgTests(
507 if (skip_single_threaded and test_target.single_threaded)507 if (skip_single_threaded and test_target.single_threaded)
508 continue;508 continue;
509509
510 const ArchTag = std.meta.Tag(builtin.Arch);510 const ArchTag = std.meta.Tag(std.Target.Cpu.Arch);
511 if (test_target.disable_native and511 if (test_target.disable_native and
512 test_target.target.getOsTag() == std.Target.current.os.tag and512 test_target.target.getOsTag() == std.Target.current.os.tag and
513 test_target.target.getCpuArch() == std.Target.current.cpu.arch)513 test_target.target.getCpuArch() == std.Target.current.cpu.arch)