| author | |
| committer | |
| log | c95a34b68f6075d7a9d305d17a6b03bc9fd1fff2 |
| tree | 6e060e102426883b8b0894a0feea0dbdd0b19684 |
| parent | 34e4b07d0c3cafd0aad15b217e8c56ab9af5de40 |
19 files changed, 104 insertions(+), 40 deletions(-)
src/AstGen.zig+33-17| ... | ... | @@ -232,7 +232,7 @@ pub const ResultLoc = union(enum) { |
| 232 | 232 | coerced_ty: Zir.Inst.Ref, |
| 233 | 233 | /// The expression must store its result into this typed pointer. The result instruction |
| 234 | 234 | /// from the expression must be ignored. |
| 235 | ptr: Zir.Inst.Ref, | |
| 235 | ptr: PtrResultLoc, | |
| 236 | 236 | /// The expression must store its result into this allocation, which has an inferred type. |
| 237 | 237 | /// The result instruction from the expression must be ignored. |
| 238 | 238 | /// Always an instruction with tag `alloc_inferred`. |
| ... | ... | @@ -242,6 +242,11 @@ pub const ResultLoc = union(enum) { |
| 242 | 242 | /// The result instruction from the expression must be ignored. |
| 243 | 243 | block_ptr: *GenZir, |
| 244 | 244 | |
| 245 | const PtrResultLoc = struct { | |
| 246 | inst: Zir.Inst.Ref, | |
| 247 | src_node: ?Ast.Node.Index = null, | |
| 248 | }; | |
| 249 | ||
| 245 | 250 | pub const Strategy = struct { |
| 246 | 251 | elide_store_to_block_ptr_instructions: bool, |
| 247 | 252 | tag: Tag, |
| ... | ... | @@ -1380,8 +1385,8 @@ fn arrayInitExpr( |
| 1380 | 1385 | const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); |
| 1381 | 1386 | return rvalue(gz, rl, result, node); |
| 1382 | 1387 | }, |
| 1383 | .ptr => |ptr_inst| { | |
| 1384 | return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array); | |
| 1388 | .ptr => |ptr_res| { | |
| 1389 | return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array); | |
| 1385 | 1390 | }, |
| 1386 | 1391 | .inferred_ptr => |ptr_inst| { |
| 1387 | 1392 | if (types.array == .none) { |
| ... | ... | @@ -1513,7 +1518,7 @@ fn arrayInitExprRlPtrInner( |
| 1513 | 1518 | }); |
| 1514 | 1519 | astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; |
| 1515 | 1520 | extra_index += 1; |
| 1516 | _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init); | |
| 1521 | _ = try expr(gz, scope, .{ .ptr = .{ .inst = elem_ptr } }, elem_init); | |
| 1517 | 1522 | } |
| 1518 | 1523 | |
| 1519 | 1524 | const tag: Zir.Inst.Tag = if (gz.force_comptime) |
| ... | ... | @@ -1631,7 +1636,7 @@ fn structInitExpr( |
| 1631 | 1636 | const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init); |
| 1632 | 1637 | return rvalue(gz, rl, result, node); |
| 1633 | 1638 | }, |
| 1634 | .ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst), | |
| 1639 | .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_res.inst), | |
| 1635 | 1640 | .inferred_ptr => |ptr_inst| { |
| 1636 | 1641 | if (struct_init.ast.type_expr == 0) { |
| 1637 | 1642 | // We treat this case differently so that we don't get a crash when |
| ... | ... | @@ -1739,7 +1744,7 @@ fn structInitExprRlPtrInner( |
| 1739 | 1744 | }); |
| 1740 | 1745 | astgen.extra.items[extra_index] = refToIndex(field_ptr).?; |
| 1741 | 1746 | extra_index += 1; |
| 1742 | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); | |
| 1747 | _ = try expr(gz, scope, .{ .ptr = .{ .inst = field_ptr } }, field_init); | |
| 1743 | 1748 | } |
| 1744 | 1749 | |
| 1745 | 1750 | const tag: Zir.Inst.Tag = if (gz.force_comptime) |
| ... | ... | @@ -2998,7 +3003,7 @@ fn varDecl( |
| 2998 | 3003 | } |
| 2999 | 3004 | }; |
| 3000 | 3005 | gz.rl_ty_inst = type_inst; |
| 3001 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; | |
| 3006 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = .{ .inst = alloc } } }; | |
| 3002 | 3007 | } else a: { |
| 3003 | 3008 | const alloc = alloc: { |
| 3004 | 3009 | if (align_inst == .none) { |
| ... | ... | @@ -3098,7 +3103,10 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi |
| 3098 | 3103 | } |
| 3099 | 3104 | } |
| 3100 | 3105 | const lvalue = try lvalExpr(gz, scope, lhs); |
| 3101 | _ = try expr(gz, scope, .{ .ptr = lvalue }, rhs); | |
| 3106 | _ = try expr(gz, scope, .{ .ptr = .{ | |
| 3107 | .inst = lvalue, | |
| 3108 | .src_node = infix_node, | |
| 3109 | } }, rhs); | |
| 3102 | 3110 | } |
| 3103 | 3111 | |
| 3104 | 3112 | fn assignOp( |
| ... | ... | @@ -6729,7 +6737,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6729 | 6737 | } |
| 6730 | 6738 | |
| 6731 | 6739 | const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{ |
| 6732 | .ptr = try gz.addNode(.ret_ptr, node), | |
| 6740 | .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) }, | |
| 6733 | 6741 | } else .{ |
| 6734 | 6742 | .ty = try gz.addNode(.ret_type, node), |
| 6735 | 6743 | }; |
| ... | ... | @@ -6748,7 +6756,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6748 | 6756 | }, |
| 6749 | 6757 | .always => { |
| 6750 | 6758 | // Value is always an error. Emit both error defers and regular defers. |
| 6751 | const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand; | |
| 6759 | const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; | |
| 6752 | 6760 | try genDefers(gz, defer_outer, scope, .{ .both = err_code }); |
| 6753 | 6761 | try emitDbgStmt(gz, ret_line, ret_column); |
| 6754 | 6762 | try gz.addRet(rl, operand, node); |
| ... | ... | @@ -6765,7 +6773,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6765 | 6773 | } |
| 6766 | 6774 | |
| 6767 | 6775 | // Emit conditional branch for generating errdefers. |
| 6768 | const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand; | |
| 6776 | const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; | |
| 6769 | 6777 | const is_non_err = try gz.addUnNode(.is_non_err, result, node); |
| 6770 | 6778 | const condbr = try gz.addCondBr(.condbr, node); |
| 6771 | 6779 | |
| ... | ... | @@ -7337,7 +7345,10 @@ fn as( |
| 7337 | 7345 | const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node); |
| 7338 | 7346 | return rvalue(gz, rl, result, node); |
| 7339 | 7347 | }, |
| 7340 | .ptr, .inferred_ptr => |result_ptr| { | |
| 7348 | .ptr => |result_ptr| { | |
| 7349 | return asRlPtr(gz, scope, rl, node, result_ptr.inst, rhs, dest_type); | |
| 7350 | }, | |
| 7351 | .inferred_ptr => |result_ptr| { | |
| 7341 | 7352 | return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type); |
| 7342 | 7353 | }, |
| 7343 | 7354 | .block_ptr => |block_scope| { |
| ... | ... | @@ -9570,9 +9581,9 @@ fn rvalue( |
| 9570 | 9581 | }), |
| 9571 | 9582 | } |
| 9572 | 9583 | }, |
| 9573 | .ptr => |ptr_inst| { | |
| 9574 | _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{ | |
| 9575 | .lhs = ptr_inst, | |
| 9584 | .ptr => |ptr_res| { | |
| 9585 | _ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{ | |
| 9586 | .lhs = ptr_res.inst, | |
| 9576 | 9587 | .rhs = result, |
| 9577 | 9588 | }); |
| 9578 | 9589 | return result; |
| ... | ... | @@ -10445,11 +10456,16 @@ const GenZir = struct { |
| 10445 | 10456 | gz.break_result_loc = parent_rl; |
| 10446 | 10457 | }, |
| 10447 | 10458 | |
| 10448 | .discard, .none, .ptr, .ref => { | |
| 10459 | .discard, .none, .ref => { | |
| 10449 | 10460 | gz.rl_ty_inst = .none; |
| 10450 | 10461 | gz.break_result_loc = parent_rl; |
| 10451 | 10462 | }, |
| 10452 | 10463 | |
| 10464 | .ptr => |ptr_res| { | |
| 10465 | gz.rl_ty_inst = .none; | |
| 10466 | gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } }; | |
| 10467 | }, | |
| 10468 | ||
| 10453 | 10469 | .inferred_ptr => |ptr| { |
| 10454 | 10470 | gz.rl_ty_inst = .none; |
| 10455 | 10471 | gz.rl_ptr = ptr; |
| ... | ... | @@ -11610,7 +11626,7 @@ const GenZir = struct { |
| 11610 | 11626 | |
| 11611 | 11627 | fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { |
| 11612 | 11628 | switch (rl) { |
| 11613 | .ptr => |ret_ptr| _ = try gz.addUnNode(.ret_load, ret_ptr, node), | |
| 11629 | .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node), | |
| 11614 | 11630 | .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node), |
| 11615 | 11631 | else => unreachable, |
| 11616 | 11632 | } |
src/Module.zig+34| ... | ... | @@ -2878,6 +2878,32 @@ pub const SrcLoc = struct { |
| 2878 | 2878 | }; |
| 2879 | 2879 | return nodeToSpan(tree, full.ast.type_expr); |
| 2880 | 2880 | }, |
| 2881 | .node_offset_store_ptr => |node_off| { | |
| 2882 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 2883 | const node_tags = tree.nodes.items(.tag); | |
| 2884 | const node_datas = tree.nodes.items(.data); | |
| 2885 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2886 | ||
| 2887 | switch (node_tags[node]) { | |
| 2888 | .assign => { | |
| 2889 | return nodeToSpan(tree, node_datas[node].lhs); | |
| 2890 | }, | |
| 2891 | else => return nodeToSpan(tree, node), | |
| 2892 | } | |
| 2893 | }, | |
| 2894 | .node_offset_store_operand => |node_off| { | |
| 2895 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 2896 | const node_tags = tree.nodes.items(.tag); | |
| 2897 | const node_datas = tree.nodes.items(.data); | |
| 2898 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2899 | ||
| 2900 | switch (node_tags[node]) { | |
| 2901 | .assign => { | |
| 2902 | return nodeToSpan(tree, node_datas[node].rhs); | |
| 2903 | }, | |
| 2904 | else => return nodeToSpan(tree, node), | |
| 2905 | } | |
| 2906 | }, | |
| 2881 | 2907 | } |
| 2882 | 2908 | } |
| 2883 | 2909 | |
| ... | ... | @@ -3213,6 +3239,12 @@ pub const LazySrcLoc = union(enum) { |
| 3213 | 3239 | /// The source location points to the type of an array or struct initializer. |
| 3214 | 3240 | /// The Decl is determined contextually. |
| 3215 | 3241 | node_offset_init_ty: i32, |
| 3242 | /// The source location points to the LHS of an assignment. | |
| 3243 | /// The Decl is determined contextually. | |
| 3244 | node_offset_store_ptr: i32, | |
| 3245 | /// The source location points to the RHS of an assignment. | |
| 3246 | /// The Decl is determined contextually. | |
| 3247 | node_offset_store_operand: i32, | |
| 3216 | 3248 | |
| 3217 | 3249 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
| 3218 | 3250 | |
| ... | ... | @@ -3296,6 +3328,8 @@ pub const LazySrcLoc = union(enum) { |
| 3296 | 3328 | .node_offset_container_tag, |
| 3297 | 3329 | .node_offset_field_default, |
| 3298 | 3330 | .node_offset_init_ty, |
| 3331 | .node_offset_store_ptr, | |
| 3332 | .node_offset_store_operand, | |
| 3299 | 3333 | => .{ |
| 3300 | 3334 | .file_scope = decl.getFileScope(), |
| 3301 | 3335 | .parent_decl_node = decl.src_node, |
src/Sema.zig+2-2| ... | ... | @@ -4639,8 +4639,8 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 4639 | 4639 | try sema.addToInferredErrorSet(operand); |
| 4640 | 4640 | } |
| 4641 | 4641 | |
| 4642 | const ptr_src = src; // TODO better soruce location | |
| 4643 | const operand_src = src; // TODO better soruce location | |
| 4642 | const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node }; | |
| 4643 | const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node }; | |
| 4644 | 4644 | const air_tag: Air.Inst.Tag = if (is_ret) .ret_ptr else .store; |
| 4645 | 4645 | return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag); |
| 4646 | 4646 | } |
test/cases/compile_errors/any_typed_null_to_any_typed_optional.zig+2-2| ... | ... | @@ -7,5 +7,5 @@ pub export fn entry() void { |
| 7 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :3:21: error: expected type '?*anyopaque', found '?usize' | |
| 11 | // :3:21: note: optional type child 'usize' cannot cast into optional type child '*anyopaque' | |
| 10 | // :3:9: error: expected type '?*anyopaque', found '?usize' | |
| 11 | // :3:9: note: optional type child 'usize' cannot cast into optional type child '*anyopaque' |
test/cases/compile_errors/assign_through_constant_pointer.zig+1-1| ... | ... | @@ -7,4 +7,4 @@ export fn f() void { |
| 7 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :3:13: error: cannot assign to constant | |
| 10 | // :3:7: error: cannot assign to constant |
test/cases/compile_errors/assign_through_constant_slice.zig+1-1| ... | ... | @@ -7,4 +7,4 @@ export fn f() void { |
| 7 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :3:13: error: cannot assign to constant | |
| 10 | // :3:7: error: cannot assign to constant |
test/cases/compile_errors/assign_to_constant_field.zig+1-1| ... | ... | @@ -10,4 +10,4 @@ export fn derp() void { |
| 10 | 10 | // backend=stage2 |
| 11 | 11 | // target=native |
| 12 | 12 | // |
| 13 | // :6:15: error: cannot assign to constant | |
| 13 | // :6:6: error: cannot assign to constant |
test/cases/compile_errors/assign_to_constant_variable.zig+1-1| ... | ... | @@ -75,7 +75,7 @@ export fn entry18() void { |
| 75 | 75 | // backend=stage2 |
| 76 | 76 | // target=native |
| 77 | 77 | // |
| 78 | // :3:9: error: cannot assign to constant | |
| 78 | // :3:5: error: cannot assign to constant | |
| 79 | 79 | // :7:7: error: cannot assign to constant |
| 80 | 80 | // :11:7: error: cannot assign to constant |
| 81 | 81 | // :15:7: error: cannot assign to constant |
test/cases/compile_errors/call_assigned_to_constant.zig+2-2| ... | ... | @@ -20,5 +20,5 @@ export fn entry1() void { |
| 20 | 20 | // backend=stage2 |
| 21 | 21 | // target=native |
| 22 | 22 | // |
| 23 | // :12:14: error: cannot assign to constant | |
| 24 | // :16:14: error: cannot assign to constant | |
| 23 | // :12:5: error: cannot assign to constant | |
| 24 | // :16:5: error: cannot assign to constant |
test/cases/compile_errors/comptime_store_in_comptime_switch_in_runtime_if.zig+1-1| ... | ... | @@ -21,5 +21,5 @@ pub export fn entry() void { |
| 21 | 21 | // backend=stage2 |
| 22 | 22 | // target=native |
| 23 | 23 | // |
| 24 | // :13:27: error: store to comptime variable depends on runtime condition | |
| 24 | // :13:25: error: store to comptime variable depends on runtime condition | |
| 25 | 25 | // :11:16: note: runtime condition here |
test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const Foo = struct { | |
| 2 | x: i32, | |
| 3 | }; | |
| 4 | var x: Foo = .{ .x = 2 }; | |
| 5 | comptime { | |
| 6 | x = .{ .x = 3 }; | |
| 7 | } | |
| 8 | ||
| 9 | // error | |
| 10 | // backend=stage2 | |
| 11 | // target=native | |
| 12 | // | |
| 13 | // :6:17: error: unable to evaluate comptime expression | |
| 14 | // :6:17: note: operation is runtime due to this operand |
test/cases/compile_errors/non-const_expression_function_call_with_struct_return_value_outside_function.zig+2-2| ... | ... | @@ -14,6 +14,6 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); } |
| 14 | 14 | // backend=stage2 |
| 15 | 15 | // target=native |
| 16 | 16 | // |
| 17 | // :6:26: error: unable to evaluate comptime expression | |
| 18 | // :6:26: note: operation is runtime due to this operand | |
| 17 | // :6:24: error: unable to evaluate comptime expression | |
| 18 | // :6:5: note: operation is runtime due to this operand | |
| 19 | 19 | // :4:17: note: called from here |
test/cases/compile_errors/reassign_to_slice_parameter.zig+1-1| ... | ... | @@ -9,4 +9,4 @@ export fn entry() void { |
| 9 | 9 | // backend=llvm |
| 10 | 10 | // target=native |
| 11 | 11 | // |
| 12 | // :2:10: error: cannot assign to constant | |
| 12 | // :2:5: error: cannot assign to constant |
test/cases/compile_errors/reference_to_const_data.zig+4-4| ... | ... | @@ -23,7 +23,7 @@ export fn qux() void { |
| 23 | 23 | // backend=stage2 |
| 24 | 24 | // target=native |
| 25 | 25 | // |
| 26 | // :3:14: error: cannot assign to constant | |
| 27 | // :7:13: error: cannot assign to constant | |
| 28 | // :11:13: error: cannot assign to constant | |
| 29 | // :19:13: error: cannot assign to constant | |
| 26 | // :3:8: error: cannot assign to constant | |
| 27 | // :7:8: error: cannot assign to constant | |
| 28 | // :11:8: error: cannot assign to constant | |
| 29 | // :19:8: error: cannot assign to constant |
test/cases/compile_errors/write_to_const_global_variable.zig+1-1| ... | ... | @@ -8,4 +8,4 @@ export fn entry() void { f(); } |
| 8 | 8 | // backend=stage2 |
| 9 | 9 | // target=native |
| 10 | 10 | // |
| 11 | // :3:9: error: cannot assign to constant | |
| 11 | // :3:5: error: cannot assign to constant |
test/cases/x86_64-linux/comptime_var.0.zig+1-1| ... | ... | @@ -8,5 +8,5 @@ pub fn main() void { |
| 8 | 8 | // output_mode=Exe |
| 9 | 9 | // target=x86_64-linux |
| 10 | 10 | // |
| 11 | // :4:21: error: store to comptime variable depends on runtime condition | |
| 11 | // :4:19: error: store to comptime variable depends on runtime condition | |
| 12 | 12 | // :4:11: note: runtime condition here |
test/cases/x86_64-linux/comptime_var.1.zig+1-1| ... | ... | @@ -9,5 +9,5 @@ pub fn main() void { |
| 9 | 9 | |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | // :6:21: error: store to comptime variable depends on runtime condition | |
| 12 | // :6:19: error: store to comptime variable depends on runtime condition | |
| 13 | 13 | // :4:13: note: runtime condition here |
test/cases/x86_64-macos/comptime_var.0.zig+1-1| ... | ... | @@ -8,5 +8,5 @@ pub fn main() void { |
| 8 | 8 | // output_mode=Exe |
| 9 | 9 | // target=x86_64-macos |
| 10 | 10 | // |
| 11 | // :4:21: error: store to comptime variable depends on runtime condition | |
| 11 | // :4:19: error: store to comptime variable depends on runtime condition | |
| 12 | 12 | // :4:11: note: runtime condition here |
test/cases/x86_64-macos/comptime_var.1.zig+1-1| ... | ... | @@ -9,5 +9,5 @@ pub fn main() void { |
| 9 | 9 | |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | // :6:21: error: store to comptime variable depends on runtime condition | |
| 12 | // :6:19: error: store to comptime variable depends on runtime condition | |
| 13 | 13 | // :4:13: note: runtime condition here |