authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2023-05-15 03:02:11+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2023-05-15 03:04:17+03:30
log9c550721e40f50b2ee44a5b1bf633ebdd50d5fd2
treeb48bc312b807f0ef41adfdc04dbaa8ffb8e47719
parent2ce9122a009efa0a5d2857a0d29ad3d77a81dff1

spirv: lower float_to_int and int_to_float


5 files changed, 80 insertions(+), 6 deletions(-)

src/codegen/spirv.zig+76
......@@ -568,6 +568,28 @@ pub const DeclGen = struct {
568568 try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]);
569569 }
570570
571 fn addFloat(self: *@This(), ty: Type, val: Value) !void {
572 const target = self.dg.getTarget();
573 const len = ty.abiSize(target);
574
575 // TODO: Swap endianess if the compiler is big endian.
576 switch (ty.floatBits(target)) {
577 16 => {
578 const float_bits = val.toFloat(f16);
579 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
580 },
581 32 => {
582 const float_bits = val.toFloat(f32);
583 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
584 },
585 64 => {
586 const float_bits = val.toFloat(f64);
587 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
588 },
589 else => unreachable,
590 }
591 }
592
571593 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
572594 const dg = self.dg;
573595
......@@ -618,6 +640,7 @@ pub const DeclGen = struct {
618640
619641 switch (ty.zigTypeTag()) {
620642 .Int => try self.addInt(ty, val),
643 .Float => try self.addFloat(ty, val),
621644 .Bool => try self.addConstBool(val.toBool()),
622645 .Array => switch (val.tag()) {
623646 .aggregate => {
......@@ -1690,6 +1713,8 @@ pub const DeclGen = struct {
16901713
16911714 .bitcast => try self.airBitcast(inst),
16921715 .intcast, .trunc => try self.airIntcast(inst),
1716 .int_to_float => try self.airIntToFloat(inst),
1717 .float_to_int => try self.airFloatToInt(inst),
16931718 .not => try self.airNot(inst),
16941719
16951720 .slice_ptr => try self.airSliceField(inst, 0),
......@@ -2095,6 +2120,57 @@ pub const DeclGen = struct {
20952120 return result_id;
20962121 }
20972122
2123 fn airIntToFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2124 if (self.liveness.isUnused(inst)) return null;
2125
2126 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2127 const operand_ty = self.air.typeOf(ty_op.operand);
2128 const operand_id = try self.resolve(ty_op.operand);
2129 const operand_info = try self.arithmeticTypeInfo(operand_ty);
2130 const dest_ty = self.air.typeOfIndex(inst);
2131 const dest_ty_id = try self.resolveTypeId(dest_ty);
2132
2133 const result_id = self.spv.allocId();
2134 switch (operand_info.signedness) {
2135 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{
2136 .id_result_type = dest_ty_id,
2137 .id_result = result_id,
2138 .signed_value = operand_id,
2139 }),
2140 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{
2141 .id_result_type = dest_ty_id,
2142 .id_result = result_id,
2143 .unsigned_value = operand_id,
2144 }),
2145 }
2146 return result_id;
2147 }
2148
2149 fn airFloatToInt(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2150 if (self.liveness.isUnused(inst)) return null;
2151
2152 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2153 const operand_id = try self.resolve(ty_op.operand);
2154 const dest_ty = self.air.typeOfIndex(inst);
2155 const dest_info = try self.arithmeticTypeInfo(dest_ty);
2156 const dest_ty_id = try self.resolveTypeId(dest_ty);
2157
2158 const result_id = self.spv.allocId();
2159 switch (dest_info.signedness) {
2160 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{
2161 .id_result_type = dest_ty_id,
2162 .id_result = result_id,
2163 .float_value = operand_id,
2164 }),
2165 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{
2166 .id_result_type = dest_ty_id,
2167 .id_result = result_id,
2168 .float_value = operand_id,
2169 }),
2170 }
2171 return result_id;
2172 }
2173
20982174 fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
20992175 if (self.liveness.isUnused(inst)) return null;
21002176 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
test/behavior/cast.zig-6
......@@ -97,7 +97,6 @@ test "@intToFloat" {
9797 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9898 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9999 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
101100
102101 const S = struct {
103102 fn doTheTest() !void {
......@@ -156,7 +155,6 @@ test "@floatToInt" {
156155 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
157156 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
158157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
160158
161159 try testFloatToInts();
162160 comptime try testFloatToInts();
......@@ -208,16 +206,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
208206}
209207
210208test "@intCast comptime_int" {
211 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
212
213209 const result = @intCast(i32, 1234);
214210 try expect(@TypeOf(result) == i32);
215211 try expect(result == 1234);
216212}
217213
218214test "@floatCast comptime_int and comptime_float" {
219 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
220
221215 {
222216 const result = @floatCast(f16, 1234);
223217 try expect(@TypeOf(result) == f16);
test/behavior/error.zig+1
......@@ -916,6 +916,7 @@ test "optional error set return type" {
916916test "try used in recursive function with inferred error set" {
917917 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
918918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
919 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
919920
920921 const Value = union(enum) {
921922 values: []const @This(),
test/behavior/maximum_minimum.zig+1
......@@ -106,6 +106,7 @@ test "@min/max for floats" {
106106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
107107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
108108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
109110
110111 const S = struct {
111112 fn doTheTest(comptime T: type) !void {
test/behavior/slice.zig+2
......@@ -186,6 +186,8 @@ test "slicing zero length array" {
186186
187187test "slicing pointer by length" {
188188 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
189 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
190
189191 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
190192 const ptr: [*]const u8 = @ptrCast([*]const u8, &array);
191193 const slice = ptr[1..][0..5];