| ... | ... | @@ -9750,19 +9750,52 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 9750 | 9750 | const mod = sema.mod; |
| 9751 | 9751 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 9752 | 9752 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9753 | | const ptr = try sema.resolveInst(inst_data.operand); |
| 9754 | | const ptr_ty = sema.typeOf(ptr); |
| 9753 | const operand = try sema.resolveInst(inst_data.operand); |
| 9754 | const operand_ty = sema.typeOf(operand); |
| 9755 | const ptr_ty = operand_ty.scalarType(mod); |
| 9756 | const is_vector = operand_ty.zigTypeTag(mod) == .Vector; |
| 9755 | 9757 | if (!ptr_ty.isPtrAtRuntime(mod)) { |
| 9756 | 9758 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(mod)}); |
| 9757 | 9759 | } |
| 9758 | | if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| { |
| 9759 | | return Air.internedToRef((try mod.intValue( |
| 9760 | | Type.usize, |
| 9761 | | (try ptr_val.getUnsignedIntAdvanced(mod, sema)).?, |
| 9762 | | )).toIntern()); |
| 9760 | if (try sema.resolveMaybeUndefValIntable(operand)) |operand_val| ct: { |
| 9761 | if (!is_vector) { |
| 9762 | return Air.internedToRef((try mod.intValue( |
| 9763 | Type.usize, |
| 9764 | (try operand_val.getUnsignedIntAdvanced(mod, sema)).?, |
| 9765 | )).toIntern()); |
| 9766 | } |
| 9767 | const len = operand_ty.vectorLen(mod); |
| 9768 | const dest_ty = try mod.vectorType(.{ .child = .usize_type, .len = len }); |
| 9769 | const new_elems = try sema.arena.alloc(InternPool.Index, len); |
| 9770 | for (new_elems, 0..) |*new_elem, i| { |
| 9771 | const ptr_val = try operand_val.elemValue(mod, i); |
| 9772 | const addr = try ptr_val.getUnsignedIntAdvanced(mod, sema) orelse { |
| 9773 | // A vector element wasn't an integer pointer. This is a runtime operation. |
| 9774 | break :ct; |
| 9775 | }; |
| 9776 | new_elem.* = (try mod.intValue( |
| 9777 | Type.usize, |
| 9778 | addr, |
| 9779 | )).toIntern(); |
| 9780 | } |
| 9781 | return Air.internedToRef(try mod.intern(.{ .aggregate = .{ |
| 9782 | .ty = dest_ty.toIntern(), |
| 9783 | .storage = .{ .elems = new_elems }, |
| 9784 | } })); |
| 9763 | 9785 | } |
| 9764 | 9786 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); |
| 9765 | | return block.addUnOp(.int_from_ptr, ptr); |
| 9787 | if (!is_vector) { |
| 9788 | return block.addUnOp(.int_from_ptr, operand); |
| 9789 | } |
| 9790 | const len = operand_ty.vectorLen(mod); |
| 9791 | const dest_ty = try mod.vectorType(.{ .child = .usize_type, .len = len }); |
| 9792 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); |
| 9793 | for (new_elems, 0..) |*new_elem, i| { |
| 9794 | const idx_ref = try mod.intRef(Type.usize, i); |
| 9795 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 9796 | new_elem.* = try block.addUnOp(.int_from_ptr, old_elem); |
| 9797 | } |
| 9798 | return block.addAggregateInit(dest_ty, new_elems); |
| 9766 | 9799 | } |
| 9767 | 9800 | |
| 9768 | 9801 | fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -10133,44 +10166,73 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10133 | 10166 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10134 | 10167 | |
| 10135 | 10168 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); |
| 10169 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 10170 | |
| 10136 | 10171 | const operand = try sema.resolveInst(extra.rhs); |
| 10172 | const operand_ty = sema.typeOf(operand); |
| 10173 | const operand_scalar_ty = operand_ty.scalarType(mod); |
| 10174 | |
| 10175 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 10176 | const is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| 10137 | 10177 | |
| 10138 | 10178 | const target = mod.getTarget(); |
| 10139 | | const dest_is_comptime_float = switch (dest_ty.zigTypeTag(mod)) { |
| 10179 | const dest_is_comptime_float = switch (dest_scalar_ty.zigTypeTag(mod)) { |
| 10140 | 10180 | .ComptimeFloat => true, |
| 10141 | 10181 | .Float => false, |
| 10142 | 10182 | else => return sema.fail( |
| 10143 | 10183 | block, |
| 10144 | 10184 | src, |
| 10145 | | "expected float type, found '{}'", |
| 10185 | "expected float or vector type, found '{}'", |
| 10146 | 10186 | .{dest_ty.fmt(mod)}, |
| 10147 | 10187 | ), |
| 10148 | 10188 | }; |
| 10149 | 10189 | |
| 10150 | | const operand_ty = sema.typeOf(operand); |
| 10151 | | switch (operand_ty.zigTypeTag(mod)) { |
| 10190 | switch (operand_scalar_ty.zigTypeTag(mod)) { |
| 10152 | 10191 | .ComptimeFloat, .Float, .ComptimeInt => {}, |
| 10153 | 10192 | else => return sema.fail( |
| 10154 | 10193 | block, |
| 10155 | 10194 | operand_src, |
| 10156 | | "expected float type, found '{}'", |
| 10195 | "expected float or vector type, found '{}'", |
| 10157 | 10196 | .{operand_ty.fmt(mod)}, |
| 10158 | 10197 | ), |
| 10159 | 10198 | } |
| 10160 | 10199 | |
| 10161 | 10200 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { |
| 10162 | | return Air.internedToRef((try operand_val.floatCast(dest_ty, mod)).toIntern()); |
| 10201 | if (!is_vector) { |
| 10202 | return Air.internedToRef((try operand_val.floatCast(dest_ty, mod)).toIntern()); |
| 10203 | } |
| 10204 | const vec_len = operand_ty.vectorLen(mod); |
| 10205 | const new_elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 10206 | for (new_elems, 0..) |*new_elem, i| { |
| 10207 | const old_elem = try operand_val.elemValue(mod, i); |
| 10208 | new_elem.* = (try old_elem.floatCast(dest_scalar_ty, mod)).toIntern(); |
| 10209 | } |
| 10210 | return Air.internedToRef(try mod.intern(.{ .aggregate = .{ |
| 10211 | .ty = dest_ty.toIntern(), |
| 10212 | .storage = .{ .elems = new_elems }, |
| 10213 | } })); |
| 10163 | 10214 | } |
| 10164 | 10215 | if (dest_is_comptime_float) { |
| 10165 | 10216 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_float'", .{}); |
| 10166 | 10217 | } |
| 10167 | | const src_bits = operand_ty.floatBits(target); |
| 10168 | | const dst_bits = dest_ty.floatBits(target); |
| 10218 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); |
| 10219 | |
| 10220 | const src_bits = operand_scalar_ty.floatBits(target); |
| 10221 | const dst_bits = dest_scalar_ty.floatBits(target); |
| 10169 | 10222 | if (dst_bits >= src_bits) { |
| 10170 | 10223 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 10171 | 10224 | } |
| 10172 | | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); |
| 10173 | | return block.addTyOp(.fptrunc, dest_ty, operand); |
| 10225 | if (!is_vector) { |
| 10226 | return block.addTyOp(.fptrunc, dest_ty, operand); |
| 10227 | } |
| 10228 | const vec_len = operand_ty.vectorLen(mod); |
| 10229 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, vec_len); |
| 10230 | for (new_elems, 0..) |*new_elem, i| { |
| 10231 | const idx_ref = try mod.intRef(Type.usize, i); |
| 10232 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 10233 | new_elem.* = try block.addTyOp(.fptrunc, dest_scalar_ty, old_elem); |
| 10234 | } |
| 10235 | return block.addAggregateInit(dest_ty, new_elems); |
| 10174 | 10236 | } |
| 10175 | 10237 | |
| 10176 | 10238 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -19761,13 +19823,51 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19761 | 19823 | fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19762 | 19824 | const mod = sema.mod; |
| 19763 | 19825 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 19826 | const src = inst_data.src(); |
| 19764 | 19827 | const operand = try sema.resolveInst(inst_data.operand); |
| 19828 | const operand_ty = sema.typeOf(operand); |
| 19829 | const is_vector = operand_ty.zigTypeTag(mod) == .Vector; |
| 19830 | const operand_scalar_ty = operand_ty.scalarType(mod); |
| 19831 | if (operand_scalar_ty.toIntern() != .bool_type) { |
| 19832 | return sema.fail(block, src, "expected 'bool', found '{}'", .{operand_scalar_ty.zigTypeTag(mod)}); |
| 19833 | } |
| 19765 | 19834 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 19766 | | if (val.isUndef(mod)) return mod.undefRef(Type.u1); |
| 19767 | | if (val.toBool()) return Air.internedToRef((try mod.intValue(Type.u1, 1)).toIntern()); |
| 19768 | | return Air.internedToRef((try mod.intValue(Type.u1, 0)).toIntern()); |
| 19835 | if (!is_vector) { |
| 19836 | if (val.isUndef(mod)) return mod.undefRef(Type.u1); |
| 19837 | if (val.toBool()) return Air.internedToRef((try mod.intValue(Type.u1, 1)).toIntern()); |
| 19838 | return Air.internedToRef((try mod.intValue(Type.u1, 0)).toIntern()); |
| 19839 | } |
| 19840 | const len = operand_ty.vectorLen(mod); |
| 19841 | const dest_ty = try mod.vectorType(.{ .child = .u1_type, .len = len }); |
| 19842 | if (val.isUndef(mod)) return mod.undefRef(dest_ty); |
| 19843 | const new_elems = try sema.arena.alloc(InternPool.Index, len); |
| 19844 | for (new_elems, 0..) |*new_elem, i| { |
| 19845 | const old_elem = try val.elemValue(mod, i); |
| 19846 | const new_val = if (old_elem.isUndef(mod)) |
| 19847 | try mod.undefValue(Type.u1) |
| 19848 | else if (old_elem.toBool()) |
| 19849 | try mod.intValue(Type.u1, 1) |
| 19850 | else |
| 19851 | try mod.intValue(Type.u1, 0); |
| 19852 | new_elem.* = new_val.toIntern(); |
| 19853 | } |
| 19854 | return Air.internedToRef(try mod.intern(.{ .aggregate = .{ |
| 19855 | .ty = dest_ty.toIntern(), |
| 19856 | .storage = .{ .elems = new_elems }, |
| 19857 | } })); |
| 19858 | } |
| 19859 | if (!is_vector) { |
| 19860 | return block.addUnOp(.int_from_bool, operand); |
| 19769 | 19861 | } |
| 19770 | | return block.addUnOp(.int_from_bool, operand); |
| 19862 | const len = operand_ty.vectorLen(mod); |
| 19863 | const dest_ty = try mod.vectorType(.{ .child = .u1_type, .len = len }); |
| 19864 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); |
| 19865 | for (new_elems, 0..) |*new_elem, i| { |
| 19866 | const idx_ref = try mod.intRef(Type.usize, i); |
| 19867 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 19868 | new_elem.* = try block.addUnOp(.int_from_bool, old_elem); |
| 19869 | } |
| 19870 | return block.addAggregateInit(dest_ty, new_elems); |
| 19771 | 19871 | } |
| 19772 | 19872 | |
| 19773 | 19873 | fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -21050,34 +21150,74 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21050 | 21150 | const operand = try sema.resolveInst(extra.rhs); |
| 21051 | 21151 | const operand_ty = sema.typeOf(operand); |
| 21052 | 21152 | |
| 21053 | | _ = try sema.checkIntType(block, src, dest_ty); |
| 21054 | | try sema.checkFloatType(block, operand_src, operand_ty); |
| 21153 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 21154 | const is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| 21055 | 21155 | |
| 21056 | | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 21057 | | const result_val = try sema.intFromFloat(block, operand_src, val, operand_ty, dest_ty); |
| 21156 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 21157 | const operand_scalar_ty = operand_ty.scalarType(mod); |
| 21158 | |
| 21159 | _ = try sema.checkIntType(block, src, dest_scalar_ty); |
| 21160 | try sema.checkFloatType(block, operand_src, operand_scalar_ty); |
| 21161 | |
| 21162 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { |
| 21163 | const result_val = try sema.intFromFloat(block, operand_src, operand_val, operand_ty, dest_ty); |
| 21058 | 21164 | return Air.internedToRef(result_val.toIntern()); |
| 21059 | | } else if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 21165 | } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 21060 | 21166 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known"); |
| 21061 | 21167 | } |
| 21062 | 21168 | |
| 21063 | 21169 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); |
| 21064 | | if (dest_ty.intInfo(mod).bits == 0) { |
| 21170 | if (dest_scalar_ty.intInfo(mod).bits == 0) { |
| 21171 | if (!is_vector) { |
| 21172 | if (block.wantSafety()) { |
| 21173 | const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, Air.internedToRef((try mod.floatValue(operand_ty, 0.0)).toIntern())); |
| 21174 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| 21175 | } |
| 21176 | return Air.internedToRef((try mod.intValue(dest_ty, 0)).toIntern()); |
| 21177 | } |
| 21178 | if (block.wantSafety()) { |
| 21179 | const len = dest_ty.vectorLen(mod); |
| 21180 | for (0..len) |i| { |
| 21181 | const idx_ref = try mod.intRef(Type.usize, i); |
| 21182 | const elem_ref = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 21183 | const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, elem_ref, Air.internedToRef((try mod.floatValue(operand_scalar_ty, 0.0)).toIntern())); |
| 21184 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| 21185 | } |
| 21186 | } |
| 21187 | return Air.internedToRef(try mod.intern(.{ .aggregate = .{ |
| 21188 | .ty = dest_ty.toIntern(), |
| 21189 | .storage = .{ .repeated_elem = (try mod.intValue(dest_scalar_ty, 0)).toIntern() }, |
| 21190 | } })); |
| 21191 | } |
| 21192 | if (!is_vector) { |
| 21193 | const result = try block.addTyOp(if (block.float_mode == .Optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); |
| 21065 | 21194 | if (block.wantSafety()) { |
| 21066 | | const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, Air.internedToRef((try mod.floatValue(operand_ty, 0.0)).toIntern())); |
| 21195 | const back = try block.addTyOp(.float_from_int, operand_ty, result); |
| 21196 | const diff = try block.addBinOp(.sub, operand, back); |
| 21197 | const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try mod.floatValue(operand_ty, 1.0)).toIntern())); |
| 21198 | const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try mod.floatValue(operand_ty, -1.0)).toIntern())); |
| 21199 | const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg); |
| 21067 | 21200 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| 21068 | 21201 | } |
| 21069 | | return Air.internedToRef((try mod.intValue(dest_ty, 0)).toIntern()); |
| 21202 | return result; |
| 21070 | 21203 | } |
| 21071 | | const result = try block.addTyOp(if (block.float_mode == .Optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); |
| 21072 | | if (block.wantSafety()) { |
| 21073 | | const back = try block.addTyOp(.float_from_int, operand_ty, result); |
| 21074 | | const diff = try block.addBinOp(.sub, operand, back); |
| 21075 | | const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try mod.floatValue(operand_ty, 1.0)).toIntern())); |
| 21076 | | const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try mod.floatValue(operand_ty, -1.0)).toIntern())); |
| 21077 | | const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg); |
| 21078 | | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| 21204 | const len = dest_ty.vectorLen(mod); |
| 21205 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); |
| 21206 | for (new_elems, 0..) |*new_elem, i| { |
| 21207 | const idx_ref = try mod.intRef(Type.usize, i); |
| 21208 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 21209 | const result = try block.addTyOp(if (block.float_mode == .Optimized) .int_from_float_optimized else .int_from_float, dest_scalar_ty, old_elem); |
| 21210 | if (block.wantSafety()) { |
| 21211 | const back = try block.addTyOp(.float_from_int, operand_scalar_ty, result); |
| 21212 | const diff = try block.addBinOp(.sub, old_elem, back); |
| 21213 | const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try mod.floatValue(operand_scalar_ty, 1.0)).toIntern())); |
| 21214 | const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try mod.floatValue(operand_scalar_ty, -1.0)).toIntern())); |
| 21215 | const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg); |
| 21216 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| 21217 | } |
| 21218 | new_elem.* = result; |
| 21079 | 21219 | } |
| 21080 | | return result; |
| 21220 | return block.addAggregateInit(dest_ty, new_elems); |
| 21081 | 21221 | } |
| 21082 | 21222 | |
| 21083 | 21223 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -21090,18 +21230,34 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21090 | 21230 | const operand = try sema.resolveInst(extra.rhs); |
| 21091 | 21231 | const operand_ty = sema.typeOf(operand); |
| 21092 | 21232 | |
| 21093 | | try sema.checkFloatType(block, src, dest_ty); |
| 21094 | | _ = try sema.checkIntType(block, operand_src, operand_ty); |
| 21233 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 21234 | const is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| 21235 | |
| 21236 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 21237 | const operand_scalar_ty = operand_ty.scalarType(mod); |
| 21095 | 21238 | |
| 21096 | | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 21097 | | const result_val = try val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema); |
| 21239 | try sema.checkFloatType(block, src, dest_scalar_ty); |
| 21240 | _ = try sema.checkIntType(block, operand_src, operand_scalar_ty); |
| 21241 | |
| 21242 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { |
| 21243 | const result_val = try operand_val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, mod, sema); |
| 21098 | 21244 | return Air.internedToRef(result_val.toIntern()); |
| 21099 | | } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 21245 | } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 21100 | 21246 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known"); |
| 21101 | 21247 | } |
| 21102 | 21248 | |
| 21103 | | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); |
| 21104 | | return block.addTyOp(.float_from_int, dest_ty, operand); |
| 21249 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21250 | if (!is_vector) { |
| 21251 | return block.addTyOp(.float_from_int, dest_ty, operand); |
| 21252 | } |
| 21253 | const len = operand_ty.vectorLen(mod); |
| 21254 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); |
| 21255 | for (new_elems, 0..) |*new_elem, i| { |
| 21256 | const idx_ref = try mod.intRef(Type.usize, i); |
| 21257 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 21258 | new_elem.* = try block.addTyOp(.float_from_int, dest_scalar_ty, old_elem); |
| 21259 | } |
| 21260 | return block.addAggregateInit(dest_ty, new_elems); |
| 21105 | 21261 | } |
| 21106 | 21262 | |
| 21107 | 21263 | fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -21113,9 +21269,20 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21113 | 21269 | |
| 21114 | 21270 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21115 | 21271 | const operand_res = try sema.resolveInst(extra.rhs); |
| 21116 | | const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src); |
| 21117 | 21272 | |
| 21118 | | const ptr_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt"); |
| 21273 | const uncoerced_operand_ty = sema.typeOf(operand_res); |
| 21274 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt"); |
| 21275 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, uncoerced_operand_ty, src, operand_src); |
| 21276 | |
| 21277 | const is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| 21278 | const operand_ty = if (is_vector) operand_ty: { |
| 21279 | const len = dest_ty.vectorLen(mod); |
| 21280 | break :operand_ty try mod.vectorType(.{ .child = .usize_type, .len = len }); |
| 21281 | } else Type.usize; |
| 21282 | |
| 21283 | const operand_coerced = try sema.coerce(block, operand_ty, operand_res, operand_src); |
| 21284 | |
| 21285 | const ptr_ty = dest_ty.scalarType(mod); |
| 21119 | 21286 | try sema.checkPtrType(block, src, ptr_ty); |
| 21120 | 21287 | const elem_ty = ptr_ty.elemType2(mod); |
| 21121 | 21288 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema); |
| ... | ... | @@ -21131,38 +21298,83 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21131 | 21298 | } |
| 21132 | 21299 | |
| 21133 | 21300 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| 21134 | | const addr = val.toUnsignedInt(mod); |
| 21135 | | if (!ptr_ty.isAllowzeroPtr(mod) and addr == 0) |
| 21136 | | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)}); |
| 21137 | | if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0) |
| 21138 | | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)}); |
| 21139 | | |
| 21140 | | const ptr_val = switch (ptr_ty.zigTypeTag(mod)) { |
| 21141 | | .Optional => (try mod.intern(.{ .opt = .{ |
| 21142 | | .ty = ptr_ty.toIntern(), |
| 21143 | | .val = if (addr == 0) .none else (try mod.ptrIntValue(ptr_ty.childType(mod), addr)).toIntern(), |
| 21144 | | } })).toValue(), |
| 21145 | | .Pointer => try mod.ptrIntValue(ptr_ty, addr), |
| 21146 | | else => unreachable, |
| 21147 | | }; |
| 21148 | | return Air.internedToRef(ptr_val.toIntern()); |
| 21301 | if (!is_vector) { |
| 21302 | const ptr_val = try sema.ptrFromIntVal(block, operand_src, val, ptr_ty, ptr_align); |
| 21303 | return Air.internedToRef(ptr_val.toIntern()); |
| 21304 | } |
| 21305 | const len = dest_ty.vectorLen(mod); |
| 21306 | const new_elems = try sema.arena.alloc(InternPool.Index, len); |
| 21307 | for (new_elems, 0..) |*new_elem, i| { |
| 21308 | const elem = try val.elemValue(mod, i); |
| 21309 | const ptr_val = try sema.ptrFromIntVal(block, operand_src, elem, ptr_ty, ptr_align); |
| 21310 | new_elem.* = ptr_val.toIntern(); |
| 21311 | } |
| 21312 | return Air.internedToRef(try mod.intern(.{ .aggregate = .{ |
| 21313 | .ty = dest_ty.toIntern(), |
| 21314 | .storage = .{ .elems = new_elems }, |
| 21315 | } })); |
| 21149 | 21316 | } |
| 21150 | 21317 | |
| 21151 | 21318 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21152 | | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { |
| 21153 | | if (!ptr_ty.isAllowzeroPtr(mod)) { |
| 21154 | | const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); |
| 21155 | | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 21319 | if (!is_vector) { |
| 21320 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { |
| 21321 | if (!ptr_ty.isAllowzeroPtr(mod)) { |
| 21322 | const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); |
| 21323 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 21324 | } |
| 21325 | if (ptr_align > 1) { |
| 21326 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, ptr_align - 1)).toIntern()); |
| 21327 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); |
| 21328 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| 21329 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); |
| 21330 | } |
| 21156 | 21331 | } |
| 21332 | return block.addBitCast(dest_ty, operand_coerced); |
| 21333 | } |
| 21157 | 21334 | |
| 21158 | | if (ptr_align > 1) { |
| 21159 | | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, ptr_align - 1)).toIntern()); |
| 21160 | | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); |
| 21161 | | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| 21162 | | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); |
| 21335 | const len = dest_ty.vectorLen(mod); |
| 21336 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { |
| 21337 | for (0..len) |i| { |
| 21338 | const idx_ref = try mod.intRef(Type.usize, i); |
| 21339 | const elem_coerced = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); |
| 21340 | if (!ptr_ty.isAllowzeroPtr(mod)) { |
| 21341 | const is_non_zero = try block.addBinOp(.cmp_neq, elem_coerced, .zero_usize); |
| 21342 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 21343 | } |
| 21344 | if (ptr_align > 1) { |
| 21345 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, ptr_align - 1)).toIntern()); |
| 21346 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1); |
| 21347 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| 21348 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); |
| 21349 | } |
| 21163 | 21350 | } |
| 21164 | 21351 | } |
| 21165 | | return block.addBitCast(ptr_ty, operand_coerced); |
| 21352 | |
| 21353 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); |
| 21354 | for (new_elems, 0..) |*new_elem, i| { |
| 21355 | const idx_ref = try mod.intRef(Type.usize, i); |
| 21356 | const old_elem = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); |
| 21357 | new_elem.* = try block.addBitCast(ptr_ty, old_elem); |
| 21358 | } |
| 21359 | return block.addAggregateInit(dest_ty, new_elems); |
| 21360 | } |
| 21361 | |
| 21362 | fn ptrFromIntVal(sema: *Sema, block: *Block, operand_src: LazySrcLoc, operand_val: Value, ptr_ty: Type, ptr_align: u32) !Value { |
| 21363 | const mod = sema.mod; |
| 21364 | const addr = operand_val.toUnsignedInt(mod); |
| 21365 | if (!ptr_ty.isAllowzeroPtr(mod) and addr == 0) |
| 21366 | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)}); |
| 21367 | if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0) |
| 21368 | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)}); |
| 21369 | |
| 21370 | return switch (ptr_ty.zigTypeTag(mod)) { |
| 21371 | .Optional => (try mod.intern(.{ .opt = .{ |
| 21372 | .ty = ptr_ty.toIntern(), |
| 21373 | .val = if (addr == 0) .none else (try mod.ptrIntValue(ptr_ty.childType(mod), addr)).toIntern(), |
| 21374 | } })).toValue(), |
| 21375 | .Pointer => try mod.ptrIntValue(ptr_ty, addr), |
| 21376 | else => unreachable, |
| 21377 | }; |
| 21166 | 21378 | } |
| 21167 | 21379 | |
| 21168 | 21380 | fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |