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 {...@@ -568,6 +568,28 @@ pub const DeclGen = struct {
568 try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]);568 try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]);
569 }569 }
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
571 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {593 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
572 const dg = self.dg;594 const dg = self.dg;
573595
...@@ -618,6 +640,7 @@ pub const DeclGen = struct {...@@ -618,6 +640,7 @@ pub const DeclGen = struct {
618640
619 switch (ty.zigTypeTag()) {641 switch (ty.zigTypeTag()) {
620 .Int => try self.addInt(ty, val),642 .Int => try self.addInt(ty, val),
643 .Float => try self.addFloat(ty, val),
621 .Bool => try self.addConstBool(val.toBool()),644 .Bool => try self.addConstBool(val.toBool()),
622 .Array => switch (val.tag()) {645 .Array => switch (val.tag()) {
623 .aggregate => {646 .aggregate => {
...@@ -1690,6 +1713,8 @@ pub const DeclGen = struct {...@@ -1690,6 +1713,8 @@ pub const DeclGen = struct {
16901713
1691 .bitcast => try self.airBitcast(inst),1714 .bitcast => try self.airBitcast(inst),
1692 .intcast, .trunc => try self.airIntcast(inst),1715 .intcast, .trunc => try self.airIntcast(inst),
1716 .int_to_float => try self.airIntToFloat(inst),
1717 .float_to_int => try self.airFloatToInt(inst),
1693 .not => try self.airNot(inst),1718 .not => try self.airNot(inst),
16941719
1695 .slice_ptr => try self.airSliceField(inst, 0),1720 .slice_ptr => try self.airSliceField(inst, 0),
...@@ -2095,6 +2120,57 @@ pub const DeclGen = struct {...@@ -2095,6 +2120,57 @@ pub const DeclGen = struct {
2095 return result_id;2120 return result_id;
2096 }2121 }
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
2098 fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2174 fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2099 if (self.liveness.isUnused(inst)) return null;2175 if (self.liveness.isUnused(inst)) return null;
2100 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2176 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
test/behavior/cast.zig-6
...@@ -97,7 +97,6 @@ test "@intToFloat" {...@@ -97,7 +97,6 @@ test "@intToFloat" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
101100
102 const S = struct {101 const S = struct {
103 fn doTheTest() !void {102 fn doTheTest() !void {
...@@ -156,7 +155,6 @@ test "@floatToInt" {...@@ -156,7 +155,6 @@ test "@floatToInt" {
156 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO155 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO156 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
160158
161 try testFloatToInts();159 try testFloatToInts();
162 comptime try testFloatToInts();160 comptime try testFloatToInts();
...@@ -208,16 +206,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {...@@ -208,16 +206,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
208}206}
209207
210test "@intCast comptime_int" {208test "@intCast comptime_int" {
211 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
212
213 const result = @intCast(i32, 1234);209 const result = @intCast(i32, 1234);
214 try expect(@TypeOf(result) == i32);210 try expect(@TypeOf(result) == i32);
215 try expect(result == 1234);211 try expect(result == 1234);
216}212}
217213
218test "@floatCast comptime_int and comptime_float" {214test "@floatCast comptime_int and comptime_float" {
219 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
220
221 {215 {
222 const result = @floatCast(f16, 1234);216 const result = @floatCast(f16, 1234);
223 try expect(@TypeOf(result) == f16);217 try expect(@TypeOf(result) == f16);
test/behavior/error.zig+1
...@@ -916,6 +916,7 @@ test "optional error set return type" {...@@ -916,6 +916,7 @@ test "optional error set return type" {
916test "try used in recursive function with inferred error set" {916test "try used in recursive function with inferred error set" {
917 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO917 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
919 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
919920
920 const Value = union(enum) {921 const Value = union(enum) {
921 values: []const @This(),922 values: []const @This(),
test/behavior/maximum_minimum.zig+1
...@@ -106,6 +106,7 @@ test "@min/max for floats" {...@@ -106,6 +106,7 @@ test "@min/max for floats" {
106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
109110
110 const S = struct {111 const S = struct {
111 fn doTheTest(comptime T: type) !void {112 fn doTheTest(comptime T: type) !void {
test/behavior/slice.zig+2
...@@ -186,6 +186,8 @@ test "slicing zero length array" {...@@ -186,6 +186,8 @@ test "slicing zero length array" {
186186
187test "slicing pointer by length" {187test "slicing pointer by length" {
188 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;188 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
189 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
190
189 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };191 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
190 const ptr: [*]const u8 = @ptrCast([*]const u8, &array);192 const ptr: [*]const u8 = @ptrCast([*]const u8, &array);
191 const slice = ptr[1..][0..5];193 const slice = ptr[1..][0..5];