From c95a34b68f6075d7a9d305d17a6b03bc9fd1fff2 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 18 Oct 2022 13:45:06 +0300 Subject: [PATCH] stage2: improve source location of assignment --- src/AstGen.zig | 50 ++++++++++++------- src/Module.zig | 34 +++++++++++++ src/Sema.zig | 4 +- .../any_typed_null_to_any_typed_optional.zig | 4 +- .../assign_through_constant_pointer.zig | 2 +- .../assign_through_constant_slice.zig | 2 +- .../assign_to_constant_field.zig | 2 +- .../assign_to_constant_variable.zig | 2 +- .../call_assigned_to_constant.zig | 4 +- ...store_in_comptime_switch_in_runtime_if.zig | 2 +- ...lobal_var_struct_init_in_comptim_block.zig | 14 ++++++ ...h_struct_return_value_outside_function.zig | 4 +- .../reassign_to_slice_parameter.zig | 2 +- .../reference_to_const_data.zig | 8 +-- .../write_to_const_global_variable.zig | 2 +- test/cases/x86_64-linux/comptime_var.0.zig | 2 +- test/cases/x86_64-linux/comptime_var.1.zig | 2 +- test/cases/x86_64-macos/comptime_var.0.zig | 2 +- test/cases/x86_64-macos/comptime_var.1.zig | 2 +- 19 files changed, 104 insertions(+), 40 deletions(-) create mode 100644 test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig diff --git a/src/AstGen.zig b/src/AstGen.zig index 7bb2ef765c..4f6e9c5e6b 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -232,7 +232,7 @@ pub const ResultLoc = union(enum) { coerced_ty: Zir.Inst.Ref, /// The expression must store its result into this typed pointer. The result instruction /// from the expression must be ignored. - ptr: Zir.Inst.Ref, + ptr: PtrResultLoc, /// The expression must store its result into this allocation, which has an inferred type. /// The result instruction from the expression must be ignored. /// Always an instruction with tag `alloc_inferred`. @@ -242,6 +242,11 @@ pub const ResultLoc = union(enum) { /// The result instruction from the expression must be ignored. block_ptr: *GenZir, + const PtrResultLoc = struct { + inst: Zir.Inst.Ref, + src_node: ?Ast.Node.Index = null, + }; + pub const Strategy = struct { elide_store_to_block_ptr_instructions: bool, tag: Tag, @@ -1380,8 +1385,8 @@ fn arrayInitExpr( const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); return rvalue(gz, rl, result, node); }, - .ptr => |ptr_inst| { - return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array); + .ptr => |ptr_res| { + return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array); }, .inferred_ptr => |ptr_inst| { if (types.array == .none) { @@ -1513,7 +1518,7 @@ fn arrayInitExprRlPtrInner( }); astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; extra_index += 1; - _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init); + _ = try expr(gz, scope, .{ .ptr = .{ .inst = elem_ptr } }, elem_init); } const tag: Zir.Inst.Tag = if (gz.force_comptime) @@ -1631,7 +1636,7 @@ fn structInitExpr( const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init); return rvalue(gz, rl, result, node); }, - .ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst), + .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_res.inst), .inferred_ptr => |ptr_inst| { if (struct_init.ast.type_expr == 0) { // We treat this case differently so that we don't get a crash when @@ -1739,7 +1744,7 @@ fn structInitExprRlPtrInner( }); astgen.extra.items[extra_index] = refToIndex(field_ptr).?; extra_index += 1; - _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); + _ = try expr(gz, scope, .{ .ptr = .{ .inst = field_ptr } }, field_init); } const tag: Zir.Inst.Tag = if (gz.force_comptime) @@ -2998,7 +3003,7 @@ fn varDecl( } }; gz.rl_ty_inst = type_inst; - break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; + break :a .{ .alloc = alloc, .result_loc = .{ .ptr = .{ .inst = alloc } } }; } else a: { const alloc = alloc: { if (align_inst == .none) { @@ -3098,7 +3103,10 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi } } const lvalue = try lvalExpr(gz, scope, lhs); - _ = try expr(gz, scope, .{ .ptr = lvalue }, rhs); + _ = try expr(gz, scope, .{ .ptr = .{ + .inst = lvalue, + .src_node = infix_node, + } }, rhs); } fn assignOp( @@ -6729,7 +6737,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref } const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{ - .ptr = try gz.addNode(.ret_ptr, node), + .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) }, } else .{ .ty = try gz.addNode(.ret_type, node), }; @@ -6748,7 +6756,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref }, .always => { // Value is always an error. Emit both error defers and regular defers. - const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand; + const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; try genDefers(gz, defer_outer, scope, .{ .both = err_code }); try emitDbgStmt(gz, ret_line, ret_column); try gz.addRet(rl, operand, node); @@ -6765,7 +6773,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref } // Emit conditional branch for generating errdefers. - const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand; + const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; const is_non_err = try gz.addUnNode(.is_non_err, result, node); const condbr = try gz.addCondBr(.condbr, node); @@ -7337,7 +7345,10 @@ fn as( const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node); return rvalue(gz, rl, result, node); }, - .ptr, .inferred_ptr => |result_ptr| { + .ptr => |result_ptr| { + return asRlPtr(gz, scope, rl, node, result_ptr.inst, rhs, dest_type); + }, + .inferred_ptr => |result_ptr| { return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type); }, .block_ptr => |block_scope| { @@ -9570,9 +9581,9 @@ fn rvalue( }), } }, - .ptr => |ptr_inst| { - _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{ - .lhs = ptr_inst, + .ptr => |ptr_res| { + _ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{ + .lhs = ptr_res.inst, .rhs = result, }); return result; @@ -10445,11 +10456,16 @@ const GenZir = struct { gz.break_result_loc = parent_rl; }, - .discard, .none, .ptr, .ref => { + .discard, .none, .ref => { gz.rl_ty_inst = .none; gz.break_result_loc = parent_rl; }, + .ptr => |ptr_res| { + gz.rl_ty_inst = .none; + gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } }; + }, + .inferred_ptr => |ptr| { gz.rl_ty_inst = .none; gz.rl_ptr = ptr; @@ -11610,7 +11626,7 @@ const GenZir = struct { fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { switch (rl) { - .ptr => |ret_ptr| _ = try gz.addUnNode(.ret_load, ret_ptr, node), + .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node), .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node), else => unreachable, } diff --git a/src/Module.zig b/src/Module.zig index 396e92ed79..cdcf551847 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2878,6 +2878,32 @@ pub const SrcLoc = struct { }; return nodeToSpan(tree, full.ast.type_expr); }, + .node_offset_store_ptr => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); + const node = src_loc.declRelativeToNodeIndex(node_off); + + switch (node_tags[node]) { + .assign => { + return nodeToSpan(tree, node_datas[node].lhs); + }, + else => return nodeToSpan(tree, node), + } + }, + .node_offset_store_operand => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); + const node = src_loc.declRelativeToNodeIndex(node_off); + + switch (node_tags[node]) { + .assign => { + return nodeToSpan(tree, node_datas[node].rhs); + }, + else => return nodeToSpan(tree, node), + } + }, } } @@ -3213,6 +3239,12 @@ pub const LazySrcLoc = union(enum) { /// The source location points to the type of an array or struct initializer. /// The Decl is determined contextually. node_offset_init_ty: i32, + /// The source location points to the LHS of an assignment. + /// The Decl is determined contextually. + node_offset_store_ptr: i32, + /// The source location points to the RHS of an assignment. + /// The Decl is determined contextually. + node_offset_store_operand: i32, pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; @@ -3296,6 +3328,8 @@ pub const LazySrcLoc = union(enum) { .node_offset_container_tag, .node_offset_field_default, .node_offset_init_ty, + .node_offset_store_ptr, + .node_offset_store_operand, => .{ .file_scope = decl.getFileScope(), .parent_decl_node = decl.src_node, diff --git a/src/Sema.zig b/src/Sema.zig index 8937bc05e7..8945bc6bed 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4639,8 +4639,8 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v try sema.addToInferredErrorSet(operand); } - const ptr_src = src; // TODO better soruce location - const operand_src = src; // TODO better soruce location + const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node }; + const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node }; const air_tag: Air.Inst.Tag = if (is_ret) .ret_ptr else .store; return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag); } diff --git a/test/cases/compile_errors/any_typed_null_to_any_typed_optional.zig b/test/cases/compile_errors/any_typed_null_to_any_typed_optional.zig index 6b3ffaca2f..306fb7efc0 100644 --- a/test/cases/compile_errors/any_typed_null_to_any_typed_optional.zig +++ b/test/cases/compile_errors/any_typed_null_to_any_typed_optional.zig @@ -7,5 +7,5 @@ pub export fn entry() void { // backend=stage2 // target=native // -// :3:21: error: expected type '?*anyopaque', found '?usize' -// :3:21: note: optional type child 'usize' cannot cast into optional type child '*anyopaque' +// :3:9: error: expected type '?*anyopaque', found '?usize' +// :3:9: note: optional type child 'usize' cannot cast into optional type child '*anyopaque' diff --git a/test/cases/compile_errors/assign_through_constant_pointer.zig b/test/cases/compile_errors/assign_through_constant_pointer.zig index 21924ae4da..674d0875aa 100644 --- a/test/cases/compile_errors/assign_through_constant_pointer.zig +++ b/test/cases/compile_errors/assign_through_constant_pointer.zig @@ -7,4 +7,4 @@ export fn f() void { // backend=stage2 // target=native // -// :3:13: error: cannot assign to constant +// :3:7: error: cannot assign to constant diff --git a/test/cases/compile_errors/assign_through_constant_slice.zig b/test/cases/compile_errors/assign_through_constant_slice.zig index a7631be61c..08910b6248 100644 --- a/test/cases/compile_errors/assign_through_constant_slice.zig +++ b/test/cases/compile_errors/assign_through_constant_slice.zig @@ -7,4 +7,4 @@ export fn f() void { // backend=stage2 // target=native // -// :3:13: error: cannot assign to constant +// :3:7: error: cannot assign to constant diff --git a/test/cases/compile_errors/assign_to_constant_field.zig b/test/cases/compile_errors/assign_to_constant_field.zig index 4c79b29592..33f08344c4 100644 --- a/test/cases/compile_errors/assign_to_constant_field.zig +++ b/test/cases/compile_errors/assign_to_constant_field.zig @@ -10,4 +10,4 @@ export fn derp() void { // backend=stage2 // target=native // -// :6:15: error: cannot assign to constant +// :6:6: error: cannot assign to constant diff --git a/test/cases/compile_errors/assign_to_constant_variable.zig b/test/cases/compile_errors/assign_to_constant_variable.zig index b09bf26259..dca2caf9de 100644 --- a/test/cases/compile_errors/assign_to_constant_variable.zig +++ b/test/cases/compile_errors/assign_to_constant_variable.zig @@ -75,7 +75,7 @@ export fn entry18() void { // backend=stage2 // target=native // -// :3:9: error: cannot assign to constant +// :3:5: error: cannot assign to constant // :7:7: error: cannot assign to constant // :11:7: error: cannot assign to constant // :15:7: error: cannot assign to constant diff --git a/test/cases/compile_errors/call_assigned_to_constant.zig b/test/cases/compile_errors/call_assigned_to_constant.zig index 7533acbf05..24150e862b 100644 --- a/test/cases/compile_errors/call_assigned_to_constant.zig +++ b/test/cases/compile_errors/call_assigned_to_constant.zig @@ -20,5 +20,5 @@ export fn entry1() void { // backend=stage2 // target=native // -// :12:14: error: cannot assign to constant -// :16:14: error: cannot assign to constant +// :12:5: error: cannot assign to constant +// :16:5: error: cannot assign to constant diff --git a/test/cases/compile_errors/comptime_store_in_comptime_switch_in_runtime_if.zig b/test/cases/compile_errors/comptime_store_in_comptime_switch_in_runtime_if.zig index f04b5cc4ec..abaff066ad 100644 --- a/test/cases/compile_errors/comptime_store_in_comptime_switch_in_runtime_if.zig +++ b/test/cases/compile_errors/comptime_store_in_comptime_switch_in_runtime_if.zig @@ -21,5 +21,5 @@ pub export fn entry() void { // backend=stage2 // target=native // -// :13:27: error: store to comptime variable depends on runtime condition +// :13:25: error: store to comptime variable depends on runtime condition // :11:16: note: runtime condition here diff --git a/test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig b/test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig new file mode 100644 index 0000000000..2ffb3747fe --- /dev/null +++ b/test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig @@ -0,0 +1,14 @@ +const Foo = struct { + x: i32, +}; +var x: Foo = .{ .x = 2 }; +comptime { + x = .{ .x = 3 }; +} + +// error +// backend=stage2 +// target=native +// +// :6:17: error: unable to evaluate comptime expression +// :6:17: note: operation is runtime due to this operand diff --git a/test/cases/compile_errors/non-const_expression_function_call_with_struct_return_value_outside_function.zig b/test/cases/compile_errors/non-const_expression_function_call_with_struct_return_value_outside_function.zig index abbbccee74..4acd0afb81 100644 --- a/test/cases/compile_errors/non-const_expression_function_call_with_struct_return_value_outside_function.zig +++ b/test/cases/compile_errors/non-const_expression_function_call_with_struct_return_value_outside_function.zig @@ -14,6 +14,6 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); } // backend=stage2 // target=native // -// :6:26: error: unable to evaluate comptime expression -// :6:26: note: operation is runtime due to this operand +// :6:24: error: unable to evaluate comptime expression +// :6:5: note: operation is runtime due to this operand // :4:17: note: called from here diff --git a/test/cases/compile_errors/reassign_to_slice_parameter.zig b/test/cases/compile_errors/reassign_to_slice_parameter.zig index 586eb230df..4f3fbe2a24 100644 --- a/test/cases/compile_errors/reassign_to_slice_parameter.zig +++ b/test/cases/compile_errors/reassign_to_slice_parameter.zig @@ -9,4 +9,4 @@ export fn entry() void { // backend=llvm // target=native // -// :2:10: error: cannot assign to constant +// :2:5: error: cannot assign to constant diff --git a/test/cases/compile_errors/reference_to_const_data.zig b/test/cases/compile_errors/reference_to_const_data.zig index 6bd9d0eb1e..b7f2e93fbd 100644 --- a/test/cases/compile_errors/reference_to_const_data.zig +++ b/test/cases/compile_errors/reference_to_const_data.zig @@ -23,7 +23,7 @@ export fn qux() void { // backend=stage2 // target=native // -// :3:14: error: cannot assign to constant -// :7:13: error: cannot assign to constant -// :11:13: error: cannot assign to constant -// :19:13: error: cannot assign to constant +// :3:8: error: cannot assign to constant +// :7:8: error: cannot assign to constant +// :11:8: error: cannot assign to constant +// :19:8: error: cannot assign to constant diff --git a/test/cases/compile_errors/write_to_const_global_variable.zig b/test/cases/compile_errors/write_to_const_global_variable.zig index eaa9353f00..5ffd3a305d 100644 --- a/test/cases/compile_errors/write_to_const_global_variable.zig +++ b/test/cases/compile_errors/write_to_const_global_variable.zig @@ -8,4 +8,4 @@ export fn entry() void { f(); } // backend=stage2 // target=native // -// :3:9: error: cannot assign to constant +// :3:5: error: cannot assign to constant diff --git a/test/cases/x86_64-linux/comptime_var.0.zig b/test/cases/x86_64-linux/comptime_var.0.zig index 45f87ecaa1..70504eb364 100644 --- a/test/cases/x86_64-linux/comptime_var.0.zig +++ b/test/cases/x86_64-linux/comptime_var.0.zig @@ -8,5 +8,5 @@ pub fn main() void { // output_mode=Exe // target=x86_64-linux // -// :4:21: error: store to comptime variable depends on runtime condition +// :4:19: error: store to comptime variable depends on runtime condition // :4:11: note: runtime condition here diff --git a/test/cases/x86_64-linux/comptime_var.1.zig b/test/cases/x86_64-linux/comptime_var.1.zig index efc51aafe3..054d69250c 100644 --- a/test/cases/x86_64-linux/comptime_var.1.zig +++ b/test/cases/x86_64-linux/comptime_var.1.zig @@ -9,5 +9,5 @@ pub fn main() void { // error // -// :6:21: error: store to comptime variable depends on runtime condition +// :6:19: error: store to comptime variable depends on runtime condition // :4:13: note: runtime condition here diff --git a/test/cases/x86_64-macos/comptime_var.0.zig b/test/cases/x86_64-macos/comptime_var.0.zig index da82b35c6f..b7bf9ebb14 100644 --- a/test/cases/x86_64-macos/comptime_var.0.zig +++ b/test/cases/x86_64-macos/comptime_var.0.zig @@ -8,5 +8,5 @@ pub fn main() void { // output_mode=Exe // target=x86_64-macos // -// :4:21: error: store to comptime variable depends on runtime condition +// :4:19: error: store to comptime variable depends on runtime condition // :4:11: note: runtime condition here diff --git a/test/cases/x86_64-macos/comptime_var.1.zig b/test/cases/x86_64-macos/comptime_var.1.zig index efc51aafe3..054d69250c 100644 --- a/test/cases/x86_64-macos/comptime_var.1.zig +++ b/test/cases/x86_64-macos/comptime_var.1.zig @@ -9,5 +9,5 @@ pub fn main() void { // error // -// :6:21: error: store to comptime variable depends on runtime condition +// :6:19: error: store to comptime variable depends on runtime condition // :4:13: note: runtime condition here