authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-26 17:36:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-26 17:36:28-07:00
log91c317bb9aa906684104db3d73442ab1198a83f4
tree6d475619655b3b0b6d2914e9b11ad79d21b351b7
parent646eb1fa934c413f29505f4742c67e61314acd90

AstGen: improved handling of declarations

* Every decl provides a 16 byte source hash which can be used to detect if the source code for any particular decl has changed. * Include comptime decls, test decls, and usingnamespace decls in the decls list of namespaces. - Tests are encoded as extended functions with is_test bit set.

3 files changed, 170 insertions(+), 64 deletions(-)

src/AstGen.zig+123-46
...@@ -35,10 +35,10 @@ string_bytes: ArrayListUnmanaged(u8) = .{},...@@ -35,10 +35,10 @@ string_bytes: ArrayListUnmanaged(u8) = .{},
35arena: *Allocator,35arena: *Allocator,
36string_table: std.StringHashMapUnmanaged(u32) = .{},36string_table: std.StringHashMapUnmanaged(u32) = .{},
37compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},37compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
38/// String table indexes, keeps track of all `@import` operands.
39imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
40/// The topmost block of the current function.38/// The topmost block of the current function.
41fn_block: ?*GenZir = null,39fn_block: ?*GenZir = null,
40/// String table indexes, keeps track of all `@import` operands.
41imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
4242
43pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {43pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
44 const fields = std.meta.fields(@TypeOf(extra));44 const fields = std.meta.fields(@TypeOf(extra));
...@@ -1078,6 +1078,7 @@ pub fn fnProtoExpr(...@@ -1078,6 +1078,7 @@ pub fn fnProtoExpr(
1078 .lib_name = 0,1078 .lib_name = 0,
1079 .is_var_args = is_var_args,1079 .is_var_args = is_var_args,
1080 .is_inferred_error = false,1080 .is_inferred_error = false,
1081 .is_test = false,
1081 });1082 });
1082 return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node);1083 return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node);
1083}1084}
...@@ -2610,6 +2611,26 @@ const WipDecls = struct {...@@ -2610,6 +2611,26 @@ const WipDecls = struct {
2610 const bits_per_field = 4;2611 const bits_per_field = 4;
2611 const fields_per_u32 = 32 / bits_per_field;2612 const fields_per_u32 = 32 / bits_per_field;
26122613
2614 fn next(
2615 wip_decls: *WipDecls,
2616 gpa: *Allocator,
2617 is_pub: bool,
2618 is_export: bool,
2619 has_align: bool,
2620 has_section: bool,
2621 ) Allocator.Error!void {
2622 if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) {
2623 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
2624 wip_decls.cur_bit_bag = 0;
2625 }
2626 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> bits_per_field) |
2627 (@as(u32, @boolToInt(is_pub)) << 28) |
2628 (@as(u32, @boolToInt(is_export)) << 29) |
2629 (@as(u32, @boolToInt(has_align)) << 30) |
2630 (@as(u32, @boolToInt(has_section)) << 31);
2631 wip_decls.decl_index += 1;
2632 }
2633
2613 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {2634 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {
2614 wip_decls.bit_bag.deinit(gpa);2635 wip_decls.bit_bag.deinit(gpa);
2615 wip_decls.payload.deinit(gpa);2636 wip_decls.payload.deinit(gpa);
...@@ -2652,16 +2673,7 @@ fn fnDecl(...@@ -2652,16 +2673,7 @@ fn fnDecl(
2652 break :inst try comptimeExpr(&decl_gz, &decl_gz.base, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);2673 break :inst try comptimeExpr(&decl_gz, &decl_gz.base, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
2653 };2674 };
26542675
2655 if (wip_decls.decl_index % WipDecls.fields_per_u32 == 0 and wip_decls.decl_index != 0) {2676 try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none);
2656 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
2657 wip_decls.cur_bit_bag = 0;
2658 }
2659 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> WipDecls.bits_per_field) |
2660 (@as(u32, @boolToInt(is_pub)) << 28) |
2661 (@as(u32, @boolToInt(is_export)) << 29) |
2662 (@as(u32, @boolToInt(align_inst != .none)) << 30) |
2663 (@as(u32, @boolToInt(section_inst != .none)) << 31);
2664 wip_decls.decl_index += 1;
26652677
2666 // The AST params array does not contain anytype and ... parameters.2678 // The AST params array does not contain anytype and ... parameters.
2667 // We must iterate to count how many param types to allocate.2679 // We must iterate to count how many param types to allocate.
...@@ -2750,6 +2762,7 @@ fn fnDecl(...@@ -2750,6 +2762,7 @@ fn fnDecl(
2750 .lib_name = lib_name,2762 .lib_name = lib_name,
2751 .is_var_args = is_var_args,2763 .is_var_args = is_var_args,
2752 .is_inferred_error = false,2764 .is_inferred_error = false,
2765 .is_test = false,
2753 });2766 });
2754 } else func: {2767 } else func: {
2755 if (is_var_args) {2768 if (is_var_args) {
...@@ -2821,6 +2834,7 @@ fn fnDecl(...@@ -2821,6 +2834,7 @@ fn fnDecl(
2821 .lib_name = lib_name,2834 .lib_name = lib_name,
2822 .is_var_args = is_var_args,2835 .is_var_args = is_var_args,
2823 .is_inferred_error = is_inferred_error,2836 .is_inferred_error = is_inferred_error,
2837 .is_test = false,
2824 });2838 });
2825 };2839 };
28262840
...@@ -2833,7 +2847,12 @@ fn fnDecl(...@@ -2833,7 +2847,12 @@ fn fnDecl(
2833 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);2847 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
2834 try decl_gz.setBlockBody(block_inst);2848 try decl_gz.setBlockBody(block_inst);
28352849
2836 try wip_decls.payload.ensureUnusedCapacity(gpa, 4);2850 try wip_decls.payload.ensureUnusedCapacity(gpa, 8);
2851 {
2852 const contents_hash = std.zig.hashSrc(tree.getNodeSource(fn_proto.ast.proto_node));
2853 const casted = @bitCast([4]u32, contents_hash);
2854 wip_decls.payload.appendSliceAssumeCapacity(&casted);
2855 }
2837 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);2856 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);
2838 wip_decls.payload.appendAssumeCapacity(block_inst);2857 wip_decls.payload.appendAssumeCapacity(block_inst);
2839 if (align_inst != .none) {2858 if (align_inst != .none) {
...@@ -2879,16 +2898,7 @@ fn globalVarDecl(...@@ -2879,16 +2898,7 @@ fn globalVarDecl(
2879 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {2898 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
2880 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);2899 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
2881 };2900 };
2882 if (wip_decls.decl_index % WipDecls.fields_per_u32 == 0 and wip_decls.decl_index != 0) {2901 try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none);
2883 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
2884 wip_decls.cur_bit_bag = 0;
2885 }
2886 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> WipDecls.bits_per_field) |
2887 (@as(u32, @boolToInt(is_pub)) << 28) |
2888 (@as(u32, @boolToInt(is_export)) << 29) |
2889 (@as(u32, @boolToInt(align_inst != .none)) << 30) |
2890 (@as(u32, @boolToInt(section_inst != .none)) << 31);
2891 wip_decls.decl_index += 1;
28922902
2893 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;2903 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
2894 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {2904 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
...@@ -2950,7 +2960,12 @@ fn globalVarDecl(...@@ -2950,7 +2960,12 @@ fn globalVarDecl(
2950 const name_token = var_decl.ast.mut_token + 1;2960 const name_token = var_decl.ast.mut_token + 1;
2951 const name_str_index = try gz.identAsString(name_token);2961 const name_str_index = try gz.identAsString(name_token);
29522962
2953 try wip_decls.payload.ensureUnusedCapacity(gpa, 4);2963 try wip_decls.payload.ensureUnusedCapacity(gpa, 8);
2964 {
2965 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
2966 const casted = @bitCast([4]u32, contents_hash);
2967 wip_decls.payload.appendSliceAssumeCapacity(&casted);
2968 }
2954 wip_decls.payload.appendAssumeCapacity(name_str_index);2969 wip_decls.payload.appendAssumeCapacity(name_str_index);
2955 wip_decls.payload.appendAssumeCapacity(var_inst);2970 wip_decls.payload.appendAssumeCapacity(var_inst);
2956 if (align_inst != .none) {2971 if (align_inst != .none) {
...@@ -2965,21 +2980,48 @@ fn comptimeDecl(...@@ -2965,21 +2980,48 @@ fn comptimeDecl(
2965 astgen: *AstGen,2980 astgen: *AstGen,
2966 gz: *GenZir,2981 gz: *GenZir,
2967 scope: *Scope,2982 scope: *Scope,
2983 wip_decls: *WipDecls,
2968 node: ast.Node.Index,2984 node: ast.Node.Index,
2969) InnerError!void {2985) InnerError!void {
2986 const gpa = astgen.gpa;
2970 const tree = &astgen.file.tree;2987 const tree = &astgen.file.tree;
2971 const node_datas = tree.nodes.items(.data);2988 const node_datas = tree.nodes.items(.data);
2972 const block_expr = node_datas[node].lhs;2989 const body_node = node_datas[node].lhs;
2973 // TODO probably we want to put these into a block and store a list of them2990
2974 _ = try expr(gz, scope, .none, block_expr);2991 // Up top so the ZIR instruction index marks the start range of this
2992 // top-level declaration.
2993 const block_inst = try gz.addBlock(.block_inline, node);
2994 try wip_decls.next(gpa, false, false, false, false);
2995
2996 var decl_block: GenZir = .{
2997 .force_comptime = true,
2998 .decl_node_index = node,
2999 .parent = scope,
3000 .astgen = astgen,
3001 };
3002 defer decl_block.instructions.deinit(gpa);
3003
3004 _ = try expr(&decl_block, &decl_block.base, .none, body_node);
3005 try decl_block.setBlockBody(block_inst);
3006
3007 try wip_decls.payload.ensureUnusedCapacity(gpa, 6);
3008 {
3009 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3010 const casted = @bitCast([4]u32, contents_hash);
3011 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3012 }
3013 wip_decls.payload.appendAssumeCapacity(0);
3014 wip_decls.payload.appendAssumeCapacity(block_inst);
2975}3015}
29763016
2977fn usingnamespaceDecl(3017fn usingnamespaceDecl(
2978 astgen: *AstGen,3018 astgen: *AstGen,
2979 gz: *GenZir,3019 gz: *GenZir,
2980 scope: *Scope,3020 scope: *Scope,
3021 wip_decls: *WipDecls,
2981 node: ast.Node.Index,3022 node: ast.Node.Index,
2982) InnerError!void {3023) InnerError!void {
3024 const gpa = astgen.gpa;
2983 const tree = &astgen.file.tree;3025 const tree = &astgen.file.tree;
2984 const node_datas = tree.nodes.items(.data);3026 const node_datas = tree.nodes.items(.data);
29853027
...@@ -2990,14 +3032,38 @@ fn usingnamespaceDecl(...@@ -2990,14 +3032,38 @@ fn usingnamespaceDecl(
2990 const main_token = main_tokens[node];3032 const main_token = main_tokens[node];
2991 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);3033 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
2992 };3034 };
2993 // TODO probably we want to put these into a block and store a list of them3035 // Up top so the ZIR instruction index marks the start range of this
2994 const namespace_inst = try expr(gz, scope, .{ .ty = .type_type }, type_expr);3036 // top-level declaration.
3037 const block_inst = try gz.addBlock(.block_inline, node);
3038 try wip_decls.next(gpa, is_pub, true, false, false);
3039
3040 var decl_block: GenZir = .{
3041 .force_comptime = true,
3042 .decl_node_index = node,
3043 .parent = scope,
3044 .astgen = astgen,
3045 };
3046 defer decl_block.instructions.deinit(gpa);
3047
3048 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);
3049 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);
3050 try decl_block.setBlockBody(block_inst);
3051
3052 try wip_decls.payload.ensureUnusedCapacity(gpa, 6);
3053 {
3054 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3055 const casted = @bitCast([4]u32, contents_hash);
3056 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3057 }
3058 wip_decls.payload.appendAssumeCapacity(0);
3059 wip_decls.payload.appendAssumeCapacity(block_inst);
2995}3060}
29963061
2997fn testDecl(3062fn testDecl(
2998 astgen: *AstGen,3063 astgen: *AstGen,
2999 gz: *GenZir,3064 gz: *GenZir,
3000 scope: *Scope,3065 scope: *Scope,
3066 wip_decls: *WipDecls,
3001 node: ast.Node.Index,3067 node: ast.Node.Index,
3002) InnerError!void {3068) InnerError!void {
3003 const gpa = astgen.gpa;3069 const gpa = astgen.gpa;
...@@ -3005,10 +3071,16 @@ fn testDecl(...@@ -3005,10 +3071,16 @@ fn testDecl(
3005 const node_datas = tree.nodes.items(.data);3071 const node_datas = tree.nodes.items(.data);
3006 const body_node = node_datas[node].rhs;3072 const body_node = node_datas[node].rhs;
30073073
3074 // Up top so the ZIR instruction index marks the start range of this
3075 // top-level declaration.
3076 const block_inst = try gz.addBlock(.block_inline, node);
3077
3078 try wip_decls.next(gpa, false, false, false, false);
3079
3008 var decl_block: GenZir = .{3080 var decl_block: GenZir = .{
3009 .force_comptime = true,3081 .force_comptime = true,
3010 .decl_node_index = node,3082 .decl_node_index = node,
3011 .parent = &gz.base,3083 .parent = scope,
3012 .astgen = astgen,3084 .astgen = astgen,
3013 };3085 };
3014 defer decl_block.instructions.deinit(gpa);3086 defer decl_block.instructions.deinit(gpa);
...@@ -3053,15 +3125,20 @@ fn testDecl(...@@ -3053,15 +3125,20 @@ fn testDecl(
3053 .lib_name = 0,3125 .lib_name = 0,
3054 .is_var_args = false,3126 .is_var_args = false,
3055 .is_inferred_error = true,3127 .is_inferred_error = true,
3128 .is_test = true,
3056 });3129 });
30573130
3058 const block_inst = try gz.addBlock(.block_inline, node);
3059 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);3131 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
3060 try decl_block.setBlockBody(block_inst);3132 try decl_block.setBlockBody(block_inst);
30613133
3062 // TODO collect these into a test decl list3134 try wip_decls.payload.ensureUnusedCapacity(gpa, 6);
3063 _ = test_name;3135 {
3064 _ = block_inst;3136 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3137 const casted = @bitCast([4]u32, contents_hash);
3138 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3139 }
3140 wip_decls.payload.appendAssumeCapacity(test_name);
3141 wip_decls.payload.appendAssumeCapacity(block_inst);
3065}3142}
30663143
3067fn structDeclInner(3144fn structDeclInner(
...@@ -3179,15 +3256,15 @@ fn structDeclInner(...@@ -3179,15 +3256,15 @@ fn structDeclInner(
3179 },3256 },
31803257
3181 .@"comptime" => {3258 .@"comptime" => {
3182 try astgen.comptimeDecl(gz, scope, member_node);3259 try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
3183 continue;3260 continue;
3184 },3261 },
3185 .@"usingnamespace" => {3262 .@"usingnamespace" => {
3186 try astgen.usingnamespaceDecl(gz, scope, member_node);3263 try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
3187 continue;3264 continue;
3188 },3265 },
3189 .test_decl => {3266 .test_decl => {
3190 try astgen.testDecl(gz, scope, member_node);3267 try astgen.testDecl(gz, scope, &wip_decls, member_node);
3191 continue;3268 continue;
3192 },3269 },
3193 else => unreachable,3270 else => unreachable,
...@@ -3382,15 +3459,15 @@ fn unionDeclInner(...@@ -3382,15 +3459,15 @@ fn unionDeclInner(
3382 },3459 },
33833460
3384 .@"comptime" => {3461 .@"comptime" => {
3385 try astgen.comptimeDecl(gz, scope, member_node);3462 try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
3386 continue;3463 continue;
3387 },3464 },
3388 .@"usingnamespace" => {3465 .@"usingnamespace" => {
3389 try astgen.usingnamespaceDecl(gz, scope, member_node);3466 try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
3390 continue;3467 continue;
3391 },3468 },
3392 .test_decl => {3469 .test_decl => {
3393 try astgen.testDecl(gz, scope, member_node);3470 try astgen.testDecl(gz, scope, &wip_decls, member_node);
3394 continue;3471 continue;
3395 },3472 },
3396 else => unreachable,3473 else => unreachable,
...@@ -3731,15 +3808,15 @@ fn containerDecl(...@@ -3731,15 +3808,15 @@ fn containerDecl(
3731 },3808 },
37323809
3733 .@"comptime" => {3810 .@"comptime" => {
3734 try astgen.comptimeDecl(gz, scope, member_node);3811 try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
3735 continue;3812 continue;
3736 },3813 },
3737 .@"usingnamespace" => {3814 .@"usingnamespace" => {
3738 try astgen.usingnamespaceDecl(gz, scope, member_node);3815 try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
3739 continue;3816 continue;
3740 },3817 },
3741 .test_decl => {3818 .test_decl => {
3742 try astgen.testDecl(gz, scope, member_node);3819 try astgen.testDecl(gz, scope, &wip_decls, member_node);
3743 continue;3820 continue;
3744 },3821 },
3745 else => unreachable,3822 else => unreachable,
...@@ -3896,15 +3973,15 @@ fn containerDecl(...@@ -3896,15 +3973,15 @@ fn containerDecl(
3896 },3973 },
38973974
3898 .@"comptime" => {3975 .@"comptime" => {
3899 try astgen.comptimeDecl(gz, scope, member_node);3976 try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
3900 continue;3977 continue;
3901 },3978 },
3902 .@"usingnamespace" => {3979 .@"usingnamespace" => {
3903 try astgen.usingnamespaceDecl(gz, scope, member_node);3980 try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
3904 continue;3981 continue;
3905 },3982 },
3906 .test_decl => {3983 .test_decl => {
3907 try astgen.testDecl(gz, scope, member_node);3984 try astgen.testDecl(gz, scope, &wip_decls, member_node);
3908 continue;3985 continue;
3909 },3986 },
3910 else => unreachable,3987 else => unreachable,
src/Module.zig+3-1
...@@ -1311,6 +1311,7 @@ pub const Scope = struct {...@@ -1311,6 +1311,7 @@ pub const Scope = struct {
1311 lib_name: u32,1311 lib_name: u32,
1312 is_var_args: bool,1312 is_var_args: bool,
1313 is_inferred_error: bool,1313 is_inferred_error: bool,
1314 is_test: bool,
1314 }) !Zir.Inst.Ref {1315 }) !Zir.Inst.Ref {
1315 assert(args.src_node != 0);1316 assert(args.src_node != 0);
1316 assert(args.ret_ty != .none);1317 assert(args.ret_ty != .none);
...@@ -1320,7 +1321,7 @@ pub const Scope = struct {...@@ -1320,7 +1321,7 @@ pub const Scope = struct {
1320 try gz.instructions.ensureUnusedCapacity(gpa, 1);1321 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1321 try astgen.instructions.ensureUnusedCapacity(gpa, 1);1322 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
13221323
1323 if (args.cc != .none or args.lib_name != 0 or args.is_var_args) {1324 if (args.cc != .none or args.lib_name != 0 or args.is_var_args or args.is_test) {
1324 try astgen.extra.ensureUnusedCapacity(1325 try astgen.extra.ensureUnusedCapacity(
1325 gpa,1326 gpa,
1326 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +1327 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
...@@ -1353,6 +1354,7 @@ pub const Scope = struct {...@@ -1353,6 +1354,7 @@ pub const Scope = struct {
1353 .is_inferred_error = args.is_inferred_error,1354 .is_inferred_error = args.is_inferred_error,
1354 .has_lib_name = args.lib_name != 0,1355 .has_lib_name = args.lib_name != 0,
1355 .has_cc = args.cc != .none,1356 .has_cc = args.cc != .none,
1357 .is_test = args.is_test,
1356 }),1358 }),
1357 .operand = payload_index,1359 .operand = payload_index,
1358 } },1360 } },
src/Zir.zig+44-17
...@@ -2201,7 +2201,8 @@ pub const Inst = struct {...@@ -2201,7 +2201,8 @@ pub const Inst = struct {
2201 is_inferred_error: bool,2201 is_inferred_error: bool,
2202 has_lib_name: bool,2202 has_lib_name: bool,
2203 has_cc: bool,2203 has_cc: bool,
2204 _: u12 = undefined,2204 is_test: bool,
2205 _: u11 = undefined,
2205 };2206 };
2206 };2207 };
22072208
...@@ -2375,7 +2376,10 @@ pub const Inst = struct {...@@ -2375,7 +2376,10 @@ pub const Inst = struct {
2375 /// 0b0X00: whether corresponding decl has an align expression2376 /// 0b0X00: whether corresponding decl has an align expression
2376 /// 0bX000: whether corresponding decl has a linksection expression2377 /// 0bX000: whether corresponding decl has a linksection expression
2377 /// 1. decl: { // for every decls_len2378 /// 1. decl: { // for every decls_len
2379 /// src_hash: [4]u32, // hash of source bytes
2378 /// name: u32, // null terminated string index2380 /// name: u32, // null terminated string index
2381 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.
2382 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2379 /// value: Index,2383 /// value: Index,
2380 /// align: Ref, // if corresponding bit is set2384 /// align: Ref, // if corresponding bit is set
2381 /// link_section: Ref, // if corresponding bit is set2385 /// link_section: Ref, // if corresponding bit is set
...@@ -2405,7 +2409,10 @@ pub const Inst = struct {...@@ -2405,7 +2409,10 @@ pub const Inst = struct {
2405 /// 0b0X00: whether corresponding decl has an align expression2409 /// 0b0X00: whether corresponding decl has an align expression
2406 /// 0bX000: whether corresponding decl has a linksection expression2410 /// 0bX000: whether corresponding decl has a linksection expression
2407 /// 1. decl: { // for every decls_len2411 /// 1. decl: { // for every decls_len
2412 /// src_hash: [4]u32, // hash of source bytes
2408 /// name: u32, // null terminated string index2413 /// name: u32, // null terminated string index
2414 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.
2415 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2409 /// value: Index,2416 /// value: Index,
2410 /// align: Ref, // if corresponding bit is set2417 /// align: Ref, // if corresponding bit is set
2411 /// link_section: Ref, // if corresponding bit is set2418 /// link_section: Ref, // if corresponding bit is set
...@@ -2433,7 +2440,10 @@ pub const Inst = struct {...@@ -2433,7 +2440,10 @@ pub const Inst = struct {
2433 /// 0b0X00: whether corresponding decl has an align expression2440 /// 0b0X00: whether corresponding decl has an align expression
2434 /// 0bX000: whether corresponding decl has a linksection expression2441 /// 0bX000: whether corresponding decl has a linksection expression
2435 /// 1. decl: { // for every decls_len2442 /// 1. decl: { // for every decls_len
2443 /// src_hash: [4]u32, // hash of source bytes
2436 /// name: u32, // null terminated string index2444 /// name: u32, // null terminated string index
2445 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.
2446 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2437 /// value: Index,2447 /// value: Index,
2438 /// align: Ref, // if corresponding bit is set2448 /// align: Ref, // if corresponding bit is set
2439 /// link_section: Ref, // if corresponding bit is set2449 /// link_section: Ref, // if corresponding bit is set
...@@ -2471,8 +2481,12 @@ pub const Inst = struct {...@@ -2471,8 +2481,12 @@ pub const Inst = struct {
2471 /// 0b0X00: whether corresponding decl has an align expression2481 /// 0b0X00: whether corresponding decl has an align expression
2472 /// 0bX000: whether corresponding decl has a linksection expression2482 /// 0bX000: whether corresponding decl has a linksection expression
2473 /// 1. decl: { // for every decls_len2483 /// 1. decl: { // for every decls_len
2484 /// src_hash: [4]u32, // hash of source bytes
2474 /// name: u32, // null terminated string index2485 /// name: u32, // null terminated string index
2486 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.
2487 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2475 /// value: Index,2488 /// value: Index,
2489 /// - one of: block_inline, block_inline_var
2476 /// align: Ref, // if corresponding bit is set2490 /// align: Ref, // if corresponding bit is set
2477 /// link_section: Ref, // if corresponding bit is set2491 /// link_section: Ref, // if corresponding bit is set
2478 /// }2492 /// }
...@@ -3553,7 +3567,10 @@ const Writer = struct {...@@ -3553,7 +3567,10 @@ const Writer = struct {
3553 const has_section = @truncate(u1, cur_bit_bag) != 0;3567 const has_section = @truncate(u1, cur_bit_bag) != 0;
3554 cur_bit_bag >>= 1;3568 cur_bit_bag >>= 1;
35553569
3556 const decl_name = self.code.nullTerminatedString(self.code.extra[extra_index]);3570 const hash_u32s = self.code.extra[extra_index..][0..4];
3571 extra_index += 4;
3572 const decl_name_index = self.code.extra[extra_index];
3573 const decl_name = self.code.nullTerminatedString(decl_name_index);
3557 extra_index += 1;3574 extra_index += 1;
3558 const decl_index = self.code.extra[extra_index];3575 const decl_index = self.code.extra[extra_index];
3559 extra_index += 1;3576 extra_index += 1;
...@@ -3568,24 +3585,33 @@ const Writer = struct {...@@ -3568,24 +3585,33 @@ const Writer = struct {
3568 break :inst inst;3585 break :inst inst;
3569 };3586 };
35703587
3571 const tag = self.code.instructions.items(.tag)[decl_index];
3572 const pub_str = if (is_pub) "pub " else "";3588 const pub_str = if (is_pub) "pub " else "";
3573 const export_str = if (is_exported) "export " else "";3589 const hash_bytes = @bitCast([16]u8, hash_u32s.*);
3574 try stream.writeByteNTimes(' ', self.indent);3590 try stream.writeByteNTimes(' ', self.indent);
3575 try stream.print("{s}{s}{}", .{3591 if (decl_name_index == 0) {
3576 pub_str, export_str, std.zig.fmtId(decl_name),3592 const name = if (is_exported) "usingnamespace" else "comptime";
3577 });3593 try stream.writeAll(pub_str);
3578 if (align_inst != .none) {3594 try stream.writeAll(name);
3579 try stream.writeAll(" align(");3595 } else {
3580 try self.writeInstRef(stream, align_inst);3596 const export_str = if (is_exported) "export " else "";
3581 try stream.writeAll(")");3597 try stream.print("{s}{s}{}", .{
3582 }3598 pub_str, export_str, std.zig.fmtId(decl_name),
3583 if (section_inst != .none) {3599 });
3584 try stream.writeAll(" linksection(");3600 if (align_inst != .none) {
3585 try self.writeInstRef(stream, section_inst);3601 try stream.writeAll(" align(");
3586 try stream.writeAll(")");3602 try self.writeInstRef(stream, align_inst);
3603 try stream.writeAll(")");
3604 }
3605 if (section_inst != .none) {
3606 try stream.writeAll(" linksection(");
3607 try self.writeInstRef(stream, section_inst);
3608 try stream.writeAll(")");
3609 }
3587 }3610 }
3588 try stream.print(": %{d} = {s}(", .{ decl_index, @tagName(tag) });3611 const tag = self.code.instructions.items(.tag)[decl_index];
3612 try stream.print(" hash({}): %{d} = {s}(", .{
3613 std.fmt.fmtSliceHexLower(&hash_bytes), decl_index, @tagName(tag),
3614 });
35893615
3590 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;3616 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;
3591 const sub_decl_node_off = decl_block_inst_data.src_node;3617 const sub_decl_node_off = decl_block_inst_data.src_node;
...@@ -3939,6 +3965,7 @@ const Writer = struct {...@@ -3939,6 +3965,7 @@ const Writer = struct {
3939 extra_index += 1;3965 extra_index += 1;
3940 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});3966 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
3941 }3967 }
3968 try self.writeFlag(stream, "test, ", small.is_test);
3942 const cc: Inst.Ref = if (!small.has_cc) .none else blk: {3969 const cc: Inst.Ref = if (!small.has_cc) .none else blk: {
3943 const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);3970 const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
3944 extra_index += 1;3971 extra_index += 1;