spirv: lower float_to_int and int_to_float

This commit is contained in:
Ali Chraghi 2023-05-15 03:02:11 +03:30
parent 2ce9122a00
commit 9c550721e4
5 changed files with 80 additions and 6 deletions

View File

@ -568,6 +568,28 @@ pub const DeclGen = struct {
try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]); 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 { fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
const dg = self.dg; const dg = self.dg;
@ -618,6 +640,7 @@ pub const DeclGen = struct {
switch (ty.zigTypeTag()) { switch (ty.zigTypeTag()) {
.Int => try self.addInt(ty, val), .Int => try self.addInt(ty, val),
.Float => try self.addFloat(ty, val),
.Bool => try self.addConstBool(val.toBool()), .Bool => try self.addConstBool(val.toBool()),
.Array => switch (val.tag()) { .Array => switch (val.tag()) {
.aggregate => { .aggregate => {
@ -1690,6 +1713,8 @@ pub const DeclGen = struct {
.bitcast => try self.airBitcast(inst), .bitcast => try self.airBitcast(inst),
.intcast, .trunc => try self.airIntcast(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), .not => try self.airNot(inst),
.slice_ptr => try self.airSliceField(inst, 0), .slice_ptr => try self.airSliceField(inst, 0),
@ -2095,6 +2120,57 @@ pub const DeclGen = struct {
return result_id; 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 { fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
if (self.liveness.isUnused(inst)) return null; if (self.liveness.isUnused(inst)) return null;
const ty_op = self.air.instructions.items(.data)[inst].ty_op; const ty_op = self.air.instructions.items(.data)[inst].ty_op;

View File

@ -97,7 +97,6 @@ test "@intToFloat" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 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_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) 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 { const S = struct {
fn doTheTest() !void { 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_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) 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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
try testFloatToInts(); try testFloatToInts();
comptime try testFloatToInts(); comptime try testFloatToInts();
@ -208,16 +206,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
} }
test "@intCast comptime_int" { test "@intCast comptime_int" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const result = @intCast(i32, 1234); const result = @intCast(i32, 1234);
try expect(@TypeOf(result) == i32); try expect(@TypeOf(result) == i32);
try expect(result == 1234); try expect(result == 1234);
} }
test "@floatCast comptime_int and comptime_float" { test "@floatCast comptime_int and comptime_float" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
{ {
const result = @floatCast(f16, 1234); const result = @floatCast(f16, 1234);
try expect(@TypeOf(result) == f16); try expect(@TypeOf(result) == f16);

View File

@ -916,6 +916,7 @@ test "optional error set return type" {
test "try used in recursive function with inferred error set" { 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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) 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) { const Value = union(enum) {
values: []const @This(), values: []const @This(),

View File

@ -106,6 +106,7 @@ test "@min/max for floats" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 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_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) 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 { const S = struct {
fn doTheTest(comptime T: type) !void { fn doTheTest(comptime T: type) !void {

View File

@ -186,6 +186,8 @@ test "slicing zero length array" {
test "slicing pointer by length" { test "slicing pointer by length" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; 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 array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
const ptr: [*]const u8 = @ptrCast([*]const u8, &array); const ptr: [*]const u8 = @ptrCast([*]const u8, &array);
const slice = ptr[1..][0..5]; const slice = ptr[1..][0..5];