| ... | @@ -9750,19 +9750,52 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -9750,19 +9750,52 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 9750 | const mod = sema.mod; | 9750 | const mod = sema.mod; |
| 9751 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 9751 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 9752 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9752 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9753 | const ptr = try sema.resolveInst(inst_data.operand); | 9753 | const operand = try sema.resolveInst(inst_data.operand); |
| 9754 | const ptr_ty = sema.typeOf(ptr); | 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 | if (!ptr_ty.isPtrAtRuntime(mod)) { | 9757 | if (!ptr_ty.isPtrAtRuntime(mod)) { |
| 9756 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(mod)}); | 9758 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(mod)}); |
| 9757 | } | 9759 | } |
| 9758 | if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| { | 9760 | if (try sema.resolveMaybeUndefValIntable(operand)) |operand_val| ct: { |
| 9759 | return Air.internedToRef((try mod.intValue( | 9761 | if (!is_vector) { |
| 9760 | Type.usize, | 9762 | return Air.internedToRef((try mod.intValue( |
| 9761 | (try ptr_val.getUnsignedIntAdvanced(mod, sema)).?, | 9763 | Type.usize, |
| 9762 | )).toIntern()); | 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 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); | 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 | fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,44 +10166,73 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10133 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 10166 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10134 | | 10167 | |
| 10135 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); | 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 | const operand = try sema.resolveInst(extra.rhs); | 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 | const target = mod.getTarget(); | 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 | .ComptimeFloat => true, | 10180 | .ComptimeFloat => true, |
| 10141 | .Float => false, | 10181 | .Float => false, |
| 10142 | else => return sema.fail( | 10182 | else => return sema.fail( |
| 10143 | block, | 10183 | block, |
| 10144 | src, | 10184 | src, |
| 10145 | "expected float type, found '{}'", | 10185 | "expected float or vector type, found '{}'", |
| 10146 | .{dest_ty.fmt(mod)}, | 10186 | .{dest_ty.fmt(mod)}, |
| 10147 | ), | 10187 | ), |
| 10148 | }; | 10188 | }; |
| 10149 | | 10189 | |
| 10150 | const operand_ty = sema.typeOf(operand); | 10190 | switch (operand_scalar_ty.zigTypeTag(mod)) { |
| 10151 | switch (operand_ty.zigTypeTag(mod)) { | | |
| 10152 | .ComptimeFloat, .Float, .ComptimeInt => {}, | 10191 | .ComptimeFloat, .Float, .ComptimeInt => {}, |
| 10153 | else => return sema.fail( | 10192 | else => return sema.fail( |
| 10154 | block, | 10193 | block, |
| 10155 | operand_src, | 10194 | operand_src, |
| 10156 | "expected float type, found '{}'", | 10195 | "expected float or vector type, found '{}'", |
| 10157 | .{operand_ty.fmt(mod)}, | 10196 | .{operand_ty.fmt(mod)}, |
| 10158 | ), | 10197 | ), |
| 10159 | } | 10198 | } |
| 10160 | | 10199 | |
| 10161 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { | 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 | if (dest_is_comptime_float) { | 10215 | if (dest_is_comptime_float) { |
| 10165 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_float'", .{}); | 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); | 10218 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); |
| 10168 | const dst_bits = dest_ty.floatBits(target); | 10219 | |
| | 10220 | const src_bits = operand_scalar_ty.floatBits(target); |
| | 10221 | const dst_bits = dest_scalar_ty.floatBits(target); |
| 10169 | if (dst_bits >= src_bits) { | 10222 | if (dst_bits >= src_bits) { |
| 10170 | return sema.coerce(block, dest_ty, operand, operand_src); | 10223 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 10171 | } | 10224 | } |
| 10172 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); | 10225 | if (!is_vector) { |
| 10173 | return block.addTyOp(.fptrunc, dest_ty, operand); | 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 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,13 +19823,51 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19761 | fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 19823 | fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19762 | const mod = sema.mod; | 19824 | const mod = sema.mod; |
| 19763 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 19825 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| | 19826 | const src = inst_data.src(); |
| 19764 | const operand = try sema.resolveInst(inst_data.operand); | 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 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 19834 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 19766 | if (val.isUndef(mod)) return mod.undefRef(Type.u1); | 19835 | if (!is_vector) { |
| 19767 | if (val.toBool()) return Air.internedToRef((try mod.intValue(Type.u1, 1)).toIntern()); | 19836 | if (val.isUndef(mod)) return mod.undefRef(Type.u1); |
| 19768 | return Air.internedToRef((try mod.intValue(Type.u1, 0)).toIntern()); | 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 | fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,34 +21150,74 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21050 | const operand = try sema.resolveInst(extra.rhs); | 21150 | const operand = try sema.resolveInst(extra.rhs); |
| 21051 | const operand_ty = sema.typeOf(operand); | 21151 | const operand_ty = sema.typeOf(operand); |
| 21052 | | 21152 | |
| 21053 | _ = try sema.checkIntType(block, src, dest_ty); | 21153 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 21054 | try sema.checkFloatType(block, operand_src, operand_ty); | 21154 | const is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| 21055 | | 21155 | |
| 21056 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 21156 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 21057 | const result_val = try sema.intFromFloat(block, operand_src, val, operand_ty, dest_ty); | 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 | return Air.internedToRef(result_val.toIntern()); | 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 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known"); | 21166 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known"); |
| 21061 | } | 21167 | } |
| 21062 | | 21168 | |
| 21063 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); | 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 | if (block.wantSafety()) { | 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 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | 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); | 21204 | const len = dest_ty.vectorLen(mod); |
| 21072 | if (block.wantSafety()) { | 21205 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); |
| 21073 | const back = try block.addTyOp(.float_from_int, operand_ty, result); | 21206 | for (new_elems, 0..) |*new_elem, i| { |
| 21074 | const diff = try block.addBinOp(.sub, operand, back); | 21207 | const idx_ref = try mod.intRef(Type.usize, i); |
| 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())); | 21208 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 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())); | 21209 | const result = try block.addTyOp(if (block.float_mode == .Optimized) .int_from_float_optimized else .int_from_float, dest_scalar_ty, old_elem); |
| 21077 | const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg); | 21210 | if (block.wantSafety()) { |
| 21078 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | 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 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,18 +21230,34 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21090 | const operand = try sema.resolveInst(extra.rhs); | 21230 | const operand = try sema.resolveInst(extra.rhs); |
| 21091 | const operand_ty = sema.typeOf(operand); | 21231 | const operand_ty = sema.typeOf(operand); |
| 21092 | | 21232 | |
| 21093 | try sema.checkFloatType(block, src, dest_ty); | 21233 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 21094 | _ = try sema.checkIntType(block, operand_src, operand_ty); | 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| { | 21239 | try sema.checkFloatType(block, src, dest_scalar_ty); |
| 21097 | const result_val = try val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema); | 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 | return Air.internedToRef(result_val.toIntern()); | 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 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known"); | 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); | 21249 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21104 | return block.addTyOp(.float_from_int, dest_ty, operand); | 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 | fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,9 +21269,20 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21113 | | 21269 | |
| 21114 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 21270 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21115 | const operand_res = try sema.resolveInst(extra.rhs); | 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 | try sema.checkPtrType(block, src, ptr_ty); | 21286 | try sema.checkPtrType(block, src, ptr_ty); |
| 21120 | const elem_ty = ptr_ty.elemType2(mod); | 21287 | const elem_ty = ptr_ty.elemType2(mod); |
| 21121 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema); | 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,38 +21298,83 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21131 | } | 21298 | } |
| 21132 | | 21299 | |
| 21133 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { | 21300 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| 21134 | const addr = val.toUnsignedInt(mod); | 21301 | if (!is_vector) { |
| 21135 | if (!ptr_ty.isAllowzeroPtr(mod) and addr == 0) | 21302 | const ptr_val = try sema.ptrFromIntVal(block, operand_src, val, ptr_ty, ptr_align); |
| 21136 | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)}); | 21303 | return Air.internedToRef(ptr_val.toIntern()); |
| 21137 | if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0) | 21304 | } |
| 21138 | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)}); | 21305 | const len = dest_ty.vectorLen(mod); |
| 21139 | | 21306 | const new_elems = try sema.arena.alloc(InternPool.Index, len); |
| 21140 | const ptr_val = switch (ptr_ty.zigTypeTag(mod)) { | 21307 | for (new_elems, 0..) |*new_elem, i| { |
| 21141 | .Optional => (try mod.intern(.{ .opt = .{ | 21308 | const elem = try val.elemValue(mod, i); |
| 21142 | .ty = ptr_ty.toIntern(), | 21309 | const ptr_val = try sema.ptrFromIntVal(block, operand_src, elem, ptr_ty, ptr_align); |
| 21143 | .val = if (addr == 0) .none else (try mod.ptrIntValue(ptr_ty.childType(mod), addr)).toIntern(), | 21310 | new_elem.* = ptr_val.toIntern(); |
| 21144 | } })).toValue(), | 21311 | } |
| 21145 | .Pointer => try mod.ptrIntValue(ptr_ty, addr), | 21312 | return Air.internedToRef(try mod.intern(.{ .aggregate = .{ |
| 21146 | else => unreachable, | 21313 | .ty = dest_ty.toIntern(), |
| 21147 | }; | 21314 | .storage = .{ .elems = new_elems }, |
| 21148 | return Air.internedToRef(ptr_val.toIntern()); | 21315 | } })); |
| 21149 | } | 21316 | } |
| 21150 | | 21317 | |
| 21151 | try sema.requireRuntimeBlock(block, src, operand_src); | 21318 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21152 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { | 21319 | if (!is_vector) { |
| 21153 | if (!ptr_ty.isAllowzeroPtr(mod)) { | 21320 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { |
| 21154 | const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); | 21321 | if (!ptr_ty.isAllowzeroPtr(mod)) { |
| 21155 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | 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) { | 21335 | const len = dest_ty.vectorLen(mod); |
| 21159 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, ptr_align - 1)).toIntern()); | 21336 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { |
| 21160 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); | 21337 | for (0..len) |i| { |
| 21161 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | 21338 | const idx_ref = try mod.intRef(Type.usize, i); |
| 21162 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | 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 | fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 21380 | fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |