| author | |
| committer | |
| log | 958fba0eb715fe9f0b5eddcf53507db03e37ae09 |
| tree | 2505c7bdfd50cebb986201271a42899fce12c21c |
| parent | b754068fbc7492962953068d31386d4c04e37ae5 |
| parent | 6fca3f8b72397d62dd7b2d2e07db843c88428ac3 |
| signature |
spirv: get more behavior tests passing7 files changed, 114 insertions(+), 20 deletions(-)
src/codegen/spirv.zig+110-4| ... | @@ -369,6 +369,17 @@ pub const DeclGen = struct { | ... | @@ -369,6 +369,17 @@ pub const DeclGen = struct { |
| 369 | .composite_integer, | 369 | .composite_integer, |
| 370 | }; | 370 | }; |
| 371 | }, | 371 | }, |
| 372 | .Enum => blk: { | ||
| 373 | var buffer: Type.Payload.Bits = undefined; | ||
| 374 | const int_ty = ty.intTagType(&buffer); | ||
| 375 | const int_info = int_ty.intInfo(target); | ||
| 376 | break :blk ArithmeticTypeInfo{ | ||
| 377 | .bits = int_info.bits, | ||
| 378 | .is_vector = false, | ||
| 379 | .signedness = int_info.signedness, | ||
| 380 | .class = .integer, | ||
| 381 | }; | ||
| 382 | }, | ||
| 372 | // As of yet, there is no vector support in the self-hosted compiler. | 383 | // As of yet, there is no vector support in the self-hosted compiler. |
| 373 | .Vector => self.todo("implement arithmeticTypeInfo for Vector", .{}), | 384 | .Vector => self.todo("implement arithmeticTypeInfo for Vector", .{}), |
| 374 | // TODO: For which types is this the case? | 385 | // TODO: For which types is this the case? |
| ... | @@ -568,6 +579,28 @@ pub const DeclGen = struct { | ... | @@ -568,6 +579,28 @@ pub const DeclGen = struct { |
| 568 | try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]); | 579 | try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]); |
| 569 | } | 580 | } |
| 570 | 581 | ||
| 582 | fn addFloat(self: *@This(), ty: Type, val: Value) !void { | ||
| 583 | const target = self.dg.getTarget(); | ||
| 584 | const len = ty.abiSize(target); | ||
| 585 | |||
| 586 | // TODO: Swap endianess if the compiler is big endian. | ||
| 587 | switch (ty.floatBits(target)) { | ||
| 588 | 16 => { | ||
| 589 | const float_bits = val.toFloat(f16); | ||
| 590 | try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]); | ||
| 591 | }, | ||
| 592 | 32 => { | ||
| 593 | const float_bits = val.toFloat(f32); | ||
| 594 | try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]); | ||
| 595 | }, | ||
| 596 | 64 => { | ||
| 597 | const float_bits = val.toFloat(f64); | ||
| 598 | try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]); | ||
| 599 | }, | ||
| 600 | else => unreachable, | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 571 | fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void { | 604 | fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void { |
| 572 | const dg = self.dg; | 605 | const dg = self.dg; |
| 573 | 606 | ||
| ... | @@ -618,6 +651,7 @@ pub const DeclGen = struct { | ... | @@ -618,6 +651,7 @@ pub const DeclGen = struct { |
| 618 | 651 | ||
| 619 | switch (ty.zigTypeTag()) { | 652 | switch (ty.zigTypeTag()) { |
| 620 | .Int => try self.addInt(ty, val), | 653 | .Int => try self.addInt(ty, val), |
| 654 | .Float => try self.addFloat(ty, val), | ||
| 621 | .Bool => try self.addConstBool(val.toBool()), | 655 | .Bool => try self.addConstBool(val.toBool()), |
| 622 | .Array => switch (val.tag()) { | 656 | .Array => switch (val.tag()) { |
| 623 | .aggregate => { | 657 | .aggregate => { |
| ... | @@ -1690,6 +1724,9 @@ pub const DeclGen = struct { | ... | @@ -1690,6 +1724,9 @@ pub const DeclGen = struct { |
| 1690 | 1724 | ||
| 1691 | .bitcast => try self.airBitcast(inst), | 1725 | .bitcast => try self.airBitcast(inst), |
| 1692 | .intcast, .trunc => try self.airIntcast(inst), | 1726 | .intcast, .trunc => try self.airIntcast(inst), |
| 1727 | .ptrtoint => try self.airPtrToInt(inst), | ||
| 1728 | .int_to_float => try self.airIntToFloat(inst), | ||
| 1729 | .float_to_int => try self.airFloatToInt(inst), | ||
| 1693 | .not => try self.airNot(inst), | 1730 | .not => try self.airNot(inst), |
| 1694 | 1731 | ||
| 1695 | .slice_ptr => try self.airSliceField(inst, 0), | 1732 | .slice_ptr => try self.airSliceField(inst, 0), |
| ... | @@ -1750,10 +1787,12 @@ pub const DeclGen = struct { | ... | @@ -1750,10 +1787,12 @@ pub const DeclGen = struct { |
| 1750 | .call_never_tail => try self.airCall(inst, .never_tail), | 1787 | .call_never_tail => try self.airCall(inst, .never_tail), |
| 1751 | .call_never_inline => try self.airCall(inst, .never_inline), | 1788 | .call_never_inline => try self.airCall(inst, .never_inline), |
| 1752 | 1789 | ||
| 1753 | .dbg_var_ptr => return, | 1790 | .dbg_inline_begin => return, |
| 1754 | .dbg_var_val => return, | 1791 | .dbg_inline_end => return, |
| 1755 | .dbg_block_begin => return, | 1792 | .dbg_var_ptr => return, |
| 1756 | .dbg_block_end => return, | 1793 | .dbg_var_val => return, |
| 1794 | .dbg_block_begin => return, | ||
| 1795 | .dbg_block_end => return, | ||
| 1757 | // zig fmt: on | 1796 | // zig fmt: on |
| 1758 | 1797 | ||
| 1759 | else => |tag| return self.todo("implement AIR tag {s}", .{@tagName(tag)}), | 1798 | else => |tag| return self.todo("implement AIR tag {s}", .{@tagName(tag)}), |
| ... | @@ -2095,6 +2134,73 @@ pub const DeclGen = struct { | ... | @@ -2095,6 +2134,73 @@ pub const DeclGen = struct { |
| 2095 | return result_id; | 2134 | return result_id; |
| 2096 | } | 2135 | } |
| 2097 | 2136 | ||
| 2137 | fn airPtrToInt(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2138 | if (self.liveness.isUnused(inst)) return null; | ||
| 2139 | |||
| 2140 | const un_op = self.air.instructions.items(.data)[inst].un_op; | ||
| 2141 | const operand_id = try self.resolve(un_op); | ||
| 2142 | const result_type_id = try self.resolveTypeId(Type.usize); | ||
| 2143 | |||
| 2144 | const result_id = self.spv.allocId(); | ||
| 2145 | try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ | ||
| 2146 | .id_result_type = result_type_id, | ||
| 2147 | .id_result = result_id, | ||
| 2148 | .pointer = operand_id, | ||
| 2149 | }); | ||
| 2150 | return result_id; | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | fn airIntToFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2154 | if (self.liveness.isUnused(inst)) return null; | ||
| 2155 | |||
| 2156 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 2157 | const operand_ty = self.air.typeOf(ty_op.operand); | ||
| 2158 | const operand_id = try self.resolve(ty_op.operand); | ||
| 2159 | const operand_info = try self.arithmeticTypeInfo(operand_ty); | ||
| 2160 | const dest_ty = self.air.typeOfIndex(inst); | ||
| 2161 | const dest_ty_id = try self.resolveTypeId(dest_ty); | ||
| 2162 | |||
| 2163 | const result_id = self.spv.allocId(); | ||
| 2164 | switch (operand_info.signedness) { | ||
| 2165 | .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{ | ||
| 2166 | .id_result_type = dest_ty_id, | ||
| 2167 | .id_result = result_id, | ||
| 2168 | .signed_value = operand_id, | ||
| 2169 | }), | ||
| 2170 | .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{ | ||
| 2171 | .id_result_type = dest_ty_id, | ||
| 2172 | .id_result = result_id, | ||
| 2173 | .unsigned_value = operand_id, | ||
| 2174 | }), | ||
| 2175 | } | ||
| 2176 | return result_id; | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | fn airFloatToInt(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2180 | if (self.liveness.isUnused(inst)) return null; | ||
| 2181 | |||
| 2182 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 2183 | const operand_id = try self.resolve(ty_op.operand); | ||
| 2184 | const dest_ty = self.air.typeOfIndex(inst); | ||
| 2185 | const dest_info = try self.arithmeticTypeInfo(dest_ty); | ||
| 2186 | const dest_ty_id = try self.resolveTypeId(dest_ty); | ||
| 2187 | |||
| 2188 | const result_id = self.spv.allocId(); | ||
| 2189 | switch (dest_info.signedness) { | ||
| 2190 | .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{ | ||
| 2191 | .id_result_type = dest_ty_id, | ||
| 2192 | .id_result = result_id, | ||
| 2193 | .float_value = operand_id, | ||
| 2194 | }), | ||
| 2195 | .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{ | ||
| 2196 | .id_result_type = dest_ty_id, | ||
| 2197 | .id_result = result_id, | ||
| 2198 | .float_value = operand_id, | ||
| 2199 | }), | ||
| 2200 | } | ||
| 2201 | return result_id; | ||
| 2202 | } | ||
| 2203 | |||
| 2098 | fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2204 | fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2099 | if (self.liveness.isUnused(inst)) return null; | 2205 | if (self.liveness.isUnused(inst)) return null; |
| 2100 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2206 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
test/behavior/cast.zig-10| ... | @@ -97,7 +97,6 @@ test "@intToFloat" { | ... | @@ -97,7 +97,6 @@ test "@intToFloat" { |
| 97 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 97 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 98 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 98 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 99 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 99 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 100 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 101 | 100 | ||
| 102 | const S = struct { | 101 | const S = struct { |
| 103 | fn doTheTest() !void { | 102 | fn doTheTest() !void { |
| ... | @@ -155,7 +154,6 @@ test "@floatToInt" { | ... | @@ -155,7 +154,6 @@ test "@floatToInt" { |
| 155 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 154 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 156 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 155 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 157 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 156 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 158 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 159 | 157 | ||
| 160 | try testFloatToInts(); | 158 | try testFloatToInts(); |
| 161 | comptime try testFloatToInts(); | 159 | comptime try testFloatToInts(); |
| ... | @@ -207,16 +205,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { | ... | @@ -207,16 +205,12 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { |
| 207 | } | 205 | } |
| 208 | 206 | ||
| 209 | test "@intCast comptime_int" { | 207 | test "@intCast comptime_int" { |
| 210 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 211 | |||
| 212 | const result = @intCast(i32, 1234); | 208 | const result = @intCast(i32, 1234); |
| 213 | try expect(@TypeOf(result) == i32); | 209 | try expect(@TypeOf(result) == i32); |
| 214 | try expect(result == 1234); | 210 | try expect(result == 1234); |
| 215 | } | 211 | } |
| 216 | 212 | ||
| 217 | test "@floatCast comptime_int and comptime_float" { | 213 | test "@floatCast comptime_int and comptime_float" { |
| 218 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 219 | |||
| 220 | { | 214 | { |
| 221 | const result = @floatCast(f16, 1234); | 215 | const result = @floatCast(f16, 1234); |
| 222 | try expect(@TypeOf(result) == f16); | 216 | try expect(@TypeOf(result) == f16); |
| ... | @@ -1290,14 +1284,10 @@ test "implicit cast *[0]T to E![]const u8" { | ... | @@ -1290,14 +1284,10 @@ test "implicit cast *[0]T to E![]const u8" { |
| 1290 | 1284 | ||
| 1291 | var global_array: [4]u8 = undefined; | 1285 | var global_array: [4]u8 = undefined; |
| 1292 | test "cast from array reference to fn: comptime fn ptr" { | 1286 | test "cast from array reference to fn: comptime fn ptr" { |
| 1293 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1294 | |||
| 1295 | const f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); | 1287 | const f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); |
| 1296 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | 1288 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1297 | } | 1289 | } |
| 1298 | test "cast from array reference to fn: runtime fn ptr" { | 1290 | test "cast from array reference to fn: runtime fn ptr" { |
| 1299 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1300 | |||
| 1301 | var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); | 1291 | var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); |
| 1302 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | 1292 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1303 | } | 1293 | } |
test/behavior/enum.zig-5| ... | @@ -27,7 +27,6 @@ const IntToEnumNumber = enum { Zero, One, Two, Three, Four }; | ... | @@ -27,7 +27,6 @@ const IntToEnumNumber = enum { Zero, One, Two, Three, Four }; |
| 27 | test "int to enum" { | 27 | test "int to enum" { |
| 28 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 28 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 29 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 29 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 30 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 31 | 30 | ||
| 32 | try testIntToEnumEval(3); | 31 | try testIntToEnumEval(3); |
| 33 | } | 32 | } |
| ... | @@ -576,8 +575,6 @@ test "enum literal equality" { | ... | @@ -576,8 +575,6 @@ test "enum literal equality" { |
| 576 | } | 575 | } |
| 577 | 576 | ||
| 578 | test "enum literal cast to enum" { | 577 | test "enum literal cast to enum" { |
| 579 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 580 | |||
| 581 | const Color = enum { Auto, Off, On }; | 578 | const Color = enum { Auto, Off, On }; |
| 582 | 579 | ||
| 583 | var color1: Color = .Auto; | 580 | var color1: Color = .Auto; |
| ... | @@ -874,8 +871,6 @@ test "switch on enum with one member is comptime-known" { | ... | @@ -874,8 +871,6 @@ test "switch on enum with one member is comptime-known" { |
| 874 | } | 871 | } |
| 875 | 872 | ||
| 876 | test "method call on an enum" { | 873 | test "method call on an enum" { |
| 877 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 878 | |||
| 879 | const S = struct { | 874 | const S = struct { |
| 880 | const E = enum { | 875 | const E = enum { |
| 881 | one, | 876 | one, |
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" { |
| 916 | test "try used in recursive function with inferred error set" { | 916 | test "try used in recursive function with inferred error set" { |
| 917 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 917 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 918 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 918 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 919 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | ||
| 919 | 920 | ||
| 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; // TODO | 106 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 107 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 107 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 108 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 108 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 109 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 109 | 110 | ||
| 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" { |
| 186 | 186 | ||
| 187 | test "slicing pointer by length" { | 187 | test "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]; |
test/behavior/union.zig-1| ... | @@ -365,7 +365,6 @@ test "simple union(enum(u32))" { | ... | @@ -365,7 +365,6 @@ test "simple union(enum(u32))" { |
| 365 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 365 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 366 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 366 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 367 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 367 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 368 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 369 | 368 | ||
| 370 | var x = MultipleChoice.C; | 369 | var x = MultipleChoice.C; |
| 371 | try expect(x == MultipleChoice.C); | 370 | try expect(x == MultipleChoice.C); |