diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index dfb51cecef..d7ab7ed4e0 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -568,6 +568,28 @@ pub const DeclGen = struct { try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]); } + fn addFloat(self: *@This(), ty: Type, val: Value) !void { + const target = self.dg.getTarget(); + const len = ty.abiSize(target); + + // TODO: Swap endianess if the compiler is big endian. + switch (ty.floatBits(target)) { + 16 => { + const float_bits = val.toFloat(f16); + try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]); + }, + 32 => { + const float_bits = val.toFloat(f32); + try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]); + }, + 64 => { + const float_bits = val.toFloat(f64); + try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]); + }, + else => unreachable, + } + } + fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void { const dg = self.dg; @@ -618,6 +640,7 @@ pub const DeclGen = struct { switch (ty.zigTypeTag()) { .Int => try self.addInt(ty, val), + .Float => try self.addFloat(ty, val), .Bool => try self.addConstBool(val.toBool()), .Array => switch (val.tag()) { .aggregate => { @@ -1690,6 +1713,8 @@ pub const DeclGen = struct { .bitcast => try self.airBitcast(inst), .intcast, .trunc => try self.airIntcast(inst), + .int_to_float => try self.airIntToFloat(inst), + .float_to_int => try self.airFloatToInt(inst), .not => try self.airNot(inst), .slice_ptr => try self.airSliceField(inst, 0), @@ -2095,6 +2120,57 @@ pub const DeclGen = struct { return result_id; } + fn airIntToFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const operand_ty = self.air.typeOf(ty_op.operand); + const operand_id = try self.resolve(ty_op.operand); + const operand_info = try self.arithmeticTypeInfo(operand_ty); + const dest_ty = self.air.typeOfIndex(inst); + const dest_ty_id = try self.resolveTypeId(dest_ty); + + const result_id = self.spv.allocId(); + switch (operand_info.signedness) { + .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{ + .id_result_type = dest_ty_id, + .id_result = result_id, + .signed_value = operand_id, + }), + .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{ + .id_result_type = dest_ty_id, + .id_result = result_id, + .unsigned_value = operand_id, + }), + } + return result_id; + } + + fn airFloatToInt(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const operand_id = try self.resolve(ty_op.operand); + const dest_ty = self.air.typeOfIndex(inst); + const dest_info = try self.arithmeticTypeInfo(dest_ty); + const dest_ty_id = try self.resolveTypeId(dest_ty); + + const result_id = self.spv.allocId(); + switch (dest_info.signedness) { + .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{ + .id_result_type = dest_ty_id, + .id_result = result_id, + .float_value = operand_id, + }), + .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{ + .id_result_type = dest_ty_id, + .id_result = result_id, + .float_value = operand_id, + }), + } + return result_id; + } + fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { if (self.liveness.isUnused(inst)) return null; const ty_op = self.air.instructions.items(.data)[inst].ty_op; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 20f84184a0..79af2176d1 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -97,7 +97,6 @@ test "@intToFloat" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -156,7 +155,6 @@ test "@floatToInt" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testFloatToInts(); comptime try testFloatToInts(); @@ -208,16 +206,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { } test "@intCast comptime_int" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const result = @intCast(i32, 1234); try expect(@TypeOf(result) == i32); try expect(result == 1234); } test "@floatCast comptime_int and comptime_float" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - { const result = @floatCast(f16, 1234); try expect(@TypeOf(result) == f16); diff --git a/test/behavior/error.zig b/test/behavior/error.zig index 7e457c6456..f179739d15 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -916,6 +916,7 @@ test "optional error set return type" { test "try used in recursive function with inferred error set" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO const Value = union(enum) { values: []const @This(), diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index 6496e00afd..f2799d229c 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -106,6 +106,7 @@ test "@min/max for floats" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest(comptime T: type) !void { diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 79fa3b9ce7..3b88636dca 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -186,6 +186,8 @@ test "slicing zero length array" { test "slicing pointer by length" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; const ptr: [*]const u8 = @ptrCast([*]const u8, &array); const slice = ptr[1..][0..5];