| ... | ... | @@ -2202,6 +2202,7 @@ const DeclGen = struct { |
| 2202 | 2202 | .int_from_ptr => try self.airIntFromPtr(inst), |
| 2203 | 2203 | .float_from_int => try self.airFloatFromInt(inst), |
| 2204 | 2204 | .int_from_float => try self.airIntFromFloat(inst), |
| 2205 | .int_from_bool => try self.airIntFromBool(inst), |
| 2205 | 2206 | .fpext, .fptrunc => try self.airFloatCast(inst), |
| 2206 | 2207 | .not => try self.airNot(inst), |
| 2207 | 2208 | |
| ... | ... | @@ -3174,50 +3175,64 @@ const DeclGen = struct { |
| 3174 | 3175 | const mod = self.module; |
| 3175 | 3176 | const src_ty_ref = try self.resolveType(src_ty, .direct); |
| 3176 | 3177 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); |
| 3177 | | if (src_ty_ref == dst_ty_ref) { |
| 3178 | | return src_id; |
| 3179 | | } |
| 3178 | const src_key = self.spv.cache.lookup(src_ty_ref); |
| 3179 | const dst_key = self.spv.cache.lookup(dst_ty_ref); |
| 3180 | 3180 | |
| 3181 | | // TODO: Some more cases are missing here |
| 3182 | | // See fn bitCast in llvm.zig |
| 3181 | const result_id = blk: { |
| 3182 | if (src_ty_ref == dst_ty_ref) { |
| 3183 | break :blk src_id; |
| 3184 | } |
| 3183 | 3185 | |
| 3184 | | if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { |
| 3185 | | const result_id = self.spv.allocId(); |
| 3186 | | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ |
| 3187 | | .id_result_type = self.typeId(dst_ty_ref), |
| 3188 | | .id_result = result_id, |
| 3189 | | .integer_value = src_id, |
| 3190 | | }); |
| 3191 | | return result_id; |
| 3192 | | } |
| 3186 | // TODO: Some more cases are missing here |
| 3187 | // See fn bitCast in llvm.zig |
| 3193 | 3188 | |
| 3194 | | // We can only use OpBitcast for specific conversions: between numerical types, and |
| 3195 | | // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast, |
| 3196 | | // otherwise use a temporary and perform a pointer cast. |
| 3197 | | const src_key = self.spv.cache.lookup(src_ty_ref); |
| 3198 | | const dst_key = self.spv.cache.lookup(dst_ty_ref); |
| 3189 | if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { |
| 3190 | const result_id = self.spv.allocId(); |
| 3191 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ |
| 3192 | .id_result_type = self.typeId(dst_ty_ref), |
| 3193 | .id_result = result_id, |
| 3194 | .integer_value = src_id, |
| 3195 | }); |
| 3196 | break :blk result_id; |
| 3197 | } |
| 3198 | |
| 3199 | // We can only use OpBitcast for specific conversions: between numerical types, and |
| 3200 | // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast, |
| 3201 | // otherwise use a temporary and perform a pointer cast. |
| 3202 | if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) { |
| 3203 | const result_id = self.spv.allocId(); |
| 3204 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 3205 | .id_result_type = self.typeId(dst_ty_ref), |
| 3206 | .id_result = result_id, |
| 3207 | .operand = src_id, |
| 3208 | }); |
| 3209 | |
| 3210 | break :blk result_id; |
| 3211 | } |
| 3199 | 3212 | |
| 3200 | | if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) { |
| 3201 | | const result_id = self.spv.allocId(); |
| 3213 | const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function); |
| 3214 | |
| 3215 | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); |
| 3216 | try self.store(src_ty, tmp_id, src_id, .{}); |
| 3217 | const casted_ptr_id = self.spv.allocId(); |
| 3202 | 3218 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 3203 | | .id_result_type = self.typeId(dst_ty_ref), |
| 3204 | | .id_result = result_id, |
| 3205 | | .operand = src_id, |
| 3219 | .id_result_type = self.typeId(dst_ptr_ty_ref), |
| 3220 | .id_result = casted_ptr_id, |
| 3221 | .operand = tmp_id, |
| 3206 | 3222 | }); |
| 3207 | | return result_id; |
| 3208 | | } |
| 3223 | break :blk try self.load(dst_ty, casted_ptr_id, .{}); |
| 3224 | }; |
| 3209 | 3225 | |
| 3210 | | const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function); |
| 3226 | // Because strange integers use sign-extended representation, we may need to normalize |
| 3227 | // the result here. |
| 3228 | // TODO: This detail could cause stuff like @as(*const i1, @ptrCast(&@as(u1, 1))) to break |
| 3229 | // should we change the representation of strange integers? |
| 3230 | if (dst_ty.zigTypeTag(mod) == .Int) { |
| 3231 | const info = self.arithmeticTypeInfo(dst_ty); |
| 3232 | return try self.normalize(dst_ty_ref, result_id, info); |
| 3233 | } |
| 3211 | 3234 | |
| 3212 | | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); |
| 3213 | | try self.store(src_ty, tmp_id, src_id, .{}); |
| 3214 | | const casted_ptr_id = self.spv.allocId(); |
| 3215 | | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 3216 | | .id_result_type = self.typeId(dst_ptr_ty_ref), |
| 3217 | | .id_result = casted_ptr_id, |
| 3218 | | .operand = tmp_id, |
| 3219 | | }); |
| 3220 | | return try self.load(dst_ty, casted_ptr_id, .{}); |
| 3235 | return result_id; |
| 3221 | 3236 | } |
| 3222 | 3237 | |
| 3223 | 3238 | fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -3340,6 +3355,22 @@ const DeclGen = struct { |
| 3340 | 3355 | return result_id; |
| 3341 | 3356 | } |
| 3342 | 3357 | |
| 3358 | fn airIntFromBool(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 3359 | if (self.liveness.isUnused(inst)) return null; |
| 3360 | |
| 3361 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3362 | const operand_id = try self.resolve(un_op); |
| 3363 | const result_ty = self.typeOfIndex(inst); |
| 3364 | |
| 3365 | var wip = try self.elementWise(result_ty); |
| 3366 | defer wip.deinit(); |
| 3367 | for (wip.results, 0..) |*result_id, i| { |
| 3368 | const elem_id = try wip.elementAt(Type.bool, operand_id, i); |
| 3369 | result_id.* = try self.intFromBool(wip.scalar_ty_ref, elem_id); |
| 3370 | } |
| 3371 | return try wip.finalize(); |
| 3372 | } |
| 3373 | |
| 3343 | 3374 | fn airFloatCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 3344 | 3375 | if (self.liveness.isUnused(inst)) return null; |
| 3345 | 3376 | |