| ... | @@ -5758,7 +5758,65 @@ fn zirIntToFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr | ... | @@ -5758,7 +5758,65 @@ fn zirIntToFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr |
| 5758 | fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | 5758 | fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 5759 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 5759 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 5760 | const src = inst_data.src(); | 5760 | const src = inst_data.src(); |
| 5761 | return sema.mod.fail(&block.base, src, "TODO: Sema.zirIntToPtr", .{}); | 5761 | |
| | 5762 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| | 5763 | |
| | 5764 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| | 5765 | const operand_res = try sema.resolveInst(extra.rhs); |
| | 5766 | const operand_coerced = try sema.coerce(block, Type.initTag(.usize), operand_res, operand_src); |
| | 5767 | |
| | 5768 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| | 5769 | const type_res = try sema.resolveType(block, src, extra.lhs); |
| | 5770 | if (type_res.zigTypeTag() != .Pointer) |
| | 5771 | return sema.mod.fail(&block.base, type_src, "expected pointer, found '{}'", .{type_res}); |
| | 5772 | const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); |
| | 5773 | |
| | 5774 | const uncasted_operand = try sema.resolveInst(extra.rhs); |
| | 5775 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| | 5776 | const addr = val.toUnsignedInt(); |
| | 5777 | if (!type_res.isAllowzeroPtr() and addr == 0) |
| | 5778 | return sema.mod.fail(&block.base, operand_src, "pointer type '{}' does not allow address zero", .{type_res}); |
| | 5779 | if (addr != 0 and addr % ptr_align != 0) |
| | 5780 | return sema.mod.fail(&block.base, operand_src, "pointer type '{}' requires aligned address", .{type_res}); |
| | 5781 | |
| | 5782 | const val_payload = try sema.arena.create(Value.Payload.U64); |
| | 5783 | val_payload.* = .{ |
| | 5784 | .base = .{ .tag = .int_u64 }, |
| | 5785 | .data = addr, |
| | 5786 | }; |
| | 5787 | return sema.mod.constInst(sema.arena, src, .{ |
| | 5788 | .ty = type_res, |
| | 5789 | .val = Value.initPayload(&val_payload.base), |
| | 5790 | }); |
| | 5791 | } |
| | 5792 | |
| | 5793 | try sema.requireRuntimeBlock(block, src); |
| | 5794 | if (block.wantSafety()) { |
| | 5795 | const zero = try sema.mod.constInst(sema.arena, src, .{ |
| | 5796 | .ty = Type.initTag(.u64), |
| | 5797 | .val = Value.initTag(.zero), |
| | 5798 | }); |
| | 5799 | if (!type_res.isAllowzeroPtr()) { |
| | 5800 | const is_non_zero = try block.addBinOp(src, Type.initTag(.bool), .cmp_neq, operand_coerced, zero); |
| | 5801 | try sema.addSafetyCheck(block, is_non_zero, .cast_to_null); |
| | 5802 | } |
| | 5803 | |
| | 5804 | if (ptr_align > 1) { |
| | 5805 | const val_payload = try sema.arena.create(Value.Payload.U64); |
| | 5806 | val_payload.* = .{ |
| | 5807 | .base = .{ .tag = .int_u64 }, |
| | 5808 | .data = ptr_align - 1, |
| | 5809 | }; |
| | 5810 | const align_minus_1 = try sema.mod.constInst(sema.arena, src, .{ |
| | 5811 | .ty = Type.initTag(.u64), |
| | 5812 | .val = Value.initPayload(&val_payload.base), |
| | 5813 | }); |
| | 5814 | const remainder = try block.addBinOp(src, Type.initTag(.u64), .bit_and, operand_coerced, align_minus_1); |
| | 5815 | const is_aligned = try block.addBinOp(src, Type.initTag(.bool), .cmp_eq, remainder, zero); |
| | 5816 | try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment); |
| | 5817 | } |
| | 5818 | } |
| | 5819 | return block.addUnOp(src, type_res, .bitcast, operand_coerced); |
| 5762 | } | 5820 | } |
| 5763 | | 5821 | |
| 5764 | fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | 5822 | fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| ... | @@ -6183,6 +6241,8 @@ pub const PanicId = enum { | ... | @@ -6183,6 +6241,8 @@ pub const PanicId = enum { |
| 6183 | unreach, | 6241 | unreach, |
| 6184 | unwrap_null, | 6242 | unwrap_null, |
| 6185 | unwrap_errunion, | 6243 | unwrap_errunion, |
| | 6244 | cast_to_null, |
| | 6245 | incorrect_alignment, |
| 6186 | invalid_error_code, | 6246 | invalid_error_code, |
| 6187 | }; | 6247 | }; |
| 6188 | | 6248 | |
| ... | @@ -6805,10 +6865,13 @@ fn storePtr( | ... | @@ -6805,10 +6865,13 @@ fn storePtr( |
| 6805 | if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null) | 6865 | if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null) |
| 6806 | return; | 6866 | return; |
| 6807 | | 6867 | |
| 6808 | if (try sema.resolvePossiblyUndefinedValue(block, src, ptr)) |ptr_val| { | 6868 | if (try sema.resolvePossiblyUndefinedValue(block, src, ptr)) |ptr_val| blk: { |
| 6809 | const const_val = (try sema.resolvePossiblyUndefinedValue(block, src, value)) orelse | 6869 | const const_val = (try sema.resolvePossiblyUndefinedValue(block, src, value)) orelse |
| 6810 | return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{}); | 6870 | return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{}); |
| 6811 | | 6871 | |
| | 6872 | if (ptr_val.tag() == .int_u64) |
| | 6873 | break :blk; // propogate it down to runtime |
| | 6874 | |
| 6812 | const comptime_alloc = ptr_val.castTag(.comptime_alloc).?; | 6875 | const comptime_alloc = ptr_val.castTag(.comptime_alloc).?; |
| 6813 | if (comptime_alloc.data.runtime_index < block.runtime_index) { | 6876 | if (comptime_alloc.data.runtime_index < block.runtime_index) { |
| 6814 | if (block.runtime_cond) |cond_src| { | 6877 | if (block.runtime_cond) |cond_src| { |
| ... | @@ -6947,7 +7010,10 @@ fn analyzeLoad( | ... | @@ -6947,7 +7010,10 @@ fn analyzeLoad( |
| 6947 | .Pointer => ptr.ty.elemType(), | 7010 | .Pointer => ptr.ty.elemType(), |
| 6948 | else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr.ty}), | 7011 | else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr.ty}), |
| 6949 | }; | 7012 | }; |
| 6950 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 7013 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| blk: { |
| | 7014 | if (ptr_val.tag() == .int_u64) |
| | 7015 | break :blk; // do it at runtime |
| | 7016 | |
| 6951 | return sema.mod.constInst(sema.arena, src, .{ | 7017 | return sema.mod.constInst(sema.arena, src, .{ |
| 6952 | .ty = elem_ty, | 7018 | .ty = elem_ty, |
| 6953 | .val = try ptr_val.pointerDeref(sema.arena), | 7019 | .val = try ptr_val.pointerDeref(sema.arena), |