authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-25 23:00:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-25 23:45:17-07:00
logb2deaf80279aab1322036e55a9646ecbaaa47f44
treef950b7d882299bab45a6d5ea8cd213d1850c2bb0
parent4bfcd105eff797aceb621d2c8b971c15fef6e450

stage2: improve source locations of Decl access

* zir.Code: introduce a decls array. This is so that `decl_val` and `decl_ref` instructions can refer to a Decl with a u32 and therefore they can also store a source location. This is needed for proper compile error reporting. * astgen uses a hash map to avoid redundantly adding a Decl to the decls array. * fixed reporting "instruction illegal outside function body" instead of the desired message "unable to resolve comptime value". * astgen skips emitting dbg_stmt instructions in comptime scopes. * astgen has some logic to avoid adding unnecessary type coercion instructions for common values.

6 files changed, 148 insertions(+), 66 deletions(-)

BRANCH_TODO+3
...@@ -38,3 +38,6 @@ Performance optimizations to look into:...@@ -38,3 +38,6 @@ Performance optimizations to look into:
38 * astgen for loops using pointer arithmetic because it's faster and if the programmer38 * astgen for loops using pointer arithmetic because it's faster and if the programmer
39 wants an index capture, that will just be a convenience variable that zig sets up39 wants an index capture, that will just be a convenience variable that zig sets up
40 independently.40 independently.
41 * in astgen, if a decl_val would be to a const variable or to a function, there could be
42 a special zir.Inst.Ref form that means to refer to a decl as the operand. This
43 would elide all the decl_val instructions in the ZIR.
src/Module.zig+21-12
...@@ -103,7 +103,7 @@ stage1_flags: packed struct {...@@ -103,7 +103,7 @@ stage1_flags: packed struct {
103103
104emit_h: ?Compilation.EmitLoc,104emit_h: ?Compilation.EmitLoc,
105105
106compile_log_text: std.ArrayListUnmanaged(u8) = .{},106compile_log_text: ArrayListUnmanaged(u8) = .{},
107107
108pub const Export = struct {108pub const Export = struct {
109 options: std.builtin.ExportOptions,109 options: std.builtin.ExportOptions,
...@@ -335,7 +335,7 @@ pub const Decl = struct {...@@ -335,7 +335,7 @@ pub const Decl = struct {
335335
336/// This state is attached to every Decl when Module emit_h is non-null.336/// This state is attached to every Decl when Module emit_h is non-null.
337pub const EmitH = struct {337pub const EmitH = struct {
338 fwd_decl: std.ArrayListUnmanaged(u8) = .{},338 fwd_decl: ArrayListUnmanaged(u8) = .{},
339};339};
340340
341/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.341/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
...@@ -916,7 +916,7 @@ pub const Scope = struct {...@@ -916,7 +916,7 @@ pub const Scope = struct {
916 zir_code: *WipZirCode,916 zir_code: *WipZirCode,
917 /// Keeps track of the list of instructions in this scope only. Indexes917 /// Keeps track of the list of instructions in this scope only. Indexes
918 /// to instructions in `zir_code`.918 /// to instructions in `zir_code`.
919 instructions: std.ArrayListUnmanaged(zir.Inst.Index) = .{},919 instructions: ArrayListUnmanaged(zir.Inst.Index) = .{},
920 label: ?Label = null,920 label: ?Label = null,
921 break_block: zir.Inst.Index = 0,921 break_block: zir.Inst.Index = 0,
922 continue_block: zir.Inst.Index = 0,922 continue_block: zir.Inst.Index = 0,
...@@ -935,11 +935,11 @@ pub const Scope = struct {...@@ -935,11 +935,11 @@ pub const Scope = struct {
935 break_count: usize = 0,935 break_count: usize = 0,
936 /// Tracks `break :foo bar` instructions so they can possibly be elided later if936 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
937 /// the labeled block ends up not needing a result location pointer.937 /// the labeled block ends up not needing a result location pointer.
938 labeled_breaks: std.ArrayListUnmanaged(zir.Inst.Index) = .{},938 labeled_breaks: ArrayListUnmanaged(zir.Inst.Index) = .{},
939 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions939 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
940 /// so they can possibly be elided later if the labeled block ends up not needing940 /// so they can possibly be elided later if the labeled block ends up not needing
941 /// a result location pointer.941 /// a result location pointer.
942 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(zir.Inst.Index) = .{},942 labeled_store_to_block_ptr_list: ArrayListUnmanaged(zir.Inst.Index) = .{},
943943
944 pub const Label = struct {944 pub const Label = struct {
945 token: ast.TokenIndex,945 token: ast.TokenIndex,
...@@ -957,6 +957,7 @@ pub const Scope = struct {...@@ -957,6 +957,7 @@ pub const Scope = struct {
957 .instructions = gz.zir_code.instructions.toOwnedSlice(),957 .instructions = gz.zir_code.instructions.toOwnedSlice(),
958 .string_bytes = gz.zir_code.string_bytes.toOwnedSlice(gpa),958 .string_bytes = gz.zir_code.string_bytes.toOwnedSlice(gpa),
959 .extra = gz.zir_code.extra.toOwnedSlice(gpa),959 .extra = gz.zir_code.extra.toOwnedSlice(gpa),
960 .decls = gz.zir_code.decls.toOwnedSlice(gpa),
960 };961 };
961 }962 }
962963
...@@ -1253,11 +1254,15 @@ pub const Scope = struct {...@@ -1253,11 +1254,15 @@ pub const Scope = struct {
1253 pub fn addDecl(1254 pub fn addDecl(
1254 gz: *GenZir,1255 gz: *GenZir,
1255 tag: zir.Inst.Tag,1256 tag: zir.Inst.Tag,
1256 decl: *Decl,1257 decl_index: u32,
1258 src_node: ast.Node.Index,
1257 ) !zir.Inst.Ref {1259 ) !zir.Inst.Ref {
1258 return gz.add(.{1260 return gz.add(.{
1259 .tag = tag,1261 .tag = tag,
1260 .data = .{ .decl = decl },1262 .data = .{ .pl_node = .{
1263 .src_node = gz.zir_code.decl.nodeIndexToRelative(src_node),
1264 .payload_index = decl_index,
1265 } },
1261 });1266 });
1262 }1267 }
12631268
...@@ -1379,8 +1384,10 @@ pub const Scope = struct {...@@ -1379,8 +1384,10 @@ pub const Scope = struct {
1379/// The `GenZir.finish` function converts this to a `zir.Code`.1384/// The `GenZir.finish` function converts this to a `zir.Code`.
1380pub const WipZirCode = struct {1385pub const WipZirCode = struct {
1381 instructions: std.MultiArrayList(zir.Inst) = .{},1386 instructions: std.MultiArrayList(zir.Inst) = .{},
1382 string_bytes: std.ArrayListUnmanaged(u8) = .{},1387 string_bytes: ArrayListUnmanaged(u8) = .{},
1383 extra: std.ArrayListUnmanaged(u32) = .{},1388 extra: ArrayListUnmanaged(u32) = .{},
1389 decl_map: std.StringArrayHashMapUnmanaged(void) = .{},
1390 decls: ArrayListUnmanaged(*Decl) = .{},
1384 /// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert1391 /// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert
1385 /// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.1392 /// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.
1386 ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,1393 ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,
...@@ -1442,6 +1449,8 @@ pub const WipZirCode = struct {...@@ -1442,6 +1449,8 @@ pub const WipZirCode = struct {
1442 wzc.instructions.deinit(wzc.gpa);1449 wzc.instructions.deinit(wzc.gpa);
1443 wzc.extra.deinit(wzc.gpa);1450 wzc.extra.deinit(wzc.gpa);
1444 wzc.string_bytes.deinit(wzc.gpa);1451 wzc.string_bytes.deinit(wzc.gpa);
1452 wzc.decl_map.deinit(wzc.gpa);
1453 wzc.decls.deinit(wzc.gpa);
1445 }1454 }
1446};1455};
14471456
...@@ -4062,7 +4071,7 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)...@@ -4062,7 +4071,7 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)
4062 if (!mem.startsWith(u8, ident_name, "@")) {4071 if (!mem.startsWith(u8, ident_name, "@")) {
4063 return ident_name;4072 return ident_name;
4064 }4073 }
4065 var buf: std.ArrayListUnmanaged(u8) = .{};4074 var buf: ArrayListUnmanaged(u8) = .{};
4066 defer buf.deinit(mod.gpa);4075 defer buf.deinit(mod.gpa);
4067 try parseStrLit(mod, scope, token, &buf, ident_name, 1);4076 try parseStrLit(mod, scope, token, &buf, ident_name, 1);
4068 return buf.toOwnedSlice(mod.gpa);4077 return buf.toOwnedSlice(mod.gpa);
...@@ -4075,7 +4084,7 @@ pub fn appendIdentStr(...@@ -4075,7 +4084,7 @@ pub fn appendIdentStr(
4075 mod: *Module,4084 mod: *Module,
4076 scope: *Scope,4085 scope: *Scope,
4077 token: ast.TokenIndex,4086 token: ast.TokenIndex,
4078 buf: *std.ArrayListUnmanaged(u8),4087 buf: *ArrayListUnmanaged(u8),
4079) InnerError!void {4088) InnerError!void {
4080 const tree = scope.tree();4089 const tree = scope.tree();
4081 const token_tags = tree.tokens.items(.tag);4090 const token_tags = tree.tokens.items(.tag);
...@@ -4093,7 +4102,7 @@ pub fn parseStrLit(...@@ -4093,7 +4102,7 @@ pub fn parseStrLit(
4093 mod: *Module,4102 mod: *Module,
4094 scope: *Scope,4103 scope: *Scope,
4095 token: ast.TokenIndex,4104 token: ast.TokenIndex,
4096 buf: *std.ArrayListUnmanaged(u8),4105 buf: *ArrayListUnmanaged(u8),
4097 bytes: []const u8,4106 bytes: []const u8,
4098 offset: u32,4107 offset: u32,
4099) InnerError!void {4108) InnerError!void {
src/Sema.zig+14-5
...@@ -1102,10 +1102,15 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1102,10 +1102,15 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
1102 const tracy = trace(@src());1102 const tracy = trace(@src());
1103 defer tracy.end();1103 defer tracy.end();
11041104
1105 // We do not set sema.src here because dbg_stmt instructions are only emitted for
1106 // ZIR code that possibly will need to generate runtime code. So error messages
1107 // and other source locations must not rely on sema.src being set from dbg_stmt
1108 // instructions.
1105 if (block.is_comptime) return;1109 if (block.is_comptime) return;
11061110
1107 const src_node = sema.code.instructions.items(.data)[inst].node;1111 const src_node = sema.code.instructions.items(.data)[inst].node;
1108 const src: LazySrcLoc = .{ .node_offset = src_node };1112 const src: LazySrcLoc = .{ .node_offset = src_node };
1113
1109 const src_loc = src.toSrcLoc(&block.base);1114 const src_loc = src.toSrcLoc(&block.base);
1110 const abs_byte_off = try src_loc.byteOffset();1115 const abs_byte_off = try src_loc.byteOffset();
1111 _ = try block.addDbgStmt(src, abs_byte_off);1116 _ = try block.addDbgStmt(src, abs_byte_off);
...@@ -1115,16 +1120,20 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -1115,16 +1120,20 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
1115 const tracy = trace(@src());1120 const tracy = trace(@src());
1116 defer tracy.end();1121 defer tracy.end();
11171122
1118 const decl = sema.code.instructions.items(.data)[inst].decl;1123 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1119 return sema.analyzeDeclRef(block, .unneeded, decl);1124 const src = inst_data.src();
1125 const decl = sema.code.decls[inst_data.payload_index];
1126 return sema.analyzeDeclRef(block, src, decl);
1120}1127}
11211128
1122fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1129fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1123 const tracy = trace(@src());1130 const tracy = trace(@src());
1124 defer tracy.end();1131 defer tracy.end();
11251132
1126 const decl = sema.code.instructions.items(.data)[inst].decl;1133 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1127 return sema.analyzeDeclVal(block, .unneeded, decl);1134 const src = inst_data.src();
1135 const decl = sema.code.decls[inst_data.payload_index];
1136 return sema.analyzeDeclVal(block, src, decl);
1128}1137}
11291138
1130fn zirCallNone(1139fn zirCallNone(
...@@ -3211,10 +3220,10 @@ fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void...@@ -3211,10 +3220,10 @@ fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void
3211}3220}
32123221
3213fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {3222fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
3214 try sema.requireFunctionBlock(block, src);
3215 if (block.is_comptime) {3223 if (block.is_comptime) {
3216 return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{});3224 return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{});
3217 }3225 }
3226 try sema.requireFunctionBlock(block, src);
3218}3227}
32193228
3220fn validateVarType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !void {3229fn validateVarType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !void {
src/astgen.zig+77-12
...@@ -952,7 +952,9 @@ fn blockExprStmts(...@@ -952,7 +952,9 @@ fn blockExprStmts(
952952
953 var scope = parent_scope;953 var scope = parent_scope;
954 for (statements) |statement| {954 for (statements) |statement| {
955 _ = try gz.addNode(.dbg_stmt_node, statement);955 if (!gz.force_comptime) {
956 _ = try gz.addNode(.dbg_stmt_node, statement);
957 }
956 switch (node_tags[statement]) {958 switch (node_tags[statement]) {
957 .global_var_decl => scope = try varDecl(mod, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),959 .global_var_decl => scope = try varDecl(mod, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
958 .local_var_decl => scope = try varDecl(mod, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),960 .local_var_decl => scope = try varDecl(mod, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),
...@@ -2846,14 +2848,17 @@ fn identifier(...@@ -2846,14 +2848,17 @@ fn identifier(
2846 };2848 };
2847 }2849 }
28482850
2849 if (mod.lookupDeclName(scope, ident_name)) |decl| {2851 const gop = try gz.zir_code.decl_map.getOrPut(mod.gpa, ident_name);
2850 return if (rl == .ref)2852 if (!gop.found_existing) {
2851 gz.addDecl(.decl_ref, decl)2853 const decl = mod.lookupDeclName(scope, ident_name) orelse
2852 else2854 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
2853 rvalue(mod, scope, rl, try gz.addDecl(.decl_val, decl), ident);2855 try gz.zir_code.decls.append(mod.gpa, decl);
2856 }
2857 const decl_index = @intCast(u32, gop.index);
2858 switch (rl) {
2859 .ref => return gz.addDecl(.decl_ref, decl_index, ident),
2860 else => return rvalue(mod, scope, rl, try gz.addDecl(.decl_val, decl_index, ident), ident),
2854 }2861 }
2855
2856 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
2857}2862}
28582863
2859fn stringLiteral(2864fn stringLiteral(
...@@ -3743,10 +3748,70 @@ fn rvalue(...@@ -3743,10 +3748,70 @@ fn rvalue(
3743 const src_token = tree.firstToken(src_node);3748 const src_token = tree.firstToken(src_node);
3744 return gz.addUnTok(.ref, result, src_token);3749 return gz.addUnTok(.ref, result, src_token);
3745 },3750 },
3746 .ty => |ty_inst| return gz.addPlNode(.as_node, src_node, zir.Inst.As{3751 .ty => |ty_inst| {
3747 .dest_type = ty_inst,3752 // Quickly eliminate some common, unnecessary type coercion.
3748 .operand = result,3753 const as_ty = @as(u64, @enumToInt(zir.Inst.Ref.type_type)) << 32;
3749 }),3754 const as_comptime_int = @as(u64, @enumToInt(zir.Inst.Ref.comptime_int_type)) << 32;
3755 const as_bool = @as(u64, @enumToInt(zir.Inst.Ref.bool_type)) << 32;
3756 const as_usize = @as(u64, @enumToInt(zir.Inst.Ref.usize_type)) << 32;
3757 const as_void = @as(u64, @enumToInt(zir.Inst.Ref.void_type)) << 32;
3758 switch ((@as(u64, @enumToInt(ty_inst)) << 32) | @as(u64, @enumToInt(result))) {
3759 as_ty | @enumToInt(zir.Inst.Ref.u8_type),
3760 as_ty | @enumToInt(zir.Inst.Ref.i8_type),
3761 as_ty | @enumToInt(zir.Inst.Ref.u16_type),
3762 as_ty | @enumToInt(zir.Inst.Ref.i16_type),
3763 as_ty | @enumToInt(zir.Inst.Ref.u32_type),
3764 as_ty | @enumToInt(zir.Inst.Ref.i32_type),
3765 as_ty | @enumToInt(zir.Inst.Ref.u64_type),
3766 as_ty | @enumToInt(zir.Inst.Ref.i64_type),
3767 as_ty | @enumToInt(zir.Inst.Ref.usize_type),
3768 as_ty | @enumToInt(zir.Inst.Ref.isize_type),
3769 as_ty | @enumToInt(zir.Inst.Ref.c_short_type),
3770 as_ty | @enumToInt(zir.Inst.Ref.c_ushort_type),
3771 as_ty | @enumToInt(zir.Inst.Ref.c_int_type),
3772 as_ty | @enumToInt(zir.Inst.Ref.c_uint_type),
3773 as_ty | @enumToInt(zir.Inst.Ref.c_long_type),
3774 as_ty | @enumToInt(zir.Inst.Ref.c_ulong_type),
3775 as_ty | @enumToInt(zir.Inst.Ref.c_longlong_type),
3776 as_ty | @enumToInt(zir.Inst.Ref.c_ulonglong_type),
3777 as_ty | @enumToInt(zir.Inst.Ref.c_longdouble_type),
3778 as_ty | @enumToInt(zir.Inst.Ref.f16_type),
3779 as_ty | @enumToInt(zir.Inst.Ref.f32_type),
3780 as_ty | @enumToInt(zir.Inst.Ref.f64_type),
3781 as_ty | @enumToInt(zir.Inst.Ref.f128_type),
3782 as_ty | @enumToInt(zir.Inst.Ref.c_void_type),
3783 as_ty | @enumToInt(zir.Inst.Ref.bool_type),
3784 as_ty | @enumToInt(zir.Inst.Ref.void_type),
3785 as_ty | @enumToInt(zir.Inst.Ref.type_type),
3786 as_ty | @enumToInt(zir.Inst.Ref.anyerror_type),
3787 as_ty | @enumToInt(zir.Inst.Ref.comptime_int_type),
3788 as_ty | @enumToInt(zir.Inst.Ref.comptime_float_type),
3789 as_ty | @enumToInt(zir.Inst.Ref.noreturn_type),
3790 as_ty | @enumToInt(zir.Inst.Ref.null_type),
3791 as_ty | @enumToInt(zir.Inst.Ref.undefined_type),
3792 as_ty | @enumToInt(zir.Inst.Ref.fn_noreturn_no_args_type),
3793 as_ty | @enumToInt(zir.Inst.Ref.fn_void_no_args_type),
3794 as_ty | @enumToInt(zir.Inst.Ref.fn_naked_noreturn_no_args_type),
3795 as_ty | @enumToInt(zir.Inst.Ref.fn_ccc_void_no_args_type),
3796 as_ty | @enumToInt(zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
3797 as_ty | @enumToInt(zir.Inst.Ref.const_slice_u8_type),
3798 as_ty | @enumToInt(zir.Inst.Ref.enum_literal_type),
3799 as_comptime_int | @enumToInt(zir.Inst.Ref.zero),
3800 as_comptime_int | @enumToInt(zir.Inst.Ref.one),
3801 as_bool | @enumToInt(zir.Inst.Ref.bool_true),
3802 as_bool | @enumToInt(zir.Inst.Ref.bool_false),
3803 as_usize | @enumToInt(zir.Inst.Ref.zero_usize),
3804 as_usize | @enumToInt(zir.Inst.Ref.one_usize),
3805 as_void | @enumToInt(zir.Inst.Ref.void_value),
3806 => return result, // type of result is already correct
3807
3808 // Need an explicit type coercion instruction.
3809 else => return gz.addPlNode(.as_node, src_node, zir.Inst.As{
3810 .dest_type = ty_inst,
3811 .operand = result,
3812 }),
3813 }
3814 },
3750 .ptr => |ptr_inst| {3815 .ptr => |ptr_inst| {
3751 _ = try gz.addPlNode(.store_node, src_node, zir.Inst.Bin{3816 _ = try gz.addPlNode(.store_node, src_node, zir.Inst.Bin{
3752 .lhs = ptr_inst,3817 .lhs = ptr_inst,
src/zir.zig+18-22
...@@ -37,6 +37,8 @@ pub const Code = struct {...@@ -37,6 +37,8 @@ pub const Code = struct {
37 string_bytes: []u8,37 string_bytes: []u8,
38 /// The meaning of this data is determined by `Inst.Tag` value.38 /// The meaning of this data is determined by `Inst.Tag` value.
39 extra: []u32,39 extra: []u32,
40 /// Used for decl_val and decl_ref instructions.
41 decls: []*Module.Decl,
4042
41 /// Returns the requested data, as well as the new index which is at the start of the43 /// Returns the requested data, as well as the new index which is at the start of the
42 /// trailers for the object.44 /// trailers for the object.
...@@ -76,6 +78,7 @@ pub const Code = struct {...@@ -76,6 +78,7 @@ pub const Code = struct {
76 code.instructions.deinit(gpa);78 code.instructions.deinit(gpa);
77 gpa.free(code.string_bytes);79 gpa.free(code.string_bytes);
78 gpa.free(code.extra);80 gpa.free(code.extra);
81 gpa.free(code.decls);
79 code.* = undefined;82 code.* = undefined;
80 }83 }
8184
...@@ -103,7 +106,7 @@ pub const Code = struct {...@@ -103,7 +106,7 @@ pub const Code = struct {
103 const stderr = std.io.getStdErr().writer();106 const stderr = std.io.getStdErr().writer();
104 try stderr.print("ZIR {s} {s} %0 ", .{ kind, decl_name });107 try stderr.print("ZIR {s} {s} %0 ", .{ kind, decl_name });
105 try writer.writeInstToStream(stderr, 0);108 try writer.writeInstToStream(stderr, 0);
106 try stderr.print("}} // ZIR {s} {s}\n\n", .{ kind, decl_name });109 try stderr.print(" // end ZIR {s} {s}\n\n", .{ kind, decl_name });
107 }110 }
108};111};
109112
...@@ -115,7 +118,7 @@ pub const Inst = struct {...@@ -115,7 +118,7 @@ pub const Inst = struct {
115 data: Data,118 data: Data,
116119
117 /// These names are used directly as the instruction names in the text format.120 /// These names are used directly as the instruction names in the text format.
118 pub const Tag = enum {121 pub const Tag = enum(u8) {
119 /// Arithmetic addition, asserts no integer overflow.122 /// Arithmetic addition, asserts no integer overflow.
120 /// Uses the `pl_node` union field. Payload is `Bin`.123 /// Uses the `pl_node` union field. Payload is `Bin`.
121 add,124 add,
...@@ -274,10 +277,10 @@ pub const Inst = struct {...@@ -274,10 +277,10 @@ pub const Inst = struct {
274 /// Uses the `node` union field.277 /// Uses the `node` union field.
275 dbg_stmt_node,278 dbg_stmt_node,
276 /// Represents a pointer to a global decl.279 /// Represents a pointer to a global decl.
277 /// Uses the `decl` union field.280 /// Uses the `pl_node` union field. `payload_index` is into `decls`.
278 decl_ref,281 decl_ref,
279 /// Equivalent to a decl_ref followed by load.282 /// Equivalent to a decl_ref followed by load.
280 /// Uses the `decl` union field.283 /// Uses the `pl_node` union field. `payload_index` is into `decls`.
281 decl_val,284 decl_val,
282 /// Load the value from a pointer. Assumes `x.*` syntax.285 /// Load the value from a pointer. Assumes `x.*` syntax.
283 /// Uses `un_node` field. AST node is the `x.*` syntax.286 /// Uses `un_node` field. AST node is the `x.*` syntax.
...@@ -612,10 +615,6 @@ pub const Inst = struct {...@@ -612,10 +615,6 @@ pub const Inst = struct {
612 // /// validated by the switch_br instruction.615 // /// validated by the switch_br instruction.
613 // switch_range,616 // switch_range,
614617
615 comptime {
616 assert(@sizeOf(Tag) == 1);
617 }
618
619 /// Returns whether the instruction is one of the control flow "noreturn" types.618 /// Returns whether the instruction is one of the control flow "noreturn" types.
620 /// Function calls do not count.619 /// Function calls do not count.
621 pub fn isNoReturn(tag: Tag) bool {620 pub fn isNoReturn(tag: Tag) bool {
...@@ -1099,7 +1098,6 @@ pub const Inst = struct {...@@ -1099,7 +1098,6 @@ pub const Inst = struct {
1099 }1098 }
1100 },1099 },
1101 bin: Bin,1100 bin: Bin,
1102 decl: *Module.Decl,
1103 @"const": *TypedValue,1101 @"const": *TypedValue,
1104 /// For strings which may contain null bytes.1102 /// For strings which may contain null bytes.
1105 str: struct {1103 str: struct {
...@@ -1503,6 +1501,10 @@ const Writer = struct {...@@ -1503,6 +1501,10 @@ const Writer = struct {
1503 .typeof_peer,1501 .typeof_peer,
1504 => try self.writePlNodeMultiOp(stream, inst),1502 => try self.writePlNodeMultiOp(stream, inst),
15051503
1504 .decl_ref,
1505 .decl_val,
1506 => try self.writePlNodeDecl(stream, inst),
1507
1506 .as_node => try self.writeAs(stream, inst),1508 .as_node => try self.writeAs(stream, inst),
15071509
1508 .breakpoint,1510 .breakpoint,
...@@ -1513,10 +1515,6 @@ const Writer = struct {...@@ -1513,10 +1515,6 @@ const Writer = struct {
1513 .repeat_inline,1515 .repeat_inline,
1514 => try self.writeNode(stream, inst),1516 => try self.writeNode(stream, inst),
15151517
1516 .decl_ref,
1517 .decl_val,
1518 => try self.writeDecl(stream, inst),
1519
1520 .error_value,1518 .error_value,
1521 .enum_literal,1519 .enum_literal,
1522 => try self.writeStrTok(stream, inst),1520 => try self.writeStrTok(stream, inst),
...@@ -1715,6 +1713,13 @@ const Writer = struct {...@@ -1715,6 +1713,13 @@ const Writer = struct {
1715 try self.writeSrc(stream, inst_data.src());1713 try self.writeSrc(stream, inst_data.src());
1716 }1714 }
17171715
1716 fn writePlNodeDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1717 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1718 const decl = self.code.decls[inst_data.payload_index];
1719 try stream.print("{s}) ", .{decl.name});
1720 try self.writeSrc(stream, inst_data.src());
1721 }
1722
1718 fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {1723 fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1719 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1724 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1720 const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;1725 const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;
...@@ -1736,15 +1741,6 @@ const Writer = struct {...@@ -1736,15 +1741,6 @@ const Writer = struct {
1736 try self.writeSrc(stream, src);1741 try self.writeSrc(stream, src);
1737 }1742 }
17381743
1739 fn writeDecl(
1740 self: *Writer,
1741 stream: anytype,
1742 inst: Inst.Index,
1743 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1744 const decl = self.code.instructions.items(.data)[inst].decl;
1745 try stream.print("{s})", .{decl.name});
1746 }
1747
1748 fn writeStrTok(1744 fn writeStrTok(
1749 self: *Writer,1745 self: *Writer,
1750 stream: anytype,1746 stream: anytype,
test/stage2/test.zig+15-15
...@@ -1112,21 +1112,21 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1112,21 +1112,21 @@ pub fn addCases(ctx: *TestContext) !void {
1112 });1112 });
1113 }1113 }
11141114
1115 //{1115 {
1116 // var case = ctx.obj("extern variable has no type", linux_x64);1116 var case = ctx.obj("extern variable has no type", linux_x64);
1117 // case.addError(1117 case.addError(
1118 // \\comptime {1118 \\comptime {
1119 // \\ _ = foo;1119 \\ _ = foo;
1120 // \\}1120 \\}
1121 // \\extern var foo: i32;1121 \\extern var foo: i32;
1122 // , &[_][]const u8{":2:9: error: unable to resolve comptime value"});1122 , &[_][]const u8{":2:9: error: unable to resolve comptime value"});
1123 // case.addError(1123 case.addError(
1124 // \\export fn entry() void {1124 \\export fn entry() void {
1125 // \\ _ = foo;1125 \\ _ = foo;
1126 // \\}1126 \\}
1127 // \\extern var foo;1127 \\extern var foo;
1128 // , &[_][]const u8{":4:8: error: unable to infer variable type"});1128 , &[_][]const u8{":4:8: error: unable to infer variable type"});
1129 //}1129 }
11301130
1131 //{1131 //{
1132 // var case = ctx.exe("break/continue", linux_x64);1132 // var case = ctx.exe("break/continue", linux_x64);