From 4e22f811e746ab5771ea7355ed8dfbfcda0420c2 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 23 Sep 2023 01:31:07 +0200 Subject: [PATCH 01/36] spirv: opaque types --- src/codegen/spirv.zig | 7 +++++++ src/codegen/spirv/Cache.zig | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index a4d3ec7f461f2d524a789a763c7d7e38bed63ea3..39dd1e6cb02fcf8a75f7138e0c612ee990a44647 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1215,6 +1215,13 @@ pub const DeclGen = struct { try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); return ty_ref; }, + .Opaque => { + return try self.spv.resolve(.{ + .opaque_type = .{ + .name = .none, // TODO + }, + }); + }, .Null, .Undefined, diff --git a/src/codegen/spirv/Cache.zig b/src/codegen/spirv/Cache.zig index 68fea5c47aa07ef021acf0a4dd7362926cda9e3b..7f5590344c6ee3b7bc7c75b5988f41b8843b8b92 100644 --- a/src/codegen/spirv/Cache.zig +++ b/src/codegen/spirv/Cache.zig @@ -81,6 +81,9 @@ const Tag = enum { /// have member names trailing. /// data is payload to SimpleStructType type_struct_simple_with_member_names, + /// Opaque type. + /// data is name string. + type_opaque, // -- Values /// Value of type u8 @@ -235,6 +238,7 @@ pub const Key = union(enum) { function_type: FunctionType, ptr_type: PointerType, struct_type: StructType, + opaque_type: OpaqueType, // -- values int: Int, @@ -289,6 +293,10 @@ pub const Key = union(enum) { } }; + pub const OpaqueType = struct { + name: String = .none, + }; + pub const Int = struct { /// The type: any bitness integer. ty: Ref, @@ -539,6 +547,13 @@ fn emit( } // TODO: Decorations? }, + .opaque_type => |opaque_type| { + const name = if (self.getString(opaque_type.name)) |name| name else ""; + try section.emit(spv.gpa, .OpTypeOpaque, .{ + .id_result = result_id, + .literal_string = name, + }); + }, .int => |int| { const int_type = self.lookup(int.ty).int_type; const ty_id = self.resultId(int.ty); @@ -697,6 +712,11 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { }; } }, + .opaque_type => |opaque_type| Item{ + .tag = .type_opaque, + .result_id = result_id, + .data = @intFromEnum(opaque_type.name), + }, .int => |int| blk: { const int_type = self.lookup(int.ty).int_type; if (int_type.signedness == .unsigned and int_type.bits == 8) { @@ -874,6 +894,11 @@ pub fn lookup(self: *const Self, ref: Ref) Key { }, }; }, + .type_opaque => .{ + .opaque_type = .{ + .name = @as(String, @enumFromInt(data)), + }, + }, .float16 => .{ .float = .{ .ty = self.get(.{ .float_type = .{ .bits = 16 } }), .value = .{ .float16 = @as(f16, @bitCast(@as(u16, @intCast(data)))) }, -- 2.54.0 From 4ea361f6dc07826337255fdddcbdfca9b8c9a0a9 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 23 Sep 2023 01:31:38 +0200 Subject: [PATCH 02/36] spirv: lower pointers to zero-bit types as undef --- src/codegen/spirv.zig | 133 +++++++++++++++++++++++------------------- src/link/SpirV.zig | 2 +- 2 files changed, 74 insertions(+), 61 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 39dd1e6cb02fcf8a75f7138e0c612ee990a44647..64850ad63f09afadd30be0a60fe4295731701661 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -521,59 +521,6 @@ pub const DeclGen = struct { return result_id; } - fn constructDeclRef(self: *DeclGen, ty: Type, decl_index: Decl.Index) !IdRef { - const mod = self.module; - const ty_ref = try self.resolveType(ty, .direct); - const ty_id = self.typeId(ty_ref); - const decl = mod.declPtr(decl_index); - const spv_decl_index = try self.resolveDecl(decl_index); - switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { - .func => { - // TODO: Properly lower function pointers. For now we are going to hack around it and - // just generate an empty pointer. Function pointers are represented by a pointer to usize. - // TODO: Add dependency - return try self.spv.constNull(ty_ref); - }, - .extern_func => unreachable, // TODO - else => { - const decl_id = self.spv.declPtr(spv_decl_index).result_id; - try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); - - const final_storage_class = spvStorageClass(decl.@"addrspace"); - - const decl_ty_ref = try self.resolveType(decl.ty, .indirect); - const decl_ptr_ty_ref = try self.spv.ptrType(decl_ty_ref, final_storage_class); - - const ptr_id = switch (final_storage_class) { - .Generic => blk: { - // Pointer should be Generic, but is actually placed in CrossWorkgroup. - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ - .id_result_type = self.typeId(decl_ptr_ty_ref), - .id_result = result_id, - .pointer = decl_id, - }); - break :blk result_id; - }, - else => decl_id, - }; - - if (decl_ptr_ty_ref != ty_ref) { - // Differing pointer types, insert a cast. - const casted_ptr_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ - .id_result_type = ty_id, - .id_result = casted_ptr_id, - .operand = ptr_id, - }); - return casted_ptr_id; - } else { - return ptr_id; - } - }, - } - } - /// This function generates a load for a constant in direct (ie, non-memory) representation. /// When the constant is simple, it can be generated directly using OpConstant instructions. /// When the constant is more complicated however, it needs to be constructed using multiple values. This @@ -796,7 +743,8 @@ pub const DeclGen = struct { return try self.constructStruct(result_ty_ref, constituents.items); }, - .vector_type, .anon_struct_type => unreachable, // TODO + .vector_type => unreachable, // TODO + .anon_struct_type => unreachable, // TODO else => unreachable, }, .un => |un| { @@ -817,9 +765,9 @@ pub const DeclGen = struct { const result_ty_ref = try self.resolveType(ptr_ty, .direct); const mod = self.module; switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { - .decl => |decl| return try self.constructDeclRef(ptr_ty, decl), + .decl => |decl| return try self.constantDeclRef(ptr_ty, decl), + .mut_decl => |decl_mut| return try self.constantDeclRef(ptr_ty, decl_mut.decl), .anon_decl => @panic("TODO"), - .mut_decl => |decl_mut| return try self.constructDeclRef(ptr_ty, decl_mut.decl), .int => |int| { const ptr_id = self.spv.allocId(); // TODO: This can probably be an OpSpecConstantOp Bitcast, but @@ -846,6 +794,65 @@ pub const DeclGen = struct { } } + fn constantDeclRef(self: *DeclGen, ty: Type, decl_index: Decl.Index) !IdRef { + const mod = self.module; + const ty_ref = try self.resolveType(ty, .direct); + const ty_id = self.typeId(ty_ref); + const decl = mod.declPtr(decl_index); + switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { + .func => { + // TODO: Properly lower function pointers. For now we are going to hack around it and + // just generate an empty pointer. Function pointers are represented by a pointer to usize. + // TODO: Add dependency + return try self.spv.constNull(ty_ref); + }, + .extern_func => unreachable, // TODO + else => {}, + } + + if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { + // Pointer to nothing - return undefined. + return self.spv.constUndef(ty_ref); + } + + const spv_decl_index = try self.resolveDecl(decl_index); + + const decl_id = self.spv.declPtr(spv_decl_index).result_id; + try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); + + const final_storage_class = spvStorageClass(decl.@"addrspace"); + + const decl_ty_ref = try self.resolveType(decl.ty, .indirect); + const decl_ptr_ty_ref = try self.spv.ptrType(decl_ty_ref, final_storage_class); + + const ptr_id = switch (final_storage_class) { + .Generic => blk: { + // Pointer should be Generic, but is actually placed in CrossWorkgroup. + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ + .id_result_type = self.typeId(decl_ptr_ty_ref), + .id_result = result_id, + .pointer = decl_id, + }); + break :blk result_id; + }, + else => decl_id, + }; + + if (decl_ptr_ty_ref != ty_ref) { + // Differing pointer types, insert a cast. + const casted_ptr_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ + .id_result_type = ty_id, + .id_result = casted_ptr_id, + .operand = ptr_id, + }); + return casted_ptr_id; + } else { + return ptr_id; + } + } + // Turn a Zig type's name into a cache reference. fn resolveTypeName(self: *DeclGen, ty: Type) !CacheString { var name = std.ArrayList(u8).init(self.gpa); @@ -1126,10 +1133,16 @@ pub const DeclGen = struct { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { - const field_ty = struct_type.field_types.get(ip)[field_index]; - const field_name = ip.stringToSlice(struct_type.field_names.get(ip)[field_index]); - try member_types.append(try self.resolveType(field_ty.toType(), .indirect)); - try member_names.append(try self.spv.resolveString(field_name)); + const field_ty = struct_type.field_types.get(ip)[field_index].toType(); + if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { + // This is a zero-bit field - we only needed it for the alignment. + continue; + } + + const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse + try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index}); + try member_types.append(try self.resolveType(field_ty, .indirect)); + try member_names.append(try self.spv.resolveString(ip.stringToSlice(field_name))); } const ty_ref = try self.spv.resolve(.{ .struct_type = .{ diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index d3906a13d7303938ede32c38d902ab2d19c3311d..e3efc0f67102c8c04710188662946ed8783d7298 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -217,7 +217,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { // TODO: Integrate with a hypothetical feature system const caps: []const spec.Capability = switch (target.os.tag) { - .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .GenericPointer }, + .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .GenericPointer }, .glsl450 => &.{.Shader}, .vulkan => &.{.Shader}, else => unreachable, // TODO -- 2.54.0 From a7c3d5e4ec551e48166919ab55f618afe7c23b2a Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 23 Sep 2023 01:46:00 +0200 Subject: [PATCH 03/36] spirv: constant elem ptr fix --- src/codegen/spirv.zig | 7 ++++--- test/behavior/slice.zig | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 64850ad63f09afadd30be0a60fe4295731701661..8a3745edb2069dc102c8022bbd5cac5bbfcf4c8f 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -784,11 +784,12 @@ pub const DeclGen = struct { .opt_payload => unreachable, // TODO .comptime_field => unreachable, .elem => |elem_ptr| { - const elem_ptr_ty = mod.intern_pool.typeOf(elem_ptr.base).toType(); - const parent_ptr_id = try self.constantPtr(elem_ptr_ty, elem_ptr.base.toValue()); + const parent_ptr_ty = mod.intern_pool.typeOf(elem_ptr.base).toType(); + const parent_ptr_id = try self.constantPtr(parent_ptr_ty, elem_ptr.base.toValue()); const size_ty_ref = try self.sizeType(); const index_id = try self.constInt(size_ty_ref, elem_ptr.index); - return self.ptrAccessChain(result_ty_ref, parent_ptr_id, index_id, &.{}); + + return try self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); }, .field => unreachable, // TODO } diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 9f430a105ae701541e278665fd555a6d9b78c518..0ebdffd16c65e5998a159afdf6d2b5c081c7f53c 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -219,7 +219,6 @@ test "slice string literal has correct type" { test "result location zero sized array inside struct field implicit cast to slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const E = struct { entries: []u32, -- 2.54.0 From 08ea9a9ff6962c40eb87ab4951bc07a05b3831c9 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Tue, 26 Sep 2023 23:15:59 +0200 Subject: [PATCH 04/36] spirv: cast result of .elem pointers to right type if needed --- src/codegen/spirv.zig | 20 +++++++++++++++++++- test/behavior/slice.zig | 3 +-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 8a3745edb2069dc102c8022bbd5cac5bbfcf4c8f..b2aab968e97e71d84359c7820b7f03ce1a4c6eb2 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -789,7 +789,25 @@ pub const DeclGen = struct { const size_ty_ref = try self.sizeType(); const index_id = try self.constInt(size_ty_ref, elem_ptr.index); - return try self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); + const elem_ptr_id = try self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); + + // TODO: Can we consolidate this in ptrElemPtr? + const elem_ty = parent_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. + const elem_ty_ref = try self.resolveType(elem_ty, .direct); + const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod))); + + if (elem_ptr_ty_ref == result_ty_ref) { + return elem_ptr_id; + } + // This may happen when we have pointer-to-array and the result is + // another pointer-to-array instead of a pointer-to-element. + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ + .id_result_type = self.typeId(result_ty_ref), + .id_result = result_id, + .operand = elem_ptr_id, + }); + return result_id; }, .field => unreachable, // TODO } diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 0ebdffd16c65e5998a159afdf6d2b5c081c7f53c..8049abb8dd21bc13ce8f60904ad2b5619b4a30a7 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -183,8 +183,6 @@ test "slicing zero length array" { } test "slicing pointer by length" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; const ptr: [*]const u8 = @as([*]const u8, @ptrCast(&array)); const slice = ptr[1..][0..5]; @@ -620,6 +618,7 @@ test "type coercion of pointer to anon struct literal to pointer to slice" { 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 { const U = union { -- 2.54.0 From ab701c3d375b102bc291f80a791109cb109964ba Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 14:21:59 +0200 Subject: [PATCH 05/36] spirv: anon decl refs --- src/codegen/llvm.zig | 1 + src/codegen/spirv.zig | 160 +++++++++++++++++++++++++++++++++++++++++- src/link/SpirV.zig | 7 +- 3 files changed, 163 insertions(+), 5 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e18ffece3d1f47aceee9ab4030ed6711e5771ead..cddd4340d70643825b32fe8f818d38c5ae85edce 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3050,6 +3050,7 @@ pub const Object = struct { decl_val: InternPool.Index, llvm_addr_space: Builder.AddrSpace, ) Error!Builder.Variable.Index { + // TODO: Add address space to the anon_decl_map const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val); if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable; errdefer assert(o.anon_decl_map.remove(decl_val)); diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index b2aab968e97e71d84359c7820b7f03ce1a4c6eb2..adb9155cfd983215e59468500f892f237f713c36 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -52,9 +52,12 @@ const Block = struct { const BlockMap = std.AutoHashMapUnmanaged(Air.Inst.Index, *Block); -/// Maps Zig decl indices to linking SPIR-V linking information. +/// Maps Zig decl indices to SPIR-V linking information. pub const DeclLinkMap = std.AutoHashMap(Module.Decl.Index, SpvModule.Decl.Index); +/// Maps anon decl indices to SPIR-V linking information. +pub const AnonDeclLinkMap = std.AutoHashMap(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index); + /// This structure is used to compile a declaration, and contains all relevant meta-information to deal with that. pub const DeclGen = struct { /// A general-purpose allocator that can be used for any allocations for this DeclGen. @@ -77,9 +80,12 @@ pub const DeclGen = struct { /// Note: If the declaration is not a function, this value will be undefined! liveness: Liveness, - /// Maps Zig Decl indices to SPIR-V globals. + /// Maps Zig Decl indices to SPIR-V decl indices. decl_link: *DeclLinkMap, + /// Maps Zig anon decl indices to SPIR-V decl indices. + anon_decl_link: *AnonDeclLinkMap, + /// An array of function argument result-ids. Each index corresponds with the /// function argument of the same index. args: std.ArrayListUnmanaged(IdRef) = .{}, @@ -182,6 +188,7 @@ pub const DeclGen = struct { module: *Module, spv: *SpvModule, decl_link: *DeclLinkMap, + anon_decl_link: *AnonDeclLinkMap, ) DeclGen { return .{ .gpa = allocator, @@ -191,6 +198,7 @@ pub const DeclGen = struct { .air = undefined, .liveness = undefined, .decl_link = decl_link, + .anon_decl_link = anon_decl_link, .next_arg_index = undefined, .current_block_label_id = undefined, .error_msg = undefined, @@ -301,6 +309,89 @@ pub const DeclGen = struct { return entry.value_ptr.*; } + fn resolveAnonDecl(self: *DeclGen, val: InternPool.Index, storage_class: StorageClass) !IdRef { + // TODO: This cannot be a function at this point, but it should probably be handled anyway. + const spv_decl_index = blk: { + const entry = try self.anon_decl_link.getOrPut(.{ val, storage_class }); + if (entry.found_existing) { + try self.func.decl_deps.put(self.spv.gpa, entry.value_ptr.*, {}); + return self.spv.declPtr(entry.value_ptr.*).result_id; + } + + const spv_decl_index = try self.spv.allocDecl(.global); + try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); + entry.value_ptr.* = spv_decl_index; + break :blk spv_decl_index; + }; + + const mod = self.module; + const ty = mod.intern_pool.typeOf(val).toType(); + const ty_ref = try self.resolveType(ty, .indirect); + const ptr_ty_ref = try self.spv.ptrType(ty_ref, storage_class); + + const var_id = self.spv.declPtr(spv_decl_index).result_id; + + const section = &self.spv.sections.types_globals_constants; + try section.emit(self.spv.gpa, .OpVariable, .{ + .id_result_type = self.typeId(ptr_ty_ref), + .id_result = var_id, + .storage_class = storage_class, + }); + + // TODO: At some point we will be able to generate this all constant here, but then all of + // constant() will need to be implemented such that it doesn't generate any at-runtime code. + // NOTE: Because this is a global, we really only want to initialize it once. Therefore the + // constant lowering of this value will need to be deferred to some other function, which + // is then added to the list of initializers using endGlobal(). + + // Save the current state so that we can temporarily generate into a different function. + // TODO: This should probably be made a little more robust. + const func = self.func; + defer self.func = func; + const block_label_id = self.current_block_label_id; + defer self.current_block_label_id = block_label_id; + + self.func = .{}; + + // TODO: Merge this with genDecl? + const begin = self.spv.beginGlobal(); + + const void_ty_ref = try self.resolveType(Type.void, .direct); + const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ + .return_type = void_ty_ref, + .parameters = &.{}, + } }); + + const initializer_id = self.spv.allocId(); + try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ + .id_result_type = self.typeId(void_ty_ref), + .id_result = initializer_id, + .function_control = .{}, + .function_type = self.typeId(initializer_proto_ty_ref), + }); + const root_block_id = self.spv.allocId(); + try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ + .id_result = root_block_id, + }); + self.current_block_label_id = root_block_id; + + const val_id = try self.constant(ty, val.toValue(), .indirect); + try self.func.body.emit(self.spv.gpa, .OpStore, .{ + .pointer = var_id, + .object = val_id, + }); + + self.spv.endGlobal(spv_decl_index, begin, var_id, initializer_id); + try self.func.body.emit(self.spv.gpa, .OpReturn, {}); + try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); + try self.spv.addFunction(spv_decl_index, self.func); + + try self.spv.debugNameFmt(var_id, "__anon_{d}", .{@intFromEnum(val)}); + try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); + + return var_id; + } + /// Start a new SPIR-V block, Emits the label of the new block, and stores which /// block we are currently generating. /// Note that there is no such thing as nested blocks like in ZIR or AIR, so we don't need to @@ -767,7 +858,7 @@ pub const DeclGen = struct { switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { .decl => |decl| return try self.constantDeclRef(ptr_ty, decl), .mut_decl => |decl_mut| return try self.constantDeclRef(ptr_ty, decl_mut.decl), - .anon_decl => @panic("TODO"), + .anon_decl => |anon_decl| return try self.constantAnonDeclRef(ptr_ty, anon_decl), .int => |int| { const ptr_id = self.spv.allocId(); // TODO: This can probably be an OpSpecConstantOp Bitcast, but @@ -813,6 +904,69 @@ pub const DeclGen = struct { } } + fn constantAnonDeclRef(self: *DeclGen, ty: Type, decl_val: InternPool.Index) !IdRef { + // TODO: Merge this function with constantDeclRef. + + const mod = self.module; + const ip = &mod.intern_pool; + const ty_ref = try self.resolveType(ty, .direct); + const decl_ty = ip.typeOf(decl_val).toType(); + + if (decl_val.toValue().getFunction(mod)) |func| { + _ = func; + unreachable; // TODO + } else if (decl_val.toValue().getExternFunc(mod)) |func| { + _ = func; + unreachable; + } + + // const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; + if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { + // Pointer to nothing - return undefoined + return self.spv.constUndef(ty_ref); + } + + if (decl_ty.zigTypeTag(mod) == .Fn) { + unreachable; // TODO + } + + const final_storage_class = spvStorageClass(ty.ptrAddressSpace(mod)); + const actual_storage_class = switch (final_storage_class) { + .Generic => .CrossWorkgroup, + else => |other| other, + }; + + const decl_id = try self.resolveAnonDecl(decl_val, actual_storage_class); + const decl_ty_ref = try self.resolveType(decl_ty, .indirect); + const decl_ptr_ty_ref = try self.spv.ptrType(decl_ty_ref, final_storage_class); + + const ptr_id = switch (final_storage_class) { + .Generic => blk: { + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ + .id_result_type = self.typeId(decl_ptr_ty_ref), + .id_result = result_id, + .pointer = decl_id, + }); + break :blk result_id; + }, + else => decl_id, + }; + + if (decl_ptr_ty_ref != ty_ref) { + // Differing pointer types, insert a cast. + const casted_ptr_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ + .id_result_type = self.typeId(ty_ref), + .id_result = casted_ptr_id, + .operand = ptr_id, + }); + return casted_ptr_id; + } else { + return ptr_id; + } + } + fn constantDeclRef(self: *DeclGen, ty: Type, decl_index: Decl.Index) !IdRef { const mod = self.module; const ty_ref = try self.resolveType(ty, .direct); diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index e3efc0f67102c8c04710188662946ed8783d7298..89aec81578c71a1e097e4b831a380e44ccbd7b84 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -48,6 +48,7 @@ base: link.File, spv: SpvModule, spv_arena: ArenaAllocator, decl_link: codegen.DeclLinkMap, +anon_decl_link: codegen.AnonDeclLinkMap, pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { const self = try gpa.create(SpirV); @@ -61,6 +62,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { .spv = undefined, .spv_arena = ArenaAllocator.init(gpa), .decl_link = codegen.DeclLinkMap.init(self.base.allocator), + .anon_decl_link = codegen.AnonDeclLinkMap.init(self.base.allocator), }; self.spv = SpvModule.init(gpa, self.spv_arena.allocator()); errdefer self.deinit(); @@ -102,6 +104,7 @@ pub fn deinit(self: *SpirV) void { self.spv.deinit(); self.spv_arena.deinit(); self.decl_link.deinit(); + self.anon_decl_link.deinit(); } pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { @@ -113,7 +116,7 @@ pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, a const decl = module.declPtr(func.owner_decl); log.debug("lowering function {s}", .{module.intern_pool.stringToSlice(decl.name)}); - var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link); + var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link, &self.anon_decl_link); defer decl_gen.deinit(); if (try decl_gen.gen(func.owner_decl, air, liveness)) |msg| { @@ -129,7 +132,7 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index) const decl = module.declPtr(decl_index); log.debug("lowering declaration {s}", .{module.intern_pool.stringToSlice(decl.name)}); - var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link); + var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link, &self.anon_decl_link); defer decl_gen.deinit(); if (try decl_gen.gen(decl_index, undefined, undefined)) |msg| { -- 2.54.0 From a3d77bdba9f8c6c3a88cfdfc009e1fabff22d2eb Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 15:10:17 +0200 Subject: [PATCH 06/36] spirv: get rid of SpvModule arena --- src/codegen/spirv/Module.zig | 12 ++++-------- src/link/SpirV.zig | 9 ++++----- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index 81b97ebae5310dc12ab0decee9958e959167b0ca..2aacc5b748a727530880426aed897d1a9a8f5400 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -103,15 +103,12 @@ pub const EntryPoint = struct { /// The declaration that should be exported. decl_index: Decl.Index, /// The name of the kernel to be exported. - name: []const u8, + name: CacheString, }; /// A general-purpose allocator which may be used to allocate resources for this module gpa: Allocator, -/// An arena allocator used to store things that have the same lifetime as this module. -arena: Allocator, - /// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module". sections: struct { /// Capability instructions @@ -176,10 +173,9 @@ globals: struct { section: Section = .{}, } = .{}, -pub fn init(gpa: Allocator, arena: Allocator) Module { +pub fn init(gpa: Allocator) Module { return .{ .gpa = gpa, - .arena = arena, .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1. }; } @@ -321,7 +317,7 @@ fn entryPoints(self: *Module) !Section { try entry_points.emit(self.gpa, .OpEntryPoint, .{ .execution_model = .Kernel, .entry_point = entry_point_id, - .name = entry_point.name, + .name = self.cache.getString(entry_point.name).?, .interface = interface.items, }); } @@ -641,7 +637,7 @@ pub fn endGlobal(self: *Module, global_index: Decl.Index, begin_inst: u32, resul pub fn declareEntryPoint(self: *Module, decl_index: Decl.Index, name: []const u8) !void { try self.entry_points.append(self.gpa, .{ .decl_index = decl_index, - .name = try self.arena.dupe(u8, name), + .name = try self.resolveString(name), }); } diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 89aec81578c71a1e097e4b831a380e44ccbd7b84..f22fe13467a4fd26f268a6480228eef95251339c 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -46,7 +46,6 @@ const IdResult = spec.IdResult; base: link.File, spv: SpvModule, -spv_arena: ArenaAllocator, decl_link: codegen.DeclLinkMap, anon_decl_link: codegen.AnonDeclLinkMap, @@ -60,11 +59,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { .allocator = gpa, }, .spv = undefined, - .spv_arena = ArenaAllocator.init(gpa), .decl_link = codegen.DeclLinkMap.init(self.base.allocator), .anon_decl_link = codegen.AnonDeclLinkMap.init(self.base.allocator), }; - self.spv = SpvModule.init(gpa, self.spv_arena.allocator()); + self.spv = SpvModule.init(gpa); errdefer self.deinit(); // TODO: Figure out where to put all of these @@ -102,7 +100,6 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option pub fn deinit(self: *SpirV) void { self.spv.deinit(); - self.spv_arena.deinit(); self.decl_link.deinit(); self.anon_decl_link.deinit(); } @@ -196,7 +193,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No // executor. This is not really an important thing though, so we can just dump it in any old // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name. - var error_info = std.ArrayList(u8).init(self.spv.arena); + var error_info = std.ArrayList(u8).init(self.spv.gpa); + defer error_info.deinit(); + try error_info.appendSlice("zig_errors"); const module = self.base.options.module.?; for (module.global_error_set.keys()) |name_nts| { -- 2.54.0 From 31ad2d72a756b837b153ae63dfc0e6df608033b4 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 15:23:39 +0200 Subject: [PATCH 07/36] spirv: use CacheString for source_file_names instead of []const u8 --- src/codegen/spirv.zig | 8 ++++---- src/codegen/spirv/Module.zig | 11 ++++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index adb9155cfd983215e59468500f892f237f713c36..93ae552b10378a60b2df30dafccdad5a285fc4b6 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -3726,10 +3726,10 @@ pub const DeclGen = struct { fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void { const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; - const src_fname_id = try self.spv.resolveSourceFileName( - self.module, - self.module.declPtr(self.decl_index), - ); + const mod = self.module; + const decl = mod.declPtr(self.decl_index); + const path = decl.getFileScope(mod).sub_file_path; + const src_fname_id = try self.spv.resolveSourceFileName(path); const base_line = self.base_line_stack.getLast(); try self.func.body.emit(self.spv.gpa, .OpLine, .{ .file = src_fname_id, diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index 2aacc5b748a727530880426aed897d1a9a8f5400..c16e1a6d72d746656d8fa07f95bcf8272cc92628 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -11,9 +11,6 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const ZigModule = @import("../../Module.zig"); -const ZigDecl = ZigModule.Decl; - const spec = @import("spec.zig"); const Word = spec.Word; const IdRef = spec.IdRef; @@ -147,7 +144,7 @@ next_result_id: Word, /// Cache for results of OpString instructions for module file names fed to OpSource. /// Since OpString is pretty much only used for those, we don't need to keep track of all strings, /// just the ones for OpLine. Note that OpLine needs the result of OpString, and not that of OpSource. -source_file_names: std.StringHashMapUnmanaged(IdRef) = .{}, +source_file_names: std.AutoArrayHashMapUnmanaged(CacheString, IdRef) = .{}, /// SPIR-V type- and constant cache. This structure is used to store information about these in a more /// efficient manner. @@ -460,9 +457,9 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void { /// Fetch the result-id of an OpString instruction that encodes the path of the source /// file of the decl. This function may also emit an OpSource with source-level information regarding /// the decl. -pub fn resolveSourceFileName(self: *Module, zig_module: *ZigModule, zig_decl: *ZigDecl) !IdRef { - const path = zig_decl.getFileScope(zig_module).sub_file_path; - const result = try self.source_file_names.getOrPut(self.gpa, path); +pub fn resolveSourceFileName(self: *Module, path: []const u8) !IdRef { + const path_ref = try self.resolveString(path); + const result = try self.source_file_names.getOrPut(self.gpa, path_ref); if (!result.found_existing) { const file_result_id = self.allocId(); result.value_ptr.* = file_result_id; -- 2.54.0 From 28dda3bf898cc338eb0040f3f21799eda1e25be0 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 18:10:35 +0200 Subject: [PATCH 08/36] spirv: put linkery bits in Object This structure is used to group information that needs to persist between decls in codegen. --- src/codegen/spirv.zig | 234 ++++++++++++++++++++++++------------------ src/link/SpirV.zig | 49 +++------ 2 files changed, 147 insertions(+), 136 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 93ae552b10378a60b2df30dafccdad5a285fc4b6..3a751fed6875519e3725cb1de03c2c48b45e0e87 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -53,20 +53,141 @@ const Block = struct { const BlockMap = std.AutoHashMapUnmanaged(Air.Inst.Index, *Block); /// Maps Zig decl indices to SPIR-V linking information. -pub const DeclLinkMap = std.AutoHashMap(Module.Decl.Index, SpvModule.Decl.Index); +pub const DeclLinkMap = std.AutoHashMapUnmanaged(Decl.Index, SpvModule.Decl.Index); /// Maps anon decl indices to SPIR-V linking information. -pub const AnonDeclLinkMap = std.AutoHashMap(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index); +pub const AnonDeclLinkMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index); + +/// This structure holds information that is relevant to the entire compilation, +/// in contrast to `DeclGen`, which only holds relevant information about a +/// single decl. +pub const Object = struct { + /// A general-purpose allocator that can be used for any allocation for this Object. + gpa: Allocator, + + /// the SPIR-V module that represents the final binary. + spv: SpvModule, + + /// The Zig module that this object file is generated for. + /// A map of Zig decl indices to SPIR-V decl indices. + decl_link: DeclLinkMap = .{}, + + /// A map of Zig InternPool indices for anonymous decls to SPIR-V decl indices. + anon_decl_link: AnonDeclLinkMap = .{}, + + /// A map that maps AIR intern pool indices to SPIR-V cache references (which + /// is basically the same thing except for SPIR-V). + /// This map is typically only used for structures that are deemed heavy enough + /// that it is worth to store them here. The SPIR-V module also interns types, + /// and so the main purpose of this map is to avoid recomputation and to + /// cache extra information about the type rather than to aid in validity + /// of the SPIR-V module. + type_map: TypeMap = .{}, + + pub fn init(gpa: Allocator) Object { + return .{ + .gpa = gpa, + .spv = SpvModule.init(gpa), + }; + } + + pub fn deinit(self: *Object) void { + self.spv.deinit(); + self.decl_link.deinit(self.gpa); + self.anon_decl_link.deinit(self.gpa); + self.type_map.deinit(self.gpa); + } + + fn genDecl( + self: *Object, + mod: *Module, + decl_index: Decl.Index, + air: Air, + liveness: Liveness, + ) !void { + var decl_gen = DeclGen{ + .gpa = self.gpa, + .object = self, + .module = mod, + .spv = &self.spv, + .decl_index = decl_index, + .air = air, + .liveness = liveness, + .type_map = &self.type_map, + .current_block_label_id = undefined, + }; + defer decl_gen.deinit(); + + decl_gen.genDecl() catch |err| switch (err) { + error.CodegenFail => { + try mod.failed_decls.put(mod.gpa, decl_index, decl_gen.error_msg.?); + }, + else => |other| { + // There might be an error that happened *after* self.error_msg + // was already allocated, so be sure to free it. + if (decl_gen.error_msg) |error_msg| { + error_msg.deinit(mod.gpa); + } + + return other; + }, + }; + } + + pub fn updateFunc( + self: *Object, + mod: *Module, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, + ) !void { + const decl_index = mod.funcInfo(func_index).owner_decl; + // TODO: Separate types for generating decls and functions? + try self.genDecl(mod, decl_index, air, liveness); + } + + pub fn updateDecl( + self: *Object, + mod: *Module, + decl_index: Decl.Index, + ) !void { + try self.genDecl(mod, decl_index, undefined, undefined); + } + + /// Fetch or allocate a result id for decl index. This function also marks the decl as alive. + /// Note: Function does not actually generate the decl, it just allocates an index. + pub fn resolveDecl(self: *Object, mod: *Module, decl_index: Decl.Index) !SpvModule.Decl.Index { + const decl = mod.declPtr(decl_index); + try mod.markDeclAlive(decl); + + const entry = try self.decl_link.getOrPut(self.gpa, decl_index); + if (!entry.found_existing) { + // TODO: Extern fn? + const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod)) + .func + else + .global; + + entry.value_ptr.* = try self.spv.allocDecl(kind); + } + + return entry.value_ptr.*; + } +}; /// This structure is used to compile a declaration, and contains all relevant meta-information to deal with that. -pub const DeclGen = struct { +const DeclGen = struct { /// A general-purpose allocator that can be used for any allocations for this DeclGen. gpa: Allocator, + /// The object that this decl is generated into. + object: *Object, + /// The Zig module that we are generating decls for. module: *Module, /// The SPIR-V module that instructions should be emitted into. + /// This is the same as `self.object.spv`, repeated here for brevity. spv: *SpvModule, /// The decl we are currently generating code for. @@ -80,30 +201,19 @@ pub const DeclGen = struct { /// Note: If the declaration is not a function, this value will be undefined! liveness: Liveness, - /// Maps Zig Decl indices to SPIR-V decl indices. - decl_link: *DeclLinkMap, - - /// Maps Zig anon decl indices to SPIR-V decl indices. - anon_decl_link: *AnonDeclLinkMap, - /// An array of function argument result-ids. Each index corresponds with the /// function argument of the same index. args: std.ArrayListUnmanaged(IdRef) = .{}, /// A counter to keep track of how many `arg` instructions we've seen yet. - next_arg_index: u32, + next_arg_index: u32 = 0, /// A map keeping track of which instruction generated which result-id. inst_results: InstMap = .{}, - /// A map that maps AIR intern pool indices to SPIR-V cache references (which - /// is basically the same thing except for SPIR-V). - /// This map is typically only used for structures that are deemed heavy enough - /// that it is worth to store them here. The SPIR-V module also interns types, - /// and so the main purpose of this map is to avoid recomputation and to - /// cache extra information about the type rather than to aid in validity - /// of the SPIR-V module. - type_map: TypeMap = .{}, + /// A map that maps AIR intern pool indices to SPIR-V cache references. + /// See Object.type_map + type_map: *TypeMap, /// We need to keep track of result ids for block labels, as well as the 'incoming' /// blocks for a block. @@ -121,7 +231,7 @@ pub const DeclGen = struct { /// If `gen` returned `Error.CodegenFail`, this contains an explanatory message. /// Memory is owned by `module.gpa`. - error_msg: ?*Module.ErrorMsg, + error_msg: ?*Module.ErrorMsg = null, /// Possible errors the `genDecl` function may return. const Error = error{ CodegenFail, OutOfMemory }; @@ -181,67 +291,10 @@ pub const DeclGen = struct { indirect, }; - /// Initialize the common resources of a DeclGen. Some fields are left uninitialized, - /// only set when `gen` is called. - pub fn init( - allocator: Allocator, - module: *Module, - spv: *SpvModule, - decl_link: *DeclLinkMap, - anon_decl_link: *AnonDeclLinkMap, - ) DeclGen { - return .{ - .gpa = allocator, - .module = module, - .spv = spv, - .decl_index = undefined, - .air = undefined, - .liveness = undefined, - .decl_link = decl_link, - .anon_decl_link = anon_decl_link, - .next_arg_index = undefined, - .current_block_label_id = undefined, - .error_msg = undefined, - }; - } - - /// Generate the code for `decl`. If a reportable error occurred during code generation, - /// a message is returned by this function. Callee owns the memory. If this function - /// returns such a reportable error, it is valid to be called again for a different decl. - pub fn gen(self: *DeclGen, decl_index: Decl.Index, air: Air, liveness: Liveness) !?*Module.ErrorMsg { - // Reset internal resources, we don't want to re-allocate these. - self.decl_index = decl_index; - self.air = air; - self.liveness = liveness; - self.args.items.len = 0; - self.next_arg_index = 0; - self.inst_results.clearRetainingCapacity(); - self.blocks.clearRetainingCapacity(); - self.current_block_label_id = undefined; - self.func.reset(); - self.base_line_stack.items.len = 0; - self.error_msg = null; - - self.genDecl() catch |err| switch (err) { - error.CodegenFail => return self.error_msg, - else => |others| { - // There might be an error that happened *after* self.error_msg - // was already allocated, so be sure to free it. - if (self.error_msg) |error_msg| { - error_msg.deinit(self.module.gpa); - } - return others; - }, - }; - - return null; - } - /// Free resources owned by the DeclGen. pub fn deinit(self: *DeclGen) void { self.args.deinit(self.gpa); self.inst_results.deinit(self.gpa); - self.type_map.deinit(self.gpa); self.blocks.deinit(self.gpa); self.func.deinit(self.gpa); self.base_line_stack.deinit(self.gpa); @@ -277,7 +330,7 @@ pub const DeclGen = struct { .func => |func| func.owner_decl, else => unreachable, }; - const spv_decl_index = try self.resolveDecl(fn_decl_index); + const spv_decl_index = try self.object.resolveDecl(mod, fn_decl_index); try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); return self.spv.declPtr(spv_decl_index).result_id; } @@ -288,31 +341,10 @@ pub const DeclGen = struct { return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. } - /// Fetch or allocate a result id for decl index. This function also marks the decl as alive. - /// Note: Function does not actually generate the decl. - fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index { - const mod = self.module; - const decl = mod.declPtr(decl_index); - try mod.markDeclAlive(decl); - - const entry = try self.decl_link.getOrPut(decl_index); - if (!entry.found_existing) { - // TODO: Extern fn? - const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod)) - .func - else - .global; - - entry.value_ptr.* = try self.spv.allocDecl(kind); - } - - return entry.value_ptr.*; - } - fn resolveAnonDecl(self: *DeclGen, val: InternPool.Index, storage_class: StorageClass) !IdRef { // TODO: This cannot be a function at this point, but it should probably be handled anyway. const spv_decl_index = blk: { - const entry = try self.anon_decl_link.getOrPut(.{ val, storage_class }); + const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, storage_class }); if (entry.found_existing) { try self.func.decl_deps.put(self.spv.gpa, entry.value_ptr.*, {}); return self.spv.declPtr(entry.value_ptr.*).result_id; @@ -988,7 +1020,7 @@ pub const DeclGen = struct { return self.spv.constUndef(ty_ref); } - const spv_decl_index = try self.resolveDecl(decl_index); + const spv_decl_index = try self.object.resolveDecl(mod, decl_index); const decl_id = self.spv.declPtr(spv_decl_index).result_id; try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); @@ -1624,7 +1656,7 @@ pub const DeclGen = struct { const mod = self.module; const ip = &mod.intern_pool; const decl = mod.declPtr(self.decl_index); - const spv_decl_index = try self.resolveDecl(self.decl_index); + const spv_decl_index = try self.object.resolveDecl(mod, self.decl_index); const decl_id = self.spv.declPtr(spv_decl_index).result_id; diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index f22fe13467a4fd26f268a6480228eef95251339c..58d8ca684173c1b6a016e9d2d234b50a6b38cd72 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -45,9 +45,7 @@ const IdResult = spec.IdResult; base: link.File, -spv: SpvModule, -decl_link: codegen.DeclLinkMap, -anon_decl_link: codegen.AnonDeclLinkMap, +object: codegen.Object, pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { const self = try gpa.create(SpirV); @@ -58,11 +56,8 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { .file = null, .allocator = gpa, }, - .spv = undefined, - .decl_link = codegen.DeclLinkMap.init(self.base.allocator), - .anon_decl_link = codegen.AnonDeclLinkMap.init(self.base.allocator), + .object = codegen.Object.init(gpa), }; - self.spv = SpvModule.init(gpa); errdefer self.deinit(); // TODO: Figure out where to put all of these @@ -99,9 +94,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option } pub fn deinit(self: *SpirV) void { - self.spv.deinit(); - self.decl_link.deinit(); - self.anon_decl_link.deinit(); + self.object.deinit(); } pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { @@ -113,12 +106,7 @@ pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, a const decl = module.declPtr(func.owner_decl); log.debug("lowering function {s}", .{module.intern_pool.stringToSlice(decl.name)}); - var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link, &self.anon_decl_link); - defer decl_gen.deinit(); - - if (try decl_gen.gen(func.owner_decl, air, liveness)) |msg| { - try module.failed_decls.put(module.gpa, func.owner_decl, msg); - } + try self.object.updateFunc(module, func_index, air, liveness); } pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index) !void { @@ -129,12 +117,7 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index) const decl = module.declPtr(decl_index); log.debug("lowering declaration {s}", .{module.intern_pool.stringToSlice(decl.name)}); - var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link, &self.anon_decl_link); - defer decl_gen.deinit(); - - if (try decl_gen.gen(decl_index, undefined, undefined)) |msg| { - try module.failed_decls.put(module.gpa, decl_index, msg); - } + try self.object.updateDecl(module, decl_index); } pub fn updateDeclExports( @@ -145,15 +128,9 @@ pub fn updateDeclExports( ) !void { const decl = mod.declPtr(decl_index); if (decl.val.isFuncBody(mod) and decl.ty.fnCallingConvention(mod) == .Kernel) { - // TODO: Unify with resolveDecl in spirv.zig. - const entry = try self.decl_link.getOrPut(decl_index); - if (!entry.found_existing) { - entry.value_ptr.* = try self.spv.allocDecl(.func); - } - const spv_decl_index = entry.value_ptr.*; - + const spv_decl_index = try self.object.resolveDecl(mod, decl_index); for (exports) |exp| { - try self.spv.declareEntryPoint(spv_decl_index, mod.intern_pool.stringToSlice(exp.opts.name)); + try self.object.spv.declareEntryPoint(spv_decl_index, mod.intern_pool.stringToSlice(exp.opts.name)); } } @@ -185,15 +162,17 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No sub_prog_node.activate(); defer sub_prog_node.end(); + const spv = &self.object.spv; + const target = comp.getTarget(); - try writeCapabilities(&self.spv, target); - try writeMemoryModel(&self.spv, target); + try writeCapabilities(spv, target); + try writeMemoryModel(spv, target); // We need to export the list of error names somewhere so that we can pretty-print them in the // executor. This is not really an important thing though, so we can just dump it in any old // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name. - var error_info = std.ArrayList(u8).init(self.spv.gpa); + var error_info = std.ArrayList(u8).init(self.object.gpa); defer error_info.deinit(); try error_info.appendSlice("zig_errors"); @@ -209,11 +188,11 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No defer self.base.allocator.free(escaped_name); try error_info.writer().print(":{s}", .{escaped_name}); } - try self.spv.sections.debug_strings.emit(self.spv.gpa, .OpSourceExtension, .{ + try spv.sections.debug_strings.emit(spv.gpa, .OpSourceExtension, .{ .extension = error_info.items, }); - try self.spv.flush(self.base.file.?); + try spv.flush(self.base.file.?); } fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { -- 2.54.0 From 89b1dafa7808d22eab78ea486f158f794da46a2c Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 18:53:33 +0200 Subject: [PATCH 09/36] spirv: aggregate_init for structs --- src/codegen/spirv.zig | 45 +++++++++++++++++++++++++++++++++++++--- test/behavior/basic.zig | 5 ----- test/behavior/struct.zig | 6 ------ 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3a751fed6875519e3725cb1de03c2c48b45e0e87..2fdec5675ff838ada344fa62a59d99cd34d20e09 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2725,6 +2725,7 @@ const DeclGen = struct { if (self.liveness.isUnused(inst)) return null; const mod = self.module; + const ip = &mod.intern_pool; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const result_ty = self.typeOfIndex(inst); const result_ty_ref = try self.resolveType(result_ty, .direct); @@ -2733,15 +2734,53 @@ const DeclGen = struct { switch (result_ty.zigTypeTag(mod)) { .Vector => unreachable, // TODO - .Struct => unreachable, // TODO + .Struct => { + if (mod.typeToPackedStruct(result_ty)) |struct_type| { + _ = struct_type; + unreachable; // TODO + } + + const constituents = try self.gpa.alloc(IdRef, elements.len); + defer self.gpa.free(constituents); + var index: usize = 0; + + switch (ip.indexToKey(result_ty.toIntern())) { + .anon_struct_type => |tuple| { + for (tuple.types.get(ip), elements, 0..) |field_ty, element, i| { + if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue; + assert(field_ty.toType().hasRuntimeBits(mod)); + + const id = try self.resolve(element); + constituents[index] = try self.convertToIndirect(field_ty.toType(), id); + index += 1; + } + }, + .struct_type => |struct_type| { + var it = struct_type.iterateRuntimeOrder(ip); + for (elements, 0..) |element, i| { + const field_index = it.next().?; + if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue; + const field_ty = struct_type.field_types.get(ip)[field_index].toType(); + assert(field_ty.hasRuntimeBitsIgnoreComptime(mod)); + + const id = try self.resolve(element); + constituents[index] = try self.convertToIndirect(field_ty, id); + index += 1; + } + }, + else => unreachable, + } + + return try self.constructStruct(result_ty_ref, constituents[0..index]); + }, .Array => { const array_info = result_ty.arrayInfo(mod); const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); const elem_ids = try self.gpa.alloc(IdRef, n_elems); defer self.gpa.free(elem_ids); - for (elements, 0..) |elem_inst, i| { - const id = try self.resolve(elem_inst); + for (elements, 0..) |element, i| { + const id = try self.resolve(element); elem_ids[i] = try self.convertToIndirect(array_info.elem_type, id); } diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 416ef0c29c435fa27ab23b1611abac5d35b82b33..f91bbe6edf7780dbdd0a2f2d52e24ede1bf661b9 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -357,8 +357,6 @@ fn f2(x: bool) []const u8 { } test "variable is allowed to be a pointer to an opaque type" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var x: i32 = 1234; _ = hereIsAnOpaqueType(@as(*OpaqueA, @ptrCast(&x))); } @@ -397,7 +395,6 @@ test "array 2D const double ptr" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const rect_2d_vertexes = [_][1]f32{ [_]f32{1.0}, @@ -410,7 +407,6 @@ test "array 2D const double ptr with offset" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const rect_2d_vertexes = [_][2]f32{ [_]f32{ 3.0, 4.239 }, @@ -423,7 +419,6 @@ test "array 3D const double ptr with offset" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const rect_3d_vertexes = [_][2][2]f32{ [_][2]f32{ diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 3f9e41b470d8fa3e8996650f7bc7b1b398158fa4..8db14affcf7918fecae3f4a345e71400bf191ac2 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -311,7 +311,6 @@ test "struct point to self" { test "void struct fields" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const foo = VoidStructFieldsFoo{ .a = void{}, @@ -340,7 +339,6 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 { test "pass slice of empty struct to fn" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); } @@ -1229,7 +1227,6 @@ test "typed init through error unions and optionals" { 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 { a: u32, @@ -1550,7 +1547,6 @@ test "no dependency loop on optional field wrapped in generic function" { test "optional field init with tuple" { 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; const S = struct { a: ?struct { b: u32 }, @@ -1652,7 +1648,6 @@ test "struct field pointer has correct alignment" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { @@ -1683,7 +1678,6 @@ test "extern struct field pointer has correct alignment" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { -- 2.54.0 From 4a6a024a4bd103cf7bf7e50a5ccf4103f4ce83a2 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 19:43:27 +0200 Subject: [PATCH 10/36] spirv: properly skip comptime function parameters --- src/codegen/spirv.zig | 21 ++++++++++++++------- test/behavior/struct.zig | 6 ------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 2fdec5675ff838ada344fa62a59d99cd34d20e09..fd984c78d53e90e52a4440f2f54e5cc94d6682c4 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1242,14 +1242,19 @@ const DeclGen = struct { const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len); defer self.gpa.free(param_ty_refs); - for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| { - param_type.* = try self.resolveType(fn_param_type.toType(), .direct); + var param_index: usize = 0; + for (fn_info.param_types.get(ip)) |param_ty_index| { + const param_ty = param_ty_index.toType(); + if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + + param_ty_refs[param_index] = try self.resolveType(param_ty, .direct); + param_index += 1; } const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct); const ty_ref = try self.spv.resolve(.{ .function_type = .{ .return_type = return_ty_ref, - .parameters = param_ty_refs, + .parameters = param_ty_refs[0..param_index], } }); try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); @@ -1675,9 +1680,11 @@ const DeclGen = struct { const fn_info = mod.typeToFunc(decl.ty).?; try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); - for (0..fn_info.param_types.len) |i| { - const param_type = fn_info.param_types.get(ip)[i]; - const param_type_id = try self.resolveTypeId(param_type.toType()); + for (fn_info.param_types.get(ip)) |param_ty_index| { + const param_ty = param_ty_index.toType(); + if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + + const param_type_id = try self.resolveTypeId(param_ty); const arg_result_id = self.spv.allocId(); try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{ .id_result_type = param_type_id, @@ -3986,9 +3993,9 @@ const DeclGen = struct { // Note: resolve() might emit instructions, so we need to call it // before starting to emit OpFunctionCall instructions. Hence the // temporary params buffer. - const arg_id = try self.resolve(arg); const arg_ty = self.typeOf(arg); if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const arg_id = try self.resolve(arg); params[n_params] = arg_id; n_params += 1; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 8db14affcf7918fecae3f4a345e71400bf191ac2..316bc6d2ccc03b377f48f4e20ddb1ff8372db02c 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -887,8 +887,6 @@ test "anonymous struct literal syntax" { } test "fully anonymous struct" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn doTheTest() !void { try dump(.{ @@ -911,8 +909,6 @@ test "fully anonymous struct" { } test "fully anonymous list literal" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn doTheTest() !void { try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" }); @@ -1715,8 +1711,6 @@ test "extern struct field pointer has correct alignment" { } test "packed struct field in anonymous struct" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const T = packed struct { f1: bool = false, }; -- 2.54.0 From c6c5fb40deaa104226581d79b3b9332315e11309 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 21:21:54 +0200 Subject: [PATCH 11/36] spirv: fix float unequality --- src/codegen/spirv.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index fd984c78d53e90e52a4440f2f54e5cc94d6682c4..293ef5860b98fde9cc31f2180e980f88a1cab5a5 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2454,7 +2454,7 @@ const DeclGen = struct { }, .float => break :opcode switch (op) { .eq => .OpFOrdEqual, - .neq => .OpFOrdNotEqual, + .neq => .OpFUnordNotEqual, .lt => .OpFOrdLessThan, .lte => .OpFOrdLessThanEqual, .gt => .OpFOrdGreaterThan, -- 2.54.0 From 0a3e566f57063c42146aa2d64481a7eb1361f96f Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 7 Oct 2023 22:11:10 +0200 Subject: [PATCH 12/36] spirv: make bitcasts between the same spirv type a no-op --- src/codegen/spirv.zig | 8 +++++++- test/behavior/for.zig | 4 ---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 293ef5860b98fde9cc31f2180e980f88a1cab5a5..82e172c0d7fafbae3436e4530be1fa5cf683f93b 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2527,7 +2527,12 @@ const DeclGen = struct { src_id: IdRef, ) !IdRef { const mod = self.module; + const src_ty_ref = try self.resolveType(src_ty, .direct); const dst_ty_ref = try self.resolveType(dst_ty, .direct); + if (src_ty_ref == dst_ty_ref) { + return src_id; + } + const result_id = self.spv.allocId(); // TODO: Some more cases are missing here @@ -2811,7 +2816,8 @@ const DeclGen = struct { fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { const mod = self.module; - const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const slice_ty = self.typeOf(bin_op.lhs); if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null; diff --git a/test/behavior/for.zig b/test/behavior/for.zig index 211fba932b2a24f427b710fabcd7e0bf341bf64b..b1fc2f0fb9e31b8774e0faa712b95768141c708f 100644 --- a/test/behavior/for.zig +++ b/test/behavior/for.zig @@ -70,7 +70,6 @@ test "basic for loop" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; @@ -157,7 +156,6 @@ test "for loop with pointer elem var" { 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 source = "abcdefg"; var target: [source.len]u8 = undefined; @@ -204,7 +202,6 @@ test "for on slice with allowzero ptr" { 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(slice: []const u8) !void { @@ -344,7 +341,6 @@ test "two slices, one captured by-ref" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [10]u8 = undefined; const slice1: []const u8 = "blah"; -- 2.54.0 From 15cf1315bb945f2a14a48e2cc7ee2eaf2e0536d2 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 00:06:06 +0200 Subject: [PATCH 13/36] spirv: fix incorrect repr of some optional operations --- src/codegen/spirv.zig | 12 ++++++++---- test/behavior/cast.zig | 1 - test/behavior/for.zig | 1 - 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 82e172c0d7fafbae3436e4530be1fa5cf683f93b..41848644c4526904345b8905b52d1bc7e5adf71c 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -3594,11 +3594,13 @@ const DeclGen = struct { return result_id; } - const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime(mod)) + const is_non_null_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) try self.extractField(Type.bool, operand_id, 1) else // Optional representation is bool indicating whether the optional is set - operand_id; + // Optionals with no payload are represented as an (indirect) bool, so convert + // it back to the direct bool here. + try self.convertToDirect(Type.bool, operand_id); return switch (pred) { .is_null => blk: { @@ -3677,17 +3679,19 @@ const DeclGen = struct { const payload_ty = self.typeOf(ty_op.operand); if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - return try self.constBool(true, .direct); + return try self.constBool(true, .indirect); } const operand_id = try self.resolve(ty_op.operand); + const optional_ty = self.typeOfIndex(inst); if (optional_ty.optionalReprIsPayload(mod)) { return operand_id; } const optional_ty_ref = try self.resolveType(optional_ty, .direct); - const members = [_]IdRef{ operand_id, try self.constBool(true, .indirect) }; + const payload_id = try self.convertToIndirect(payload_ty, operand_id); + const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) }; return try self.constructStruct(optional_ty_ref, &members); } diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index cc4723405fe370274a3c32a315f5a1270d2628b7..a642860e4e80d85fdc3522bc282ac149ef6fe812 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -240,7 +240,6 @@ test "coerce undefined to optional" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(MakeType(void).getNull() == null); try expect(MakeType(void).getNonNull() != null); diff --git a/test/behavior/for.zig b/test/behavior/for.zig index b1fc2f0fb9e31b8774e0faa712b95768141c708f..bf90d661fb09f5178fb357a0c3cb8376ac5e4024 100644 --- a/test/behavior/for.zig +++ b/test/behavior/for.zig @@ -492,7 +492,6 @@ test "inferred alloc ptr of for loop" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO { var cond = false; -- 2.54.0 From fe51ff9fc14c38337c559acb7647480188b1d154 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 01:27:20 +0200 Subject: [PATCH 14/36] spirv: make air is_null not emit OpPtr(Not)Equal --- src/codegen/spirv.zig | 24 ++++++++---------------- test/behavior/cast.zig | 12 ------------ test/behavior/pointers.zig | 2 -- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 41848644c4526904345b8905b52d1bc7e5adf71c..0ab87b4df04869735a31e329e2e3ba92cced5045 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2406,8 +2406,7 @@ const DeclGen = struct { fn cmp( self: *DeclGen, - comptime op: std.math.CompareOperator, - bool_ty_id: IdRef, + op: std.math.CompareOperator, ty: Type, lhs_id: IdRef, rhs_id: IdRef, @@ -2415,6 +2414,7 @@ const DeclGen = struct { const mod = self.module; var cmp_lhs_id = lhs_id; var cmp_rhs_id = rhs_id; + const bool_ty_ref = try self.resolveType(Type.bool, .direct); const opcode: Opcode = opcode: { const op_ty = switch (ty.zigTypeTag(mod)) { .Int, .Bool, .Float => ty, @@ -2497,7 +2497,7 @@ const DeclGen = struct { const result_id = self.spv.allocId(); try self.func.body.emitRaw(self.spv.gpa, opcode, 4); - self.func.body.writeOperand(spec.IdResultType, bool_ty_id); + self.func.body.writeOperand(spec.IdResultType, self.typeId(bool_ty_ref)); self.func.body.writeOperand(spec.IdResult, result_id); self.func.body.writeOperand(spec.IdResultType, cmp_lhs_id); self.func.body.writeOperand(spec.IdResultType, cmp_rhs_id); @@ -2513,11 +2513,10 @@ const DeclGen = struct { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs_id = try self.resolve(bin_op.lhs); const rhs_id = try self.resolve(bin_op.rhs); - const bool_ty_id = try self.resolveTypeId(Type.bool); const ty = self.typeOf(bin_op.lhs); assert(ty.eql(self.typeOf(bin_op.rhs), self.module)); - return try self.cmp(op, bool_ty_id, ty, lhs_id, rhs_id); + return try self.cmp(op, ty, lhs_id, rhs_id); } fn bitCast( @@ -3580,18 +3579,11 @@ const DeclGen = struct { const payload_ty_ref = try self.resolveType(ptr_ty, .direct); const null_id = try self.spv.constNull(payload_ty_ref); - const result_id = self.spv.allocId(); - const operands = .{ - .id_result_type = self.typeId(bool_ty_ref), - .id_result = result_id, - .operand_1 = ptr_id, - .operand_2 = null_id, + const op: std.math.CompareOperator = switch (pred) { + .is_null => .eq, + .is_non_null => .neq, }; - switch (pred) { - .is_null => try self.func.body.emit(self.spv.gpa, .OpPtrEqual, operands), - .is_non_null => try self.func.body.emit(self.spv.gpa, .OpPtrNotEqual, operands), - } - return result_id; + return try self.cmp(op, ptr_ty, ptr_id, null_id); } const is_non_null_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index a642860e4e80d85fdc3522bc282ac149ef6fe812..ec198c313349df1d9e1e26ea16b3583bc823247c 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -179,7 +179,6 @@ fn expectIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void { test "implicitly cast indirect pointer to maybe-indirect pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const Self = @This(); @@ -260,7 +259,6 @@ fn MakeType(comptime T: type) type { test "implicit cast from *[N]T to [*c]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: [4]u16 = [4]u16{ 0, 1, 2, 3 }; var y: [*c]u16 = &x; @@ -1101,7 +1099,6 @@ test "implicit cast from [*]T to ?*anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; var a = [_]u8{ 3, 2, 1 }; var runtime_zero: usize = 0; @@ -1164,7 +1161,6 @@ test "implicit ptr to *anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; var a: u32 = 1; var ptr: *align(@alignOf(u32)) anyopaque = &a; @@ -1178,7 +1174,6 @@ test "implicit ptr to *anyopaque" { test "return null from fn () anyerror!?&T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const a = returnNullFromOptionalTypeErrorRef(); const b = returnNullLitFromOptionalTypeErrorRef(); @@ -1268,7 +1263,6 @@ test "implicit cast from *T to ?*anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; var a: u8 = 1; incrementVoidPtrValue(&a); @@ -1338,7 +1332,6 @@ test "assignment to optional pointer result loc" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; try expect(foo.ptr.? == @as(*anyopaque, @ptrCast(&global_struct))); @@ -1532,7 +1525,6 @@ test "cast typed undefined to int" { test "implicit cast from [:0]T to [*c]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var a: [:0]const u8 = "foo"; var b: [*c]const u8 = a; @@ -1788,7 +1780,6 @@ test "peer type resolution: three-way resolution combines error set and optional 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; // TODO const E = error{Foo}; var a: E = error.Foo; @@ -2180,7 +2171,6 @@ test "cast builtins can wrap result in optional" { 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; // TODO const S = struct { const MyEnum = enum(u32) { _ }; @@ -2256,7 +2246,6 @@ test "cast builtins can wrap result in error union and optional" { 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; // TODO const S = struct { const MyEnum = enum(u32) { _ }; @@ -2461,7 +2450,6 @@ test "result information is preserved through many nested structures" { 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 { diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index 8974b75dbe520d43ff7d20f11dc16f280fcfb070..ad3d9717e14ec1ecd2fb77280b81f7d3747eb51d 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -149,7 +149,6 @@ test "implicit casting between C pointer and optional non-C pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var slice: []const u8 = "aoeu"; const opt_many_ptr: ?[*]const u8 = slice.ptr; @@ -211,7 +210,6 @@ test "assign null directly to C pointer and test null equality" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: [*c]i32 = null; try expect(x == null); -- 2.54.0 From ae3efab2260ce84fa25dd874e0c193d919eb80c1 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 02:06:47 +0200 Subject: [PATCH 15/36] spirv: generate *void as pointer to opaque --- src/codegen/spirv.zig | 20 ++++++++++++++------ test/behavior/cast.zig | 2 -- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 0ab87b4df04869735a31e329e2e3ba92cced5045..86232c61498cac3c649a67ed3ffb9462a9fb53ce 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1187,7 +1187,17 @@ const DeclGen = struct { log.debug("resolveType: ty = {}", .{ty.fmt(mod)}); const target = self.getTarget(); switch (ty.zigTypeTag(mod)) { - .Void, .NoReturn => return try self.spv.resolve(.void_type), + .NoReturn => { + assert(repr == .direct); + return try self.spv.resolve(.void_type); + }, + .Void => switch (repr) { + .direct => return try self.spv.resolve(.void_type), + // Pointers to void + .indirect => return try self.spv.resolve(.{ .opaque_type = .{ + .name = try self.spv.resolveString("void"), + } }), + }, .Bool => switch (repr) { .direct => return try self.spv.resolve(.bool_type), .indirect => return try self.intType(.unsigned, 1), @@ -1439,11 +1449,9 @@ const DeclGen = struct { return ty_ref; }, .Opaque => { - return try self.spv.resolve(.{ - .opaque_type = .{ - .name = .none, // TODO - }, - }); + return try self.spv.resolve(.{ .opaque_type = .{ + .name = .none, // TODO + } }); }, .Null, diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index ec198c313349df1d9e1e26ea16b3583bc823247c..388d6f4750c4a5657d0dfce68f281f26a7c99689 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -270,8 +270,6 @@ test "implicit cast from *[N]T to [*c]T" { } test "*usize to *void" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var i = @as(usize, 0); var v = @as(*void, @ptrCast(&i)); v.* = {}; -- 2.54.0 From d2692af8e2c6e4397f9be94b2b6625ba0e6e725f Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 02:44:52 +0200 Subject: [PATCH 16/36] spirv: override function return type to void if it has no runtime bits --- src/codegen/spirv.zig | 75 +++++++++++++++++++++++++++++--------- test/behavior/optional.zig | 4 -- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 86232c61498cac3c649a67ed3ffb9462a9fb53ce..7528c40cca47b7f1602dbfdb724f2c451ef2f5e5 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1180,6 +1180,22 @@ const DeclGen = struct { return ty_ref; } + fn resolveFnReturnType(self: *DeclGen, ret_ty: Type) !CacheRef { + const mod = self.module; + if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { + // If the return type is an error set or an error union, then we make this + // anyerror return type instead, so that it can be coerced into a function + // pointer type which has anyerror as the return type. + if (ret_ty.isError(mod)) { + return self.resolveType(Type.anyerror, .direct); + } else { + return self.resolveType(Type.void, .direct); + } + } + + return try self.resolveType(ret_ty, .direct); + } + /// Turn a Zig type into a SPIR-V Type, and return a reference to it. fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef { const mod = self.module; @@ -1260,7 +1276,7 @@ const DeclGen = struct { param_ty_refs[param_index] = try self.resolveType(param_ty, .direct); param_index += 1; } - const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct); + const return_ty_ref = try self.resolveFnReturnType(fn_info.return_type.toType()); const ty_ref = try self.spv.resolve(.{ .function_type = .{ .return_type = return_ty_ref, @@ -1449,9 +1465,11 @@ const DeclGen = struct { return ty_ref; }, .Opaque => { - return try self.spv.resolve(.{ .opaque_type = .{ - .name = .none, // TODO - } }); + return try self.spv.resolve(.{ + .opaque_type = .{ + .name = .none, // TODO + }, + }); }, .Null, @@ -1677,16 +1695,17 @@ const DeclGen = struct { if (decl.val.getFunction(mod)) |_| { assert(decl.ty.zigTypeTag(mod) == .Fn); + const fn_info = mod.typeToFunc(decl.ty).?; + const return_ty_ref = try self.resolveFnReturnType(fn_info.return_type.toType()); + const prototype_id = try self.resolveTypeId(decl.ty); try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ - .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType(mod)), + .id_result_type = self.typeId(return_ty_ref), .id_result = decl_id, .function_control = .{}, // TODO: We can set inline here if the type requires it. .function_type = prototype_id, }); - const fn_info = mod.typeToFunc(decl.ty).?; - try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); for (fn_info.param_types.get(ip)) |param_ty_index| { const param_ty = param_ty_index.toType(); @@ -3385,15 +3404,25 @@ const DeclGen = struct { fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { const operand = self.air.instructions.items(.data)[inst].un_op; - const operand_ty = self.typeOf(operand); + const ret_ty = self.typeOf(operand); const mod = self.module; - if (operand_ty.hasRuntimeBits(mod)) { - // TODO: If we return an empty struct, this branch is also hit incorrectly. - const operand_id = try self.resolve(operand); - try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); - } else { - try self.func.body.emit(self.spv.gpa, .OpReturn, {}); + if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { + const decl = mod.declPtr(self.decl_index); + const fn_info = mod.typeToFunc(decl.ty).?; + if (fn_info.return_type.toType().isError(mod)) { + // Functions with an empty error set are emitted with an error code + // return type and return zero so they can be function pointers coerced + // to functions that return anyerror. + const err_ty_ref = try self.resolveType(Type.anyerror, .direct); + const no_err_id = try self.constInt(err_ty_ref, 0); + return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); + } else { + return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); + } } + + const operand_id = try self.resolve(operand); + try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); } fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void { @@ -3403,8 +3432,18 @@ const DeclGen = struct { const ret_ty = ptr_ty.childType(mod); if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { - try self.func.body.emit(self.spv.gpa, .OpReturn, {}); - return; + const decl = mod.declPtr(self.decl_index); + const fn_info = mod.typeToFunc(decl.ty).?; + if (fn_info.return_type.toType().isError(mod)) { + // Functions with an empty error set are emitted with an error code + // return type and return zero so they can be function pointers coerced + // to functions that return anyerror. + const err_ty_ref = try self.resolveType(Type.anyerror, .direct); + const no_err_id = try self.constInt(err_ty_ref, 0); + return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); + } else { + return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); + } } const ptr = try self.resolve(un_op); @@ -3991,7 +4030,7 @@ const DeclGen = struct { const fn_info = mod.typeToFunc(zig_fn_ty).?; const return_type = fn_info.return_type; - const result_type_id = try self.resolveTypeId(return_type.toType()); + const result_type_ref = try self.resolveFnReturnType(return_type.toType()); const result_id = self.spv.allocId(); const callee_id = try self.resolve(pl_op.operand); @@ -4012,7 +4051,7 @@ const DeclGen = struct { } try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{ - .id_result_type = result_type_id, + .id_result_type = self.typeId(result_type_ref), .id_result = result_id, .function = callee_id, .id_ref_3 = params[0..n_params], diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index 0b2d7d11104a1b7accfbaf29dfe931301d17a8b3..3bd171e9d4e5f221060b5ea18db70cc441cc2bf7 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -27,7 +27,6 @@ pub const EmptyStruct = struct {}; test "optional pointer to size zero struct" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var e = EmptyStruct{}; var o: ?*EmptyStruct = &e; @@ -152,7 +151,6 @@ fn test_cmp_optional_non_optional() !void { test "unwrap function call with optional pointer return value" { 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 entry() !void { @@ -400,7 +398,6 @@ const NoReturn = struct { test "optional of noreturn used with if" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; NoReturn.a = 64; if (NoReturn.loop()) |_| { @@ -412,7 +409,6 @@ test "optional of noreturn used with if" { test "optional of noreturn used with orelse" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; NoReturn.a = 64; const val = NoReturn.testOrelse(); -- 2.54.0 From d8b591766ac37090ae77f7b67d0ce6b54c64254e Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Sun, 8 Oct 2023 16:22:37 +0330 Subject: [PATCH 17/36] spirv: `fpext` and `fptrunc` instructions --- src/codegen/spirv.zig | 18 ++++++++++++++++++ src/link/SpirV.zig | 2 +- test/behavior/cast.zig | 1 - 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 7528c40cca47b7f1602dbfdb724f2c451ef2f5e5..6881b2c59862c108f6b1b860770feae0bbabf1c8 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1957,6 +1957,7 @@ const DeclGen = struct { .int_from_ptr => try self.airIntFromPtr(inst), .float_from_int => try self.airFloatFromInt(inst), .int_from_float => try self.airIntFromFloat(inst), + .fpext, .fptrunc => try self.airFloatCast(inst), .not => try self.airNot(inst), .array_to_slice => try self.airArrayToSlice(inst), @@ -2685,6 +2686,23 @@ const DeclGen = struct { return result_id; } + fn airFloatCast(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.typeOfIndex(inst); + const dest_ty_id = try self.resolveTypeId(dest_ty); + + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpFConvert, .{ + .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/src/link/SpirV.zig b/src/link/SpirV.zig index 58d8ca684173c1b6a016e9d2d234b50a6b38cd72..325bb30fe05076358a72c83eb825b509bb577988 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -230,7 +230,7 @@ fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { }; // TODO: Put this in a proper section. - try spv.sections.capabilities.emit(spv.gpa, .OpMemoryModel, .{ + try spv.sections.extensions.emit(spv.gpa, .OpMemoryModel, .{ .addressing_model = addressing_model, .memory_model = memory_model, }); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 388d6f4750c4a5657d0dfce68f281f26a7c99689..4a6b4db2cec2a0b9e8288e99f877119c7150526e 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -648,7 +648,6 @@ test "@floatCast cast down" { 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; { var double: f64 = 0.001534; -- 2.54.0 From 2d52fc762da7e7288c4caa381fb02933c205e9be Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 10:54:41 +0200 Subject: [PATCH 18/36] spirv: handle zero-sized arrays --- src/codegen/spirv.zig | 38 ++++++++++++++++++++++++++------------ test/behavior/slice.zig | 8 -------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 6881b2c59862c108f6b1b860770feae0bbabf1c8..e8e1b895071a46321147a5c92ad135a72b27515e 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1008,8 +1008,7 @@ const DeclGen = struct { .func => { // TODO: Properly lower function pointers. For now we are going to hack around it and // just generate an empty pointer. Function pointers are represented by a pointer to usize. - // TODO: Add dependency - return try self.spv.constNull(ty_ref); + return try self.spv.constUndef(ty_ref); }, .extern_func => unreachable, // TODO else => {}, @@ -1253,6 +1252,18 @@ const DeclGen = struct { const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse { return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)}); }; + if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { + // The size of the array would be 0, but that is not allowed in SPIR-V. + // This path can be reached for example when there is a slicing of a pointer + // that produces a zero-length array. In all cases where this type can be generated, + // we should be in an indirect path (direct uses of this type should be filtered out in Sema). + assert(repr == .indirect); + + return try self.spv.resolve(.{ .opaque_type = .{ + .name = try self.spv.resolveString("zero-sized array"), + } }); + } + const ty_ref = try self.spv.arrayType(total_len, elem_ty_ref); try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); return ty_ref; @@ -2742,22 +2753,23 @@ const DeclGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const array_ptr_ty = self.typeOf(ty_op.operand); const array_ty = array_ptr_ty.childType(mod); - const elem_ty = array_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. - const elem_ty_ref = try self.resolveType(elem_ty, .indirect); - const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(array_ptr_ty.ptrAddressSpace(mod))); const slice_ty = self.typeOfIndex(inst); + const elem_ptr_ty = slice_ty.slicePtrFieldType(mod); + + const elem_ptr_ty_ref = try self.resolveType(elem_ptr_ty, .direct); const slice_ty_ref = try self.resolveType(slice_ty, .direct); const size_ty_ref = try self.sizeType(); const array_ptr_id = try self.resolve(ty_op.operand); const len_id = try self.constInt(size_ty_ref, array_ty.arrayLen(mod)); - if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) { - unreachable; // TODO - } + const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) + // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. + try self.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id) + else + // Convert the pointer-to-array to a pointer to the first element. + try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0}); - // Convert the pointer-to-array to a pointer to the first element. - const elem_ptr_id = try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0}); return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id }); } @@ -2916,8 +2928,10 @@ const DeclGen = struct { const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.childType(mod); - // TODO: Make this return a null ptr or something - if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; + if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) { + const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); + return try self.spv.constUndef(ptr_ty_ref); + } const ptr_id = try self.resolve(bin_op.lhs); const index_id = try self.resolve(bin_op.rhs); diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 8049abb8dd21bc13ce8f60904ad2b5619b4a30a7..cbd3b5416341c63181298516a6f33b5310aaf926 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -64,7 +64,6 @@ test "comptime slice of undefined pointer of length 0" { test "implicitly cast array of size 0 to slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var msg = [_]u8{}; try assertLenIsZero(&msg); @@ -172,7 +171,6 @@ test "comptime pointer cast array and then slice" { test "slicing zero length array" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const s1 = ""[0..]; const s2 = ([_]u32{})[0..]; @@ -583,7 +581,6 @@ test "slice pointer-to-array null terminated" { test "slice pointer-to-array zero length" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; comptime { { @@ -793,8 +790,6 @@ test "global slice field access" { } test "slice of void" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var n: usize = 10; var arr: [12]void = undefined; const slice = @as([]void, &arr)[0..n]; @@ -802,8 +797,6 @@ test "slice of void" { } test "slice with dereferenced value" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var a: usize = 0; var idx: *usize = &a; _ = blk: { @@ -819,7 +812,6 @@ test "slice with dereferenced value" { test "empty slice ptr is non null" { if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; { const empty_slice: []u8 = &[_]u8{}; -- 2.54.0 From d0e7a3596ba480fdbc59644fd13859efe3024ea8 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 11:04:48 +0200 Subject: [PATCH 19/36] spirv: allow generation of *i0 --- src/codegen/spirv.zig | 9 ++++++++- test/behavior/array.zig | 2 -- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index e8e1b895071a46321147a5c92ad135a72b27515e..dc572d390ed9615cd1a280760137401d01c41421 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1219,7 +1219,14 @@ const DeclGen = struct { }, .Int => { const int_info = ty.intInfo(mod); - // TODO: Integers in OpenCL kernels are always unsigned. + if (int_info.bits == 0) { + // Some times, the backend will be asked to generate a pointer to i0. OpTypeInt + // with 0 bits is invalid, so return an opaque type in this case. + assert(repr == .indirect); + return try self.spv.resolve(.{ .opaque_type = .{ + .name = try self.spv.resolveString("u0"), + } }); + } return try self.intType(int_info.signedness, int_info.bits); }, .Enum => { diff --git a/test/behavior/array.zig b/test/behavior/array.zig index 40224e5026c2f1eb0b5848afe8b529c41489cf21..a8d42f6589b9e009670990dbbbc2e1953fa21f16 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -261,7 +261,6 @@ fn doSomeMangling(array: *[4]u8) void { test "implicit cast zero sized array ptr to slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; { var b = "".*; @@ -732,7 +731,6 @@ test "slicing array of zero-sized values" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var arr: [32]u0 = undefined; for (arr[0..]) |*zero| -- 2.54.0 From 0af16a58a0af20efa063057e90f8f448b010afd1 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 11:38:43 +0200 Subject: [PATCH 20/36] spirv: fix air is_null optional slice field type --- src/codegen/spirv.zig | 2 +- test/behavior/cast.zig | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index dc572d390ed9615cd1a280760137401d01c41421..638bf7b187c926ee8e0548cdab40da84cdfd8a53 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -3659,7 +3659,7 @@ const DeclGen = struct { payload_ty; const ptr_id = if (payload_ty.isSlice(mod)) - try self.extractField(Type.bool, operand_id, 0) + try self.extractField(ptr_ty, operand_id, 0) else operand_id; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 4a6b4db2cec2a0b9e8288e99f877119c7150526e..ca491a0a228f6f9ee16f4cf32f3b03e54518a691 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1208,7 +1208,6 @@ test "implicitly cast from [N]T to ?[]const T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); try comptime expect(mem.eql(u8, castToOptionalSlice().?, "hi")); @@ -1293,7 +1292,6 @@ test "*const [N]null u8 to ?[]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 { @@ -1335,8 +1333,6 @@ test "assignment to optional pointer result loc" { } test "cast between *[N]void and []void" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var a: [4]void = undefined; var b: []void = &a; try expect(b.len == 4); @@ -1398,7 +1394,6 @@ test "peer type resolution: unreachable, null, slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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(num: usize, word: []const u8) !void { @@ -1438,7 +1433,6 @@ test "cast compatible optional types" { 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; var a: ?[:0]const u8 = null; var b: ?[]const u8 = a; -- 2.54.0 From f858bf161602d72584da9e950c5a9eeadfe8b29d Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 12:09:25 +0200 Subject: [PATCH 21/36] spirv: air bitcast for non-numeric non-pointer types --- src/codegen/spirv.zig | 35 +++++++++++++++++++++++++++++++---- src/codegen/spirv/Cache.zig | 7 +++++++ test/behavior/cast.zig | 2 -- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 638bf7b187c926ee8e0548cdab40da84cdfd8a53..62f945dd81b421f29a4c1c55f11dfb53b4c9802d 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2578,25 +2578,52 @@ const DeclGen = struct { return src_id; } - const result_id = self.spv.allocId(); - // TODO: Some more cases are missing here // See fn bitCast in llvm.zig if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { + const result_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ .id_result_type = self.typeId(dst_ty_ref), .id_result = result_id, .integer_value = src_id, }); - } else { + return result_id; + } + + // We can only use OpBitcast for specific conversions: between numerical types, and + // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast, + // otherwise use a temporary and perform a pointer cast. + const src_key = self.spv.cache.lookup(src_ty_ref); + const dst_key = self.spv.cache.lookup(dst_ty_ref); + + if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) { + const result_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ .id_result_type = self.typeId(dst_ty_ref), .id_result = result_id, .operand = src_id, }); + return result_id; } - return result_id; + + const src_ptr_ty_ref = try self.spv.ptrType(src_ty_ref, .Function); + const dst_ptr_ty_ref = try self.spv.ptrType(dst_ty_ref, .Function); + + const tmp_id = self.spv.allocId(); + try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ + .id_result_type = self.typeId(src_ptr_ty_ref), + .id_result = tmp_id, + .storage_class = .Function, + }); + try self.store(src_ty, tmp_id, src_id, false); + const casted_ptr_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ + .id_result_type = self.typeId(dst_ptr_ty_ref), + .id_result = casted_ptr_id, + .operand = tmp_id, + }); + return try self.load(dst_ty, casted_ptr_id, false); } fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { diff --git a/src/codegen/spirv/Cache.zig b/src/codegen/spirv/Cache.zig index 7f5590344c6ee3b7bc7c75b5988f41b8843b8b92..ad2d3442e5e09f9992c6fa1529da85cf12eb5859 100644 --- a/src/codegen/spirv/Cache.zig +++ b/src/codegen/spirv/Cache.zig @@ -435,6 +435,13 @@ pub const Key = union(enum) { else => unreachable, }; } + + pub fn isNumericalType(self: Key) bool { + return switch (self) { + .int_type, .float_type => true, + else => false, + }; + } }; pub fn deinit(self: *Self, spv: *const Module) void { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index ca491a0a228f6f9ee16f4cf32f3b03e54518a691..20867fa7e8fc65d8b360e5f2e0a7db465c7f9cf1 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -899,7 +899,6 @@ test "peer cast [:x]T to []T" { test "peer cast [N:x]T to [N]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 { @@ -1728,7 +1727,6 @@ test "peer type resolution: error union and optional of same type" { 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; // TODO const E = error{Foo}; var a: E!*u8 = error.Foo; -- 2.54.0 From 4f279078c8bd57e7ee47eebce2572ab25729850a Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 13:02:16 +0200 Subject: [PATCH 22/36] spirv: air min/max --- src/codegen/spirv.zig | 51 +++++++++++++++++++++++++++++++ test/behavior/maximum_minimum.zig | 8 +++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 62f945dd81b421f29a4c1c55f11dfb53b4c9802d..42a11120b5bff592e23ffb906bf8b25ba973c7bc 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1970,6 +1970,9 @@ const DeclGen = struct { .shl => try self.airShift(inst, .OpShiftLeftLogical), + .min => try self.airMinMax(inst, .lt), + .max => try self.airMinMax(inst, .gt), + .bitcast => try self.airBitCast(inst), .intcast, .trunc => try self.airIntCast(inst), .int_from_ptr => try self.airIntFromPtr(inst), @@ -2103,6 +2106,54 @@ const DeclGen = struct { return result_id; } + fn airMinMax(self: *DeclGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const lhs_id = try self.resolve(bin_op.lhs); + const rhs_id = try self.resolve(bin_op.rhs); + const result_ty = self.typeOfIndex(inst); + const result_ty_ref = try self.resolveType(result_ty, .direct); + + const info = try self.arithmeticTypeInfo(result_ty); + // TODO: Use fmin for OpenCL + const cmp_id = try self.cmp(op, result_ty, lhs_id, rhs_id); + const selection_id = switch (info.class) { + .float => blk: { + // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, + // but we want it to pick lhs. Therefore we also have to check if + // rhs is nan. We don't need to care about the result when both + // are nan. + const rhs_is_nan_id = self.spv.allocId(); + const bool_ty_ref = try self.resolveType(Type.bool, .direct); + try self.func.body.emit(self.spv.gpa, .OpIsNan, .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = rhs_is_nan_id, + .x = rhs_id, + }); + const float_cmp_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = float_cmp_id, + .operand_1 = cmp_id, + .operand_2 = rhs_is_nan_id, + }); + break :blk float_cmp_id; + }, + else => cmp_id, + }; + + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpSelect, .{ + .id_result_type = self.typeId(result_ty_ref), + .id_result = result_id, + .condition = selection_id, + .object_1 = lhs_id, + .object_2 = rhs_id, + }); + return result_id; + } + fn maskStrangeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, bits: u16) !IdRef { const mask_value = if (bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(bits))) - 1; const result_id = self.spv.allocId(); diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index c76dd7573da42e99d8e1607c24592e1603248b94..0b9ca8c63666b14f7ce8e4bc1a7a81592d6c71f0 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -9,14 +9,16 @@ test "@max" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 { var x: i32 = 10; var y: f32 = 0.68; + var nan: f32 = std.math.nan(f32); try expect(@as(i32, 10) == @max(@as(i32, -3), x)); try expect(@as(f32, 3.2) == @max(@as(f32, 3.2), y)); + try expect(y == @max(nan, y)); + try expect(y == @max(y, nan)); } }; try S.doTheTest(); @@ -58,14 +60,16 @@ test "@min" { 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 { var x: i32 = 10; var y: f32 = 0.68; + var nan: f32 = std.math.nan(f32); try expect(@as(i32, -3) == @min(@as(i32, -3), x)); try expect(@as(f32, 0.68) == @min(@as(f32, 3.2), y)); + try expect(y == @min(nan, y)); + try expect(y == @min(y, nan)); } }; try S.doTheTest(); -- 2.54.0 From 839a93a101804bb41cb519a965dc62e3eb7deed0 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 16:57:53 +0200 Subject: [PATCH 23/36] intern pool: fix float equality We need to perform bitwise equality here, otherwise we get two different entries for nan values. --- src/InternPool.zig | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index 14490c21dbb513c78db62b229f201c3956a2cfc7..36a5c65deb8ff86570fde4ad696d06b65d88dd5f 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -1556,10 +1556,10 @@ pub const Key = union(enum) { // These are strange: we'll sometimes represent them as f128, even if the // underlying type is smaller. f80 is an exception: see float_c_longdouble_f80. const a_val = switch (a_info.storage) { - inline else => |val| @as(f128, @floatCast(val)), + inline else => |val| @as(u128, @bitCast(@as(f128, @floatCast(val)))), }; const b_val = switch (b_info.storage) { - inline else => |val| @as(f128, @floatCast(val)), + inline else => |val| @as(u128, @bitCast(@as(f128, @floatCast(val)))), }; return a_val == b_val; } @@ -1567,9 +1567,14 @@ pub const Key = union(enum) { const StorageTag = @typeInfo(Key.Float.Storage).Union.tag_type.?; assert(@as(StorageTag, a_info.storage) == @as(StorageTag, b_info.storage)); - return switch (a_info.storage) { - inline else => |val, tag| val == @field(b_info.storage, @tagName(tag)), - }; + switch (a_info.storage) { + inline else => |val, tag| { + const Bits = std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(val))); + const a_bits: Bits = @bitCast(val); + const b_bits: Bits = @bitCast(@field(b_info.storage, @tagName(tag))); + return a_bits == b_bits; + }, + } }, .opaque_type => |a_info| { -- 2.54.0 From dc44baf763f38ba3735d45fc4f633cac13949b0e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 17:02:59 +0200 Subject: [PATCH 24/36] std.testing: allow print() at comptime This allows functions like expectEqual to be performed at comptime. If an error is detected, the result is logged via a compile error. --- lib/std/testing.zig | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 4dda8a0d0def1ad9b38a0f11fb44ee7f033512f4..d4d162721d0971f29edef98ff1a8d8f2a53cc1d4 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -22,10 +22,14 @@ pub var base_allocator_instance = std.heap.FixedBufferAllocator.init(""); pub var log_level = std.log.Level.warn; fn print(comptime fmt: []const u8, args: anytype) void { - // Disable printing in tests for simple backends. - if (builtin.zig_backend == .stage2_spirv64) return; + if (@inComptime()) { + @compileError(std.fmt.comptimePrint(fmt, args)); + } else { + // Disable printing in tests for simple backends. + if (builtin.zig_backend == .stage2_spirv64) return; - std.debug.print(fmt, args); + std.debug.print(fmt, args); + } } /// This function is intended to be used only in tests. It prints diagnostics to stderr -- 2.54.0 From b1499df1b88b0fa25c4d7e4a16cb1715db452227 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 18:52:58 +0200 Subject: [PATCH 25/36] spirv: sign-extension for strange integers --- src/codegen/spirv.zig | 70 +++++++++++++++++++++++++++++++++--------- test/behavior/math.zig | 3 ++ 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 42a11120b5bff592e23ffb906bf8b25ba973c7bc..fab69da39bf6c5cec8b1bb4ec246d2b9eecf0964 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -270,6 +270,12 @@ const DeclGen = struct { /// This is the actual number of bits of the type, not the size of the backing integer. bits: u16, + /// The number of bits required to store the type. + /// For `integer` and `float`, this is equal to `bits`. + /// For `strange_integer` and `bool` this is the size of the backing integer. + /// For `composite_integer` this is 0 (TODO) + backing_bits: u16, + /// Whether the type is a vector. is_vector: bool, @@ -499,12 +505,14 @@ const DeclGen = struct { return switch (ty.zigTypeTag(mod)) { .Bool => ArithmeticTypeInfo{ .bits = 1, // Doesn't matter for this class. + .backing_bits = self.backingIntBits(1).?, .is_vector = false, .signedness = .unsigned, // Technically, but doesn't matter for this class. .class = .bool, }, .Float => ArithmeticTypeInfo{ .bits = ty.floatBits(target), + .backing_bits = ty.floatBits(target), // TODO: F80? .is_vector = false, .signedness = .signed, // Technically, but doesn't matter for this class. .class = .float, @@ -515,6 +523,7 @@ const DeclGen = struct { const maybe_backing_bits = self.backingIntBits(int_info.bits); break :blk ArithmeticTypeInfo{ .bits = int_info.bits, + .backing_bits = maybe_backing_bits orelse 0, .is_vector = false, .signedness = int_info.signedness, .class = if (maybe_backing_bits) |backing_bits| @@ -2154,17 +2163,48 @@ const DeclGen = struct { return result_id; } - fn maskStrangeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, bits: u16) !IdRef { - const mask_value = if (bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(bits))) - 1; - const result_id = self.spv.allocId(); - const mask_id = try self.constInt(ty_ref, mask_value); - try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ - .id_result_type = self.typeId(ty_ref), - .id_result = result_id, - .operand_1 = value_id, - .operand_2 = mask_id, - }); - return result_id; + /// This function canonicalizes a "strange" integer value: + /// For unsigned integers, the value is masked so that only the relevant bits can contain + /// non-zeros. + /// For signed integers, the value is also sign extended. + fn normalizeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, info: ArithmeticTypeInfo) !IdRef { + if (info.bits == info.backing_bits) { + return value_id; + } + + switch (info.signedness) { + .unsigned => { + const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; + const result_id = self.spv.allocId(); + const mask_id = try self.constInt(ty_ref, mask_value); + try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ + .id_result_type = self.typeId(ty_ref), + .id_result = result_id, + .operand_1 = value_id, + .operand_2 = mask_id, + }); + return result_id; + }, + .signed => { + // Shift left and right so that we can copy the sight bit that way. + const shift_amt_id = try self.constInt(ty_ref, info.backing_bits - info.bits); + const left_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{ + .id_result_type = self.typeId(ty_ref), + .id_result = left_id, + .base = value_id, + .shift = shift_amt_id, + }); + const right_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{ + .id_result_type = self.typeId(ty_ref), + .id_result = right_id, + .base = left_id, + .shift = shift_amt_id, + }); + return right_id; + }, + } } fn airArithOp( @@ -2199,8 +2239,8 @@ const DeclGen = struct { }, .strange_integer => blk: { if (!modular) { - lhs_id = try self.maskStrangeInt(result_ty_ref, lhs_id, info.bits); - rhs_id = try self.maskStrangeInt(result_ty_ref, rhs_id, info.bits); + lhs_id = try self.normalizeInt(result_ty_ref, lhs_id, info); + rhs_id = try self.normalizeInt(result_ty_ref, rhs_id, info); } break :blk switch (info.signedness) { .signed => @as(usize, 1), @@ -2565,8 +2605,8 @@ const DeclGen = struct { .strange_integer => sign: { const op_ty_ref = try self.resolveType(op_ty, .direct); // Mask operands before performing comparison. - cmp_lhs_id = try self.maskStrangeInt(op_ty_ref, cmp_lhs_id, info.bits); - cmp_rhs_id = try self.maskStrangeInt(op_ty_ref, cmp_rhs_id, info.bits); + cmp_lhs_id = try self.normalizeInt(op_ty_ref, cmp_lhs_id, info); + cmp_rhs_id = try self.normalizeInt(op_ty_ref, cmp_rhs_id, info); break :sign info.signedness; }, .integer => info.signedness, diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 0bf1e93078f5e196ad050fd75c711497aec323c5..aec2920eb1038bfb484efe509402099cff94c9a6 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -468,6 +468,9 @@ fn testDivision() !void { try expect(mod(i32, -14, -12) == -2); try expect(mod(i32, -2, -12) == -2); + try expect(divTrunc(i20, 20, -5) == -4); + try expect(divTrunc(i20, -20, -4) == 5); + comptime { try expect( 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, -- 2.54.0 From e2e4e1f8b4fa5d8394cb571d00b4b62eacea97df Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 20:26:15 +0200 Subject: [PATCH 26/36] spirv: intcast, trunc for strange ints --- src/codegen/spirv.zig | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index fab69da39bf6c5cec8b1bb4ec246d2b9eecf0964..6fff39f95145db68870751203d6d5cff0bbd3178 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -535,6 +535,7 @@ const DeclGen = struct { .composite_integer, }; }, + .Enum => return self.arithmeticTypeInfo(ty.intTagType(mod)), // As of yet, there is no vector support in the self-hosted compiler. .Vector => self.todo("implement arithmeticTypeInfo for Vector", .{}), // TODO: For which types is this the case? @@ -2168,6 +2169,7 @@ const DeclGen = struct { /// non-zeros. /// For signed integers, the value is also sign extended. fn normalizeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, info: ArithmeticTypeInfo) !IdRef { + assert(info.class != .composite_integer); // TODO if (info.bits == info.backing_bits) { return value_id; } @@ -2731,25 +2733,33 @@ const DeclGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand_id = try self.resolve(ty_op.operand); - const dest_ty = self.typeOfIndex(inst); - const dest_ty_id = try self.resolveTypeId(dest_ty); + const src_ty = self.typeOf(ty_op.operand); + const dst_ty = self.typeOfIndex(inst); + const src_ty_ref = try self.resolveType(src_ty, .direct); + const dst_ty_ref = try self.resolveType(dst_ty, .direct); - const mod = self.module; - const dest_info = dest_ty.intInfo(mod); + const src_info = try self.arithmeticTypeInfo(src_ty); + const dst_info = try self.arithmeticTypeInfo(dst_ty); - // TODO: Masking? + // While intcast promises that the value already fits, the upper bits of a + // strange integer may contain garbage. Therefore, mask/sign extend it before. + const src_id = try self.normalizeInt(src_ty_ref, operand_id, src_info); + + if (src_info.backing_bits == dst_info.backing_bits) { + return src_id; + } const result_id = self.spv.allocId(); - switch (dest_info.signedness) { + switch (dst_info.signedness) { .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{ - .id_result_type = dest_ty_id, + .id_result_type = self.typeId(dst_ty_ref), .id_result = result_id, - .signed_value = operand_id, + .signed_value = src_id, }), .unsigned => try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ - .id_result_type = dest_ty_id, + .id_result_type = self.typeId(dst_ty_ref), .id_result = result_id, - .unsigned_value = operand_id, + .unsigned_value = src_id, }), } return result_id; -- 2.54.0 From 3ca1f888980641c9d9aff02100f277833b988413 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 21:00:20 +0200 Subject: [PATCH 27/36] std.testing: disable expectEqualSlices printing for spirv --- lib/std/testing.zig | 12 ++++++++---- test/behavior/basic.zig | 1 - test/behavior/cast.zig | 10 ---------- test/behavior/src.zig | 1 - test/behavior/struct.zig | 1 - 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/lib/std/testing.zig b/lib/std/testing.zig index d4d162721d0971f29edef98ff1a8d8f2a53cc1d4..95f1b156c1376ae28543e7d453641ad58206dfa6 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -21,13 +21,13 @@ pub var base_allocator_instance = std.heap.FixedBufferAllocator.init(""); /// TODO https://github.com/ziglang/zig/issues/5738 pub var log_level = std.log.Level.warn; +// Disable printing in tests for simple backends. +pub const backend_can_print = builtin.zig_backend != .stage2_spirv64; + fn print(comptime fmt: []const u8, args: anytype) void { if (@inComptime()) { @compileError(std.fmt.comptimePrint(fmt, args)); - } else { - // Disable printing in tests for simple backends. - if (builtin.zig_backend == .stage2_spirv64) return; - + } else if (backend_can_print) { std.debug.print(fmt, args); } } @@ -304,6 +304,10 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const break :diff_index if (expected.len == actual.len) return else shortest; }; + if (!backend_can_print) { + return error.TestExpectedEqual; + } + print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); // TODO: Should this be configurable by the caller? diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index f91bbe6edf7780dbdd0a2f2d52e24ede1bf661b9..3436cba9ba0efef445ef89f1b5fbc84c4a990fa7 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -644,7 +644,6 @@ test "string escapes" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expectEqualStrings("\"", "\x22"); try expectEqualStrings("\'", "\x27"); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 20867fa7e8fc65d8b360e5f2e0a7db465c7f9cf1..69e8c88b794db9dc4e5369073763cc0c2778f7eb 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -385,7 +385,6 @@ test "cast from ?[*]T to ??[*]T" { test "peer type unsigned int to signed" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var w: u31 = 5; var x: u8 = 7; @@ -1552,8 +1551,6 @@ test "single item pointer to pointer to array to slice" { } test "peer type resolution forms error union" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var foo: i32 = 123; const result = if (foo < 0) switch (-foo) { 0 => unreachable, @@ -1641,7 +1638,6 @@ test "peer type resolution: same array type with sentinel" { 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; // TODO var a: [2:0]u32 = .{ 0, 1 }; var b: [2:0]u32 = .{ 2, 3 }; @@ -1662,7 +1658,6 @@ test "peer type resolution: array with sentinel and array without sentinel" { 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; // TODO var a: [2:0]u32 = .{ 0, 1 }; var b: [2]u32 = .{ 2, 3 }; @@ -1852,7 +1847,6 @@ test "peer type resolution: array and tuple" { 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; // TODO var arr: [3]i32 = .{ 1, 2, 3 }; const tup = .{ 4, 5, 6 }; @@ -1939,7 +1933,6 @@ test "peer type resolution: empty tuple pointer and slice" { 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; // TODO var a: [:0]const u8 = "Hello"; var b = &.{}; @@ -1959,7 +1952,6 @@ test "peer type resolution: tuple pointer and slice" { 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; // TODO var a: [:0]const u8 = "Hello"; var b = &.{ @as(u8, 'x'), @as(u8, 'y'), @as(u8, 'z') }; @@ -1979,7 +1971,6 @@ test "peer type resolution: tuple pointer and optional slice" { 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; // TODO var a: ?[:0]const u8 = null; var b = &.{ @as(u8, 'x'), @as(u8, 'y'), @as(u8, 'z') }; @@ -2117,7 +2108,6 @@ test "peer type resolution: pointer attributes are combined correctly" { 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; // TODO var buf_a align(4) = "foo".*; var buf_b align(4) = "bar".*; diff --git a/test/behavior/src.zig b/test/behavior/src.zig index 9c81bcde89a3b882c4a9c001e6153309f040b4c4..71c2753dad912274afda30b05c7ea4798711f21a 100644 --- a/test/behavior/src.zig +++ b/test/behavior/src.zig @@ -17,7 +17,6 @@ test "@src" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try doTheTest(); } diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 316bc6d2ccc03b377f48f4e20ddb1ff8372db02c..a914ff946c271882e423d9f34040f85c76610ab4 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -954,7 +954,6 @@ test "tuple element initialized with fn call" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 { -- 2.54.0 From 10b8171466f6a2572cea0b8e70eba33be0020ac2 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 21:21:15 +0200 Subject: [PATCH 28/36] spirv: handle errors in switch --- src/codegen/spirv.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 6fff39f95145db68870751203d6d5cff0bbd3178..bb2fe4219c0edc86ae37a7e21aaebd6d43ae5e01 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -3924,6 +3924,7 @@ const DeclGen = struct { }; break :blk if (backing_bits <= 32) @as(u32, 1) else 2; }, + .ErrorSet => 1, else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag(mod))}), // TODO: Figure out which types apply here, and work around them as we can only do integers. }; @@ -3977,6 +3978,7 @@ const DeclGen = struct { // TODO: figure out of cond_ty is correct (something with enum literals) break :blk (try value.intFromEnum(cond_ty, mod)).toUnsignedInt(mod); // TODO: composite integer constants }, + .ErrorSet => value.getErrorInt(mod), else => unreachable, }; const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) { -- 2.54.0 From f4064d98e23eaa4ad0ec76aca7a341d3e923e86e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 12 Oct 2023 22:09:34 +0200 Subject: [PATCH 29/36] spirv: optional comparison --- src/codegen/spirv.zig | 159 ++++++++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 54 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index bb2fe4219c0edc86ae37a7e21aaebd6d43ae5e01..c9c11dd44ead95dfe1a95cf2567650a9b2f9b32d 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -52,12 +52,6 @@ const Block = struct { const BlockMap = std.AutoHashMapUnmanaged(Air.Inst.Index, *Block); -/// Maps Zig decl indices to SPIR-V linking information. -pub const DeclLinkMap = std.AutoHashMapUnmanaged(Decl.Index, SpvModule.Decl.Index); - -/// Maps anon decl indices to SPIR-V linking information. -pub const AnonDeclLinkMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index); - /// This structure holds information that is relevant to the entire compilation, /// in contrast to `DeclGen`, which only holds relevant information about a /// single decl. @@ -70,10 +64,10 @@ pub const Object = struct { /// The Zig module that this object file is generated for. /// A map of Zig decl indices to SPIR-V decl indices. - decl_link: DeclLinkMap = .{}, + decl_link: std.AutoHashMapUnmanaged(Decl.Index, SpvModule.Decl.Index) = .{}, /// A map of Zig InternPool indices for anonymous decls to SPIR-V decl indices. - anon_decl_link: AnonDeclLinkMap = .{}, + anon_decl_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .{}, /// A map that maps AIR intern pool indices to SPIR-V cache references (which /// is basically the same thing except for SPIR-V). @@ -1266,22 +1260,32 @@ const DeclGen = struct { const elem_ty = ty.childType(mod); const elem_ty_ref = try self.resolveType(elem_ty, .indirect); - const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse { + var total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse { return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)}); }; - if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { + const ty_ref = if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: { + // The size of the array would be 0, but that is not allowed in SPIR-V. + // This path can be reached when the backend is asked to generate a pointer to + // an array of some zero-bit type. This should always be an indirect path. + assert(repr == .indirect); + + // We cannot use the child type here, so just use an opaque type. + break :blk try self.spv.resolve(.{ .opaque_type = .{ + .name = try self.spv.resolveString("zero-sized array"), + } }); + } else if (total_len == 0) blk: { // The size of the array would be 0, but that is not allowed in SPIR-V. // This path can be reached for example when there is a slicing of a pointer // that produces a zero-length array. In all cases where this type can be generated, - // we should be in an indirect path (direct uses of this type should be filtered out in Sema). + // this should be an indirect path. assert(repr == .indirect); - return try self.spv.resolve(.{ .opaque_type = .{ - .name = try self.spv.resolveString("zero-sized array"), - } }); - } + // In this case, we have an array of a non-zero sized type. In this case, + // generate an array of 1 element instead, so that ptr_elem_ptr instructions + // can be lowered to ptrAccessChain instead of manually performing the math. + break :blk try self.spv.arrayType(1, elem_ty_ref); + } else try self.spv.arrayType(total_len, elem_ty_ref); - const ty_ref = try self.spv.arrayType(total_len, elem_ty_ref); try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); return ty_ref; }, @@ -2554,38 +2558,85 @@ const DeclGen = struct { var cmp_lhs_id = lhs_id; var cmp_rhs_id = rhs_id; const bool_ty_ref = try self.resolveType(Type.bool, .direct); + const op_ty = switch (ty.zigTypeTag(mod)) { + .Int, .Bool, .Float => ty, + .Enum => ty.intTagType(mod), + .ErrorSet => Type.u16, + .Pointer => blk: { + // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are + // currently not implemented in the SPIR-V LLVM translator. Thus, we emit these using + // OpConvertPtrToU... + cmp_lhs_id = self.spv.allocId(); + cmp_rhs_id = self.spv.allocId(); + + const usize_ty_id = self.typeId(try self.sizeType()); + + try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ + .id_result_type = usize_ty_id, + .id_result = cmp_lhs_id, + .pointer = lhs_id, + }); + + try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ + .id_result_type = usize_ty_id, + .id_result = cmp_rhs_id, + .pointer = rhs_id, + }); + + break :blk Type.usize; + }, + .Optional => { + const payload_ty = ty.optionalChild(mod); + if (ty.optionalReprIsPayload(mod)) { + assert(payload_ty.hasRuntimeBitsIgnoreComptime(mod)); + assert(!payload_ty.isSlice(mod)); + return self.cmp(op, payload_ty, lhs_id, rhs_id); + } + + const lhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) + try self.extractField(Type.bool, lhs_id, 1) + else + try self.convertToDirect(Type.bool, lhs_id); + + const rhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) + try self.extractField(Type.bool, rhs_id, 1) + else + try self.convertToDirect(Type.bool, rhs_id); + + const valid_cmp_id = try self.cmp(op, Type.bool, lhs_valid_id, rhs_valid_id); + if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + return valid_cmp_id; + } + + // TODO: Should we short circuit here? It shouldn't affect correctness, but + // perhaps it will generate more efficient code. + + const lhs_pl_id = try self.extractField(payload_ty, lhs_id, 0); + const rhs_pl_id = try self.extractField(payload_ty, rhs_id, 0); + + const pl_cmp_id = try self.cmp(op, payload_ty, lhs_pl_id, rhs_pl_id); + + // op == .eq => lhs_valid == rhs_valid && lhs_pl == rhs_pl + // op == .neq => lhs_valid != rhs_valid || lhs_pl != rhs_pl + + const result_id = self.spv.allocId(); + const args = .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = result_id, + .operand_1 = valid_cmp_id, + .operand_2 = pl_cmp_id, + }; + switch (op) { + .eq => try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, args), + .neq => try self.func.body.emit(self.spv.gpa, .OpLogicalOr, args), + else => unreachable, + } + return result_id; + }, + else => unreachable, + }; + const opcode: Opcode = opcode: { - const op_ty = switch (ty.zigTypeTag(mod)) { - .Int, .Bool, .Float => ty, - .Enum => ty.intTagType(mod), - .ErrorSet => Type.u16, - .Pointer => blk: { - // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are - // currently not implemented in the SPIR-V LLVM translator. Thus, we emit these using - // OpConvertPtrToU... - cmp_lhs_id = self.spv.allocId(); - cmp_rhs_id = self.spv.allocId(); - - const usize_ty_id = self.typeId(try self.sizeType()); - - try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ - .id_result_type = usize_ty_id, - .id_result = cmp_lhs_id, - .pointer = lhs_id, - }); - - try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ - .id_result_type = usize_ty_id, - .id_result = cmp_rhs_id, - .pointer = rhs_id, - }); - - break :blk Type.usize; - }, - .Optional => unreachable, // TODO - else => unreachable, - }; - const info = try self.arithmeticTypeInfo(op_ty); const signedness = switch (info.class) { .composite_integer => { @@ -2653,7 +2704,6 @@ const DeclGen = struct { const lhs_id = try self.resolve(bin_op.lhs); const rhs_id = try self.resolve(bin_op.rhs); const ty = self.typeOf(bin_op.lhs); - assert(ty.eql(self.typeOf(bin_op.rhs), self.module)); return try self.cmp(op, ty, lhs_id, rhs_id); } @@ -3061,16 +3111,17 @@ const DeclGen = struct { const mod = self.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; - const ptr_ty = self.typeOf(bin_op.lhs); - const elem_ty = ptr_ty.childType(mod); + const src_ptr_ty = self.typeOf(bin_op.lhs); + const elem_ty = src_ptr_ty.childType(mod); + const ptr_id = try self.resolve(bin_op.lhs); + if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) { - const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); - return try self.spv.constUndef(ptr_ty_ref); + const dst_ptr_ty = self.typeOfIndex(inst); + return try self.bitCast(dst_ptr_ty, src_ptr_ty, ptr_id); } - const ptr_id = try self.resolve(bin_op.lhs); const index_id = try self.resolve(bin_op.rhs); - return try self.ptrElemPtr(ptr_ty, ptr_id, index_id); + return try self.ptrElemPtr(src_ptr_ty, ptr_id, index_id); } fn airArrayElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { -- 2.54.0 From 245c0847265d3b0b904747ac4be298fe763a4454 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Mon, 9 Oct 2023 19:45:22 +0200 Subject: [PATCH 30/36] add Snektron to CODEOWNERS for SPIR-V --- .github/CODEOWNERS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4c8e64768b522f3d774073f6e98cdc130e6c0905..c912f561c61bafa6d700bf16d8befc5d7002bf67 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ -# Autodoc +# Autodoc /src/Autodoc.zig @kristoff-it /src/autodoc/* @kristoff-it /lib/docs/* @kristoff-it @@ -11,3 +11,6 @@ # resinator /src/resinator/* @squeek502 + +# SPIR-V selfhosted backend +/src/codegen/spirv* @Snektron -- 2.54.0 From 2fe16e072ac447de5826ee436f50f73f56876ff9 Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Thu, 12 Oct 2023 22:55:22 +0330 Subject: [PATCH 31/36] spirv: emit vectors as arrays --- src/codegen/spirv.zig | 85 ++++++++++++++++++++++++++++++---------- test/behavior/vector.zig | 1 - 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index c9c11dd44ead95dfe1a95cf2567650a9b2f9b32d..3a5c9b876b9e2d981e9d3b9f903eeaf27d2ad43a 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -531,7 +531,17 @@ const DeclGen = struct { }, .Enum => return self.arithmeticTypeInfo(ty.intTagType(mod)), // As of yet, there is no vector support in the self-hosted compiler. - .Vector => self.todo("implement arithmeticTypeInfo for Vector", .{}), + .Vector => blk: { + const child_type = ty.childType(mod); + const child_ty_info = try self.arithmeticTypeInfo(child_type); + break :blk ArithmeticTypeInfo{ + .bits = child_ty_info.bits, + .backing_bits = child_ty_info.backing_bits, + .is_vector = true, + .signedness = child_ty_info.signedness, + .class = child_ty_info.class, + }; + }, // TODO: For which types is this the case? // else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), else => unreachable, @@ -609,7 +619,7 @@ const DeclGen = struct { return result_id; } - /// Construct a struct at runtime. + /// Construct an array at runtime. /// result_ty_ref must be an array type. /// Constituents should be in `indirect` representation (as the elements of an array should be). /// Result is in `direct` representation. @@ -812,7 +822,7 @@ const DeclGen = struct { return try self.constructStruct(result_ty_ref, &.{ payload_id, has_pl_id }); }, .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) { - .array_type => |array_type| { + inline .array_type, .vector_type => |array_type, tag| { const elem_ty = array_type.child.toType(); const elem_ty_ref = try self.resolveType(elem_ty, .indirect); @@ -839,9 +849,14 @@ const DeclGen = struct { } }, } - if (array_type.sentinel != .none) { - constituents[constituents.len - 1] = try self.constant(elem_ty, array_type.sentinel.toValue(), .indirect); + + switch (tag) { + inline .array_type => if (array_type.sentinel != .none) { + constituents[constituents.len - 1] = try self.constant(elem_ty, array_type.sentinel.toValue(), .indirect); + }, + else => {}, } + return try self.constructArray(result_ty_ref, constituents); }, .struct_type => { @@ -870,7 +885,6 @@ const DeclGen = struct { return try self.constructStruct(result_ty_ref, constituents.items); }, - .vector_type => unreachable, // TODO .anon_struct_type => unreachable, // TODO else => unreachable, }, @@ -1347,19 +1361,14 @@ const DeclGen = struct { } }); }, .Vector => { - // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations - // which work on them), so simply use those. - // Note: SPIR-V vectors only support bools, ints and floats, so pointer vectors need to be supported another way. - // "composite integers" (larger than the largest supported native type) can probably be represented by an array of vectors. - // TODO: The SPIR-V spec mentions that vector sizes may be quite restricted! look into which we can use, and whether OpTypeVector - // is adequate at all for this. + if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref; - // TODO: Properly verify sizes and child type. + const elem_ty = ty.childType(mod); + const elem_ty_ref = try self.resolveType(elem_ty, .indirect); - return try self.spv.resolve(.{ .vector_type = .{ - .component_type = try self.resolveType(ty.childType(mod), repr), - .component_count = @as(u32, @intCast(ty.vectorLen(mod))), - } }); + const ty_ref = try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref); + try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); + return ty_ref; }, .Struct => { if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref; @@ -2223,18 +2232,52 @@ const DeclGen = struct { comptime modular: bool, ) !?IdRef { if (self.liveness.isUnused(inst)) return null; + // LHS and RHS are guaranteed to have the same type, and AIR guarantees // the result to be the same as the LHS and RHS, which matches SPIR-V. const ty = self.typeOfIndex(inst); const bin_op = self.air.instructions.items(.data)[inst].bin_op; - var lhs_id = try self.resolve(bin_op.lhs); - var rhs_id = try self.resolve(bin_op.rhs); - - const result_ty_ref = try self.resolveType(ty, .direct); + const lhs_id = try self.resolve(bin_op.lhs); + const rhs_id = try self.resolve(bin_op.rhs); assert(self.typeOf(bin_op.lhs).eql(ty, self.module)); assert(self.typeOf(bin_op.rhs).eql(ty, self.module)); + return try self.arithOp(ty, lhs_id, rhs_id, fop, sop, uop, modular); + } + + fn arithOp( + self: *DeclGen, + ty: Type, + lhs_id_: IdRef, + rhs_id_: IdRef, + comptime fop: Opcode, + comptime sop: Opcode, + comptime uop: Opcode, + /// true if this operation holds under modular arithmetic. + comptime modular: bool, + ) !IdRef { + var rhs_id = rhs_id_; + var lhs_id = lhs_id_; + + const mod = self.module; + const result_ty_ref = try self.resolveType(ty, .direct); + + if (ty.isVector(mod)) { + const child_ty = ty.childType(mod); + const vector_len = ty.vectorLen(mod); + var constituents = try self.gpa.alloc(IdRef, vector_len); + defer self.gpa.free(constituents); + + for (constituents, 0..) |*constituent, i| { + const lhs_index_id = try self.extractField(child_ty, lhs_id, @intCast(i)); + const rhs_index_id = try self.extractField(child_ty, rhs_id, @intCast(i)); + constituent.* = try self.arithOp(child_ty, lhs_index_id, rhs_index_id, fop, sop, uop, modular); + } + + return self.constructArray(result_ty_ref, constituents); + } + // Binary operations are generally applicable to both scalar and vector operations // in SPIR-V, but int and float versions of operations require different opcodes. const info = try self.arithmeticTypeInfo(ty); diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 81e51f49835ec34d1f47f3041e86cec2637321c5..ed118be6414cb62b4f828728b7c5ced554766be1 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -29,7 +29,6 @@ test "vector wrap operators" { 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; if (builtin.zig_backend == .stage2_x86_64 and !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO -- 2.54.0 From 9c20449cc5be5da0458556e143980b40d51e8776 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 14 Oct 2023 12:52:31 +0200 Subject: [PATCH 32/36] wasm: lower min/max for floats to compiler_rt The min and max builtins in Zig have some intricate behavior related to floats, that is not replicated with the min and max wasm instructions or using simple select operations. By lowering these instructions to compiler_rt, handling around NaNs is done correctly. See also https://github.com/WebAssembly/design/issues/214 --- src/arch/wasm/CodeGen.zig | 28 +++++++++++++++++++++------- test/behavior/maximum_minimum.zig | 6 ++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index ebcccd781d72edd1e531806c18c7f8343060c818..3eac273164e17c8481e11a96926a655415ea139c 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -6253,8 +6253,10 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); } -fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerError!void { +fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { + assert(op == .max or op == .min); const mod = func.bin_file.base.options.module.?; + const target = mod.getTarget(); const bin_op = func.air.instructions.items(.data)[inst].bin_op; const ty = func.typeOfIndex(inst); @@ -6269,13 +6271,25 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE const lhs = try func.resolveInst(bin_op.lhs); const rhs = try func.resolveInst(bin_op.rhs); - // operands to select from - try func.lowerToStack(lhs); - try func.lowerToStack(rhs); - _ = try func.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt); + if (ty.zigTypeTag(mod) == .Float) { + var fn_name_buf: [64]u8 = undefined; + const float_bits = ty.floatBits(target); + const fn_name = std.fmt.bufPrint(&fn_name_buf, "{s}f{s}{s}", .{ + target_util.libcFloatPrefix(float_bits), + @tagName(op), + target_util.libcFloatSuffix(float_bits), + }) catch unreachable; + const result = try func.callIntrinsic(fn_name, &.{ ty.ip_index, ty.ip_index }, ty, &.{ lhs, rhs }); + try func.lowerToStack(result); + } else { + // operands to select from + try func.lowerToStack(lhs); + try func.lowerToStack(rhs); + _ = try func.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt); - // based on the result from comparison, return operand 0 or 1. - try func.addTag(.select); + // based on the result from comparison, return operand 0 or 1. + try func.addTag(.select); + } // store result in local const result_ty = if (isByRef(ty, mod)) Type.u32 else ty; diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index 0b9ca8c63666b14f7ce8e4bc1a7a81592d6c71f0..ecc32a33f6a6df0967e29272549813cc29c7b066 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -123,6 +123,12 @@ test "@min/max for floats" { try expectEqual(x, @min(y, x)); try expectEqual(y, @max(x, y)); try expectEqual(y, @max(y, x)); + + if (T != comptime_float) { + var nan: T = std.math.nan(T); + try expectEqual(y, @max(nan, y)); + try expectEqual(y, @max(y, nan)); + } } }; -- 2.54.0 From 45a1945dc4a77fb757725d977a6e385a21793a98 Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Sat, 14 Oct 2023 04:05:04 +0330 Subject: [PATCH 33/36] spirv: simple binary and comparison vector operations --- src/codegen/spirv.zig | 90 +++++++++++++++++++++++++++++++++------- test/behavior/vector.zig | 19 --------- 2 files changed, 75 insertions(+), 34 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3a5c9b876b9e2d981e9d3b9f903eeaf27d2ad43a..0f0adf5646a5fa5d9a16b8aa3d41da865e1d0da5 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2027,12 +2027,13 @@ const DeclGen = struct { .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2), .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3), - .cmp_eq => try self.airCmp(inst, .eq), - .cmp_neq => try self.airCmp(inst, .neq), - .cmp_gt => try self.airCmp(inst, .gt), - .cmp_gte => try self.airCmp(inst, .gte), - .cmp_lt => try self.airCmp(inst, .lt), - .cmp_lte => try self.airCmp(inst, .lte), + .cmp_eq => try self.airCmp(inst, .eq), + .cmp_neq => try self.airCmp(inst, .neq), + .cmp_gt => try self.airCmp(inst, .gt), + .cmp_gte => try self.airCmp(inst, .gte), + .cmp_lt => try self.airCmp(inst, .lt), + .cmp_lte => try self.airCmp(inst, .lte), + .cmp_vector => try self.airVectorCmp(inst), .arg => self.airArg(), .alloc => try self.airAlloc(inst), @@ -2088,20 +2089,48 @@ const DeclGen = struct { try self.inst_results.putNoClobber(self.gpa, inst, result_id); } + fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef { + const mod = self.module; + + if (ty.isVector(mod)) { + const child_ty = ty.childType(mod); + const vector_len = ty.vectorLen(mod); + + var constituents = try self.gpa.alloc(IdRef, vector_len); + defer self.gpa.free(constituents); + + for (constituents, 0..) |*constituent, i| { + const lhs_index_id = try self.extractField(child_ty, lhs_id, @intCast(i)); + const rhs_index_id = try self.extractField(child_ty, rhs_id, @intCast(i)); + const result_id = try self.binOpSimple(child_ty, lhs_index_id, rhs_index_id, opcode); + constituent.* = try self.convertToIndirect(child_ty, result_id); + } + + const result_ty = try self.resolveType(child_ty, .indirect); + const result_ty_ref = try self.spv.arrayType(vector_len, result_ty); + return try self.constructArray(result_ty_ref, constituents); + } + + const result_id = self.spv.allocId(); + const result_type_id = try self.resolveTypeId(ty); + try self.func.body.emit(self.spv.gpa, opcode, .{ + .id_result_type = result_type_id, + .id_result = result_id, + .operand_1 = lhs_id, + .operand_2 = rhs_id, + }); + return result_id; + } + fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { if (self.liveness.isUnused(inst)) return null; + const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs_id = try self.resolve(bin_op.lhs); const rhs_id = try self.resolve(bin_op.rhs); - const result_id = self.spv.allocId(); - const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst)); - try self.func.body.emit(self.spv.gpa, opcode, .{ - .id_result_type = result_type_id, - .id_result = result_id, - .operand_1 = lhs_id, - .operand_2 = rhs_id, - }); - return result_id; + const ty = self.typeOf(bin_op.lhs); + + return try self.binOpSimple(ty, lhs_id, rhs_id, opcode); } fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { @@ -2676,6 +2705,24 @@ const DeclGen = struct { } return result_id; }, + .Vector => { + const child_ty = ty.childType(mod); + const vector_len = ty.vectorLen(mod); + const bool_ty_ref_indirect = try self.resolveType(Type.bool, .indirect); + + var constituents = try self.gpa.alloc(IdRef, vector_len); + defer self.gpa.free(constituents); + + for (constituents, 0..) |*constituent, i| { + const lhs_index_id = try self.extractField(child_ty, cmp_lhs_id, @intCast(i)); + const rhs_index_id = try self.extractField(child_ty, cmp_rhs_id, @intCast(i)); + const result_id = try self.cmp(op, child_ty, lhs_index_id, rhs_index_id); + constituent.* = try self.convertToIndirect(Type.bool, result_id); + } + + const result_ty_ref = try self.spv.arrayType(vector_len, bool_ty_ref_indirect); + return try self.constructArray(result_ty_ref, constituents); + }, else => unreachable, }; @@ -2751,6 +2798,19 @@ const DeclGen = struct { return try self.cmp(op, ty, lhs_id, rhs_id); } + fn airVectorCmp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const vec_cmp = self.air.extraData(Air.VectorCmp, ty_pl.payload).data; + const lhs_id = try self.resolve(vec_cmp.lhs); + const rhs_id = try self.resolve(vec_cmp.rhs); + const op = vec_cmp.compareOperator(); + const ty = self.typeOf(vec_cmp.lhs); + + return try self.cmp(op, ty, lhs_id, rhs_id); + } + fn bitCast( self: *DeclGen, dst_ty: Type, diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index ed118be6414cb62b4f828728b7c5ced554766be1..caf92f17cbb6785b1d870800518de3d0b27d979f 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -53,7 +53,6 @@ test "vector bin compares with mem.eql" { 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 { @@ -123,7 +122,6 @@ test "vector bit operators" { 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 { @@ -142,7 +140,6 @@ test "implicit cast vector to array" { 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 { @@ -160,7 +157,6 @@ test "array to vector" { 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 { @@ -285,7 +281,6 @@ test "vector casts of sizes not divisible by 8" { 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 { @@ -366,7 +361,6 @@ test "load vector elements via comptime index" { 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 { @@ -388,7 +382,6 @@ test "store vector elements via comptime index" { 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 { @@ -416,7 +409,6 @@ test "load vector elements via runtime index" { 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 { @@ -438,7 +430,6 @@ test "store vector elements via runtime index" { 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 { @@ -461,7 +452,6 @@ test "initialize vector which is a struct field" { 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 Vec4Obj = struct { data: @Vector(4, f32), @@ -485,7 +475,6 @@ test "vector comparison operators" { 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 { @@ -1167,7 +1156,6 @@ test "loading the second vector from a slice of vectors" { 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; @setRuntimeSafety(false); var small_bases = [2]@Vector(2, u8){ @@ -1184,7 +1172,6 @@ test "array of vectors is copied" { 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 Vec3 = @Vector(3, i32); var points = [_]Vec3{ @@ -1255,7 +1242,6 @@ test "zero multiplicand" { 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 zeros = @Vector(2, u32){ 0.0, 0.0 }; var ones = @Vector(2, u32){ 1.0, 1.0 }; @@ -1316,7 +1302,6 @@ test "load packed vector element" { 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; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO @@ -1347,7 +1332,6 @@ test "store to vector in slice" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var v = [_]@Vector(3, f32){ .{ 1, 1, 1 }, @@ -1411,7 +1395,6 @@ test "store vector with memset" { test "addition of vectors represented as strings" { 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; const V = @Vector(3, u8); const foo: V = "foo".*; @@ -1437,7 +1420,6 @@ test "vector pointer is indexable" { if (builtin.zig_backend == .stage2_arm) 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; // TODO const V = @Vector(2, u32); @@ -1478,7 +1460,6 @@ test "bitcast to vector with different child type" { if (builtin.zig_backend == .stage2_arm) 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; // TODO const S = struct { fn doTheTest() !void { -- 2.54.0 From 0552e504d061c428655536b82db3bda21d97ef3c Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 15 Oct 2023 16:47:48 +0200 Subject: [PATCH 34/36] spirv: work around OpSource parsing issue in llvm-spirv The Khronos SPIRV-LLVM translator does not parse OpSource correctly. This was causing tests to fail and other mysterious issues. These are resolved by only generating a single OpSource instruction for now, which does not have the source file locations also. See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/2188 --- src/codegen/spirv/Module.zig | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index c16e1a6d72d746656d8fa07f95bcf8272cc92628..1936b788260efccd6ff8122b22d79fced9002149 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -415,6 +415,18 @@ pub fn flush(self: *Module, file: std.fs.File) !void { 0, // Schema (currently reserved for future use) }; + var source = Section{}; + defer source.deinit(self.gpa); + try self.sections.debug_strings.emit(self.gpa, .OpSource, .{ + .source_language = .Unknown, + .version = 0, + // We cannot emit these because the Khronos translator does not parse this instruction + // correctly. + // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/2188 + .file = null, + .source = null, + }); + // Note: needs to be kept in order according to section 2.3! const buffers = &[_][]const Word{ &header, @@ -422,6 +434,7 @@ pub fn flush(self: *Module, file: std.fs.File) !void { self.sections.extensions.toWords(), entry_points.toWords(), self.sections.execution_modes.toWords(), + source.toWords(), self.sections.debug_strings.toWords(), self.sections.debug_names.toWords(), self.sections.annotations.toWords(), @@ -467,13 +480,6 @@ pub fn resolveSourceFileName(self: *Module, path: []const u8) !IdRef { .id_result = file_result_id, .string = path, }); - - try self.sections.debug_strings.emit(self.gpa, .OpSource, .{ - .source_language = .Unknown, // TODO: Register Zig source language. - .version = 0, // TODO: Zig version as u32? - .file = file_result_id, - .source = null, // TODO: Store actual source also? - }); } return result.value_ptr.*; -- 2.54.0 From faad97edffb2fc9cda4885feb688f3ccec71c5db Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 23 Sep 2023 01:30:16 +0200 Subject: [PATCH 35/36] spirv: update failing / passing tests Some tests are now failing due to debug info changes, some tests now pass due to improved compiler functionality. --- test/behavior/abs.zig | 1 - test/behavior/align.zig | 7 ------ test/behavior/array.zig | 4 ---- test/behavior/basic.zig | 7 ------ test/behavior/bitcast.zig | 8 ------- test/behavior/bugs/10684.zig | 1 - test/behavior/bugs/1076.zig | 1 - test/behavior/bugs/11046.zig | 1 - test/behavior/bugs/11139.zig | 1 - test/behavior/bugs/11213.zig | 2 -- test/behavior/bugs/11995.zig | 1 - test/behavior/bugs/12092.zig | 1 - test/behavior/bugs/12142.zig | 1 - test/behavior/bugs/12551.zig | 1 - test/behavior/bugs/12644.zig | 2 -- test/behavior/bugs/12890.zig | 1 - test/behavior/bugs/12891.zig | 6 ----- test/behavior/bugs/12972.zig | 1 - test/behavior/bugs/13064.zig | 1 - test/behavior/bugs/13065.zig | 1 - test/behavior/bugs/13366.zig | 1 - test/behavior/bugs/1381.zig | 1 - test/behavior/bugs/1442.zig | 1 - test/behavior/bugs/1607.zig | 1 - test/behavior/bugs/1741.zig | 2 +- test/behavior/bugs/2346.zig | 2 ++ test/behavior/bugs/2578.zig | 1 - test/behavior/bugs/2692.zig | 1 - test/behavior/bugs/3046.zig | 1 - test/behavior/bugs/3367.zig | 2 -- test/behavior/bugs/3742.zig | 1 - test/behavior/bugs/3779.zig | 3 --- test/behavior/bugs/5487.zig | 1 - test/behavior/bugs/6905.zig | 1 - test/behavior/bugs/726.zig | 2 -- test/behavior/bugs/8646.zig | 1 - test/behavior/call.zig | 6 ----- test/behavior/cast.zig | 24 +++----------------- test/behavior/cast_int.zig | 3 +++ test/behavior/comptime_memory.zig | 4 ---- test/behavior/const_slice_child.zig | 1 - test/behavior/defer.zig | 3 --- test/behavior/empty_union.zig | 4 ---- test/behavior/enum.zig | 8 ------- test/behavior/error.zig | 10 -------- test/behavior/eval.zig | 8 ------- test/behavior/floatop.zig | 20 ++++++++++++++-- test/behavior/fn.zig | 11 --------- test/behavior/for.zig | 11 --------- test/behavior/generics.zig | 4 ---- test/behavior/if.zig | 3 --- test/behavior/inline_switch.zig | 1 - test/behavior/int_comparison_elision.zig | 3 +-- test/behavior/ir_block_deps.zig | 1 - test/behavior/lower_strlit_to_vector.zig | 1 - test/behavior/math.zig | 5 ++-- test/behavior/maximum_minimum.zig | 7 ------ test/behavior/merge_error_sets.zig | 1 - test/behavior/null.zig | 4 ---- test/behavior/optional.zig | 12 ---------- test/behavior/packed-struct.zig | 5 ++++ test/behavior/packed-union.zig | 1 + test/behavior/pointers.zig | 5 ---- test/behavior/ptrcast.zig | 4 ++-- test/behavior/ptrfromint.zig | 2 -- test/behavior/sizeof_and_typeof.zig | 3 --- test/behavior/slice.zig | 9 -------- test/behavior/src.zig | 2 -- test/behavior/struct.zig | 3 --- test/behavior/switch.zig | 7 ------ test/behavior/switch_prong_err_enum.zig | 1 - test/behavior/switch_prong_implicit_cast.zig | 1 - test/behavior/threadlocal.zig | 1 - test/behavior/try.zig | 3 --- test/behavior/tuple.zig | 10 -------- test/behavior/tuple_declarations.zig | 2 -- test/behavior/type.zig | 3 --- test/behavior/type_info.zig | 1 - test/behavior/type_info_only_pub_decls.zig | 2 -- test/behavior/typename.zig | 2 -- test/behavior/union.zig | 17 ++++++++------ test/behavior/usingnamespace.zig | 1 - test/behavior/var_args.zig | 10 -------- test/behavior/vector.zig | 1 - test/behavior/void.zig | 2 -- test/behavior/while.zig | 1 - test/behavior/widening.zig | 2 -- 87 files changed, 48 insertions(+), 279 deletions(-) diff --git a/test/behavior/abs.zig b/test/behavior/abs.zig index 98ca04a5a5f3646d81c3a7e06ac3016a7223004d..51ade3dbcfc2ddd0f665341cf533fe6c75e3ef9c 100644 --- a/test/behavior/abs.zig +++ b/test/behavior/abs.zig @@ -48,7 +48,6 @@ test "@abs unsigned integers" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try comptime testAbsUnsignedIntegers(); try testAbsUnsignedIntegers(); diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 4b5dfafdc844c6c71c44f3da55538d45c61437ab..00fbfc2cb5b6057f2862716d24da0011b999b4c8 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -18,7 +18,6 @@ test "global variable alignment" { test "slicing array of length 1 can not assume runtime index is always zero" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var runtime_index: usize = 1; const slice = @as(*align(4) [1]u8, &foo)[runtime_index..]; @@ -226,7 +225,6 @@ fn fnWithAlignedStack() i32 { test "implicitly decreasing slice alignment" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const a: u32 align(4) = 3; const b: u32 align(8) = 4; @@ -396,7 +394,6 @@ test "function align expression depends on generic parameter" { test "function callconv expression depends on generic parameter" { 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 { @@ -414,7 +411,6 @@ test "function callconv expression depends on generic parameter" { test "runtime-known array index has best alignment possible" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // take full advantage of over-alignment var array align(4) = [_]u8{ 1, 2, 3, 4 }; @@ -546,7 +542,6 @@ test "align(N) on functions" { 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; if (builtin.zig_backend == .stage2_c) { // https://github.com/ziglang/zig/issues/16845 @@ -585,7 +580,6 @@ test "comptime alloc alignment" { test "@alignCast null" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var ptr: ?*anyopaque = null; const aligned: ?*anyopaque = @alignCast(ptr); @@ -601,7 +595,6 @@ test "sub-aligned pointer field access" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // Originally reported at https://github.com/ziglang/zig/issues/14904 diff --git a/test/behavior/array.zig b/test/behavior/array.zig index a8d42f6589b9e009670990dbbbc2e1953fa21f16..2586770c6fa4a84052e1371af7dfa41a7610b9a0 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -72,7 +72,6 @@ test "array concat with tuple" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const array: [2]u8 = .{ 1, 2 }; { @@ -298,7 +297,6 @@ const Str = struct { a: []Sub }; test "set global var array via slice embedded in struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var s = Str{ .a = s_array[0..] }; @@ -568,7 +566,6 @@ test "type coercion of anon struct literal to array" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const U = union { @@ -651,7 +648,6 @@ test "array init of container level array variable" { 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 { var pair: [2]usize = .{ 1, 2 }; diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 3436cba9ba0efef445ef89f1b5fbc84c4a990fa7..b85f2e6d2bf033e8e8072c298efbfb5cd959be70 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -378,8 +378,6 @@ fn testTakeAddressOfParameter(f: f32) !void { } test "pointer to void return type" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try testPointerToVoidReturnType(); } fn testPointerToVoidReturnType() anyerror!void { @@ -473,7 +471,6 @@ fn testStructInFn() !void { test "fn call returning scalar optional in equality expression" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(getNull() == null); } @@ -484,7 +481,6 @@ fn getNull() ?*i32 { test "global variable assignment with optional unwrapping with var initialized to undefined" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { var data: i32 = 1234; @@ -573,8 +569,6 @@ test "comptime cast fn to ptr" { } test "equality compare fn ptrs" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var a = &emptyFn; try expect(a == a); } @@ -840,7 +834,6 @@ test "labeled block implicitly ends in a break" { test "catch in block has correct result location" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn open() error{A}!@This() { diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index d01700ed89e14b63a08cf3b5e2a34a69f33068c0..e21ae2b20c1d088407d7efafc0302ac1cc317a35 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -149,8 +149,6 @@ test "bitcast literal [4]u8 param to u32" { } test "bitcast generates a temporary value" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var y = @as(u16, 0x55AA); const x = @as(u16, @bitCast(@as([2]u8, @bitCast(y)))); try expect(y == x); @@ -186,7 +184,6 @@ test "@bitCast packed structs at runtime and comptime" { test "@bitCast extern structs at runtime and comptime" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Full = extern struct { number: u16, @@ -241,7 +238,6 @@ test "bitcast packed struct to integer and back" { test "implicit cast to error union by returning" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn entry() !void { @@ -271,8 +267,6 @@ test "comptime bitcast used in expression has the correct type" { } test "bitcast passed as tuple element" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn foo(args: anytype) !void { try comptime expect(@TypeOf(args[0]) == f32); @@ -283,8 +277,6 @@ test "bitcast passed as tuple element" { } test "triple level result location with bitcast sandwich passed as tuple element" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn foo(args: anytype) !void { try comptime expect(@TypeOf(args[0]) == f64); diff --git a/test/behavior/bugs/10684.zig b/test/behavior/bugs/10684.zig index f2b0e09bbd92bfbdc2e446e95284b269dd35966e..f09dd3577184424d79e9c670ea53a79479195252 100644 --- a/test/behavior/bugs/10684.zig +++ b/test/behavior/bugs/10684.zig @@ -6,7 +6,6 @@ test "slicing slices" { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; const foo = "1234"; const bar = foo[0..4]; diff --git a/test/behavior/bugs/1076.zig b/test/behavior/bugs/1076.zig index 9aca002c901fd4430653fda8009dc36b585a979b..26d863d9018df4b71754a9d5e457f8b74f4317b2 100644 --- a/test/behavior/bugs/1076.zig +++ b/test/behavior/bugs/1076.zig @@ -6,7 +6,6 @@ const expect = std.testing.expect; test "comptime code should not modify constant data" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testCastPtrOfArrayToSliceAndPtr(); try comptime testCastPtrOfArrayToSliceAndPtr(); diff --git a/test/behavior/bugs/11046.zig b/test/behavior/bugs/11046.zig index 6bf6041a65c92cf4572df3aae0a56c8f5d3e8c2a..a13e02e45c2455dd9cd72dd9e7021ed92cf4abfe 100644 --- a/test/behavior/bugs/11046.zig +++ b/test/behavior/bugs/11046.zig @@ -13,7 +13,6 @@ test "fixed" { 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; bar() catch |err| switch (err) { error.Foo => {}, // error: expected (inferred error set of bar), found error{Foo} diff --git a/test/behavior/bugs/11139.zig b/test/behavior/bugs/11139.zig index 85b2e6957bbe0fca2d0e104b0ab033a3331f83db..7af8b59101192a629030d4a76a93f9bf6e27f5c3 100644 --- a/test/behavior/bugs/11139.zig +++ b/test/behavior/bugs/11139.zig @@ -6,7 +6,6 @@ test "store array of array of structs at comptime" { 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; try expect(storeArrayOfArrayOfStructs() == 15); try comptime expect(storeArrayOfArrayOfStructs() == 15); diff --git a/test/behavior/bugs/11213.zig b/test/behavior/bugs/11213.zig index 875c12697b02ca67ca03f35a4797f1fa025468f3..7f13b6efd80f98a5c606a29bddc927a253208325 100644 --- a/test/behavior/bugs/11213.zig +++ b/test/behavior/bugs/11213.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const testing = std.testing; test { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const g: error{Test}!void = error.Test; var v: u32 = 0; diff --git a/test/behavior/bugs/11995.zig b/test/behavior/bugs/11995.zig index 0c470bee5b2f833dc63d7e688aa8c06d128773d0..8ddf80fd8e34ddc5048747e14173ee521575c645 100644 --- a/test/behavior/bugs/11995.zig +++ b/test/behavior/bugs/11995.zig @@ -20,7 +20,6 @@ test { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; var string: [5]u8 = "hello".*; const arg_data = wuffs_base__slice_u8{ .ptr = @as([*c]u8, @ptrCast(&string)), .len = string.len }; diff --git a/test/behavior/bugs/12092.zig b/test/behavior/bugs/12092.zig index e438539f55fe98926c30a621fa9618a6ddd3183b..e5e89a9c5819d495ca6f5953047bbe320fc7d8dc 100644 --- a/test/behavior/bugs/12092.zig +++ b/test/behavior/bugs/12092.zig @@ -17,7 +17,6 @@ test { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; var baz: u32 = 24; try takeFoo(&.{ diff --git a/test/behavior/bugs/12142.zig b/test/behavior/bugs/12142.zig index ca66b1f8f5b99766de77a81a556937d6cf150e06..14fb8af15a337faece7e544eda51992382a786bb 100644 --- a/test/behavior/bugs/12142.zig +++ b/test/behavior/bugs/12142.zig @@ -22,7 +22,6 @@ test { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; const test_struct = Test{ .holders = &.{ diff --git a/test/behavior/bugs/12551.zig b/test/behavior/bugs/12551.zig index b2a79c0847555cd2b1c11c623d2d2755d9bd0a27..df01e5cbdd84056bd96b5dd608e4066780d5342a 100644 --- a/test/behavior/bugs/12551.zig +++ b/test/behavior/bugs/12551.zig @@ -4,7 +4,6 @@ const builtin = @import("builtin"); test { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try std.testing.expect(for ([1]u8{0}) |x| { if (x == 0) break true; diff --git a/test/behavior/bugs/12644.zig b/test/behavior/bugs/12644.zig index 3c0cc5656f2f9815d3a5cc33ddf234e05f5b5ff7..d1514d2e47b642d68b28f0972b380afc619daf29 100644 --- a/test/behavior/bugs/12644.zig +++ b/test/behavior/bugs/12644.zig @@ -10,8 +10,6 @@ fn main0() !void { } test "issue12644" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - main0() catch |e| { try std.testing.expect(e == error.AnError); }; diff --git a/test/behavior/bugs/12890.zig b/test/behavior/bugs/12890.zig index a832f14cefbd690bee55bdca9d8942e70f7d6a13..1316c2745e43a85a6aaa10aaf860599d44b274dd 100644 --- a/test/behavior/bugs/12890.zig +++ b/test/behavior/bugs/12890.zig @@ -11,7 +11,6 @@ fn a(b: []u3, c: u3) void { test { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var arr: [8]u3 = undefined; a(&arr, 5); diff --git a/test/behavior/bugs/12891.zig b/test/behavior/bugs/12891.zig index 82995eb019387e1745a7a8d91d77adb9aca4402e..354d9e856e2b2b347236fc2ff3ffb3a1a01dc06b 100644 --- a/test/behavior/bugs/12891.zig +++ b/test/behavior/bugs/12891.zig @@ -29,7 +29,6 @@ test "inf >= 1" { test "isNan(nan * 1)" { 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; const nan_times_one = comptime std.math.nan(f64) * 1; try std.testing.expect(std.math.isNan(nan_times_one)); @@ -37,7 +36,6 @@ test "isNan(nan * 1)" { test "runtime isNan(nan * 1)" { 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; const nan_times_one = std.math.nan(f64) * 1; try std.testing.expect(std.math.isNan(nan_times_one)); @@ -45,7 +43,6 @@ test "runtime isNan(nan * 1)" { test "isNan(nan * 0)" { 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; const nan_times_zero = comptime std.math.nan(f64) * 0; try std.testing.expect(std.math.isNan(nan_times_zero)); @@ -55,7 +52,6 @@ test "isNan(nan * 0)" { test "isNan(inf * 0)" { 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; const inf_times_zero = comptime std.math.inf(f64) * 0; try std.testing.expect(std.math.isNan(inf_times_zero)); @@ -65,7 +61,6 @@ test "isNan(inf * 0)" { test "runtime isNan(nan * 0)" { 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; const nan_times_zero = std.math.nan(f64) * 0; try std.testing.expect(std.math.isNan(nan_times_zero)); @@ -75,7 +70,6 @@ test "runtime isNan(nan * 0)" { test "runtime isNan(inf * 0)" { 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; const inf_times_zero = std.math.inf(f64) * 0; try std.testing.expect(std.math.isNan(inf_times_zero)); diff --git a/test/behavior/bugs/12972.zig b/test/behavior/bugs/12972.zig index 329e993ab8da2f9fbc82232fcad99f95d4676011..3c256a19f81f5f1afe1a2f7d6c1c3e9243921c49 100644 --- a/test/behavior/bugs/12972.zig +++ b/test/behavior/bugs/12972.zig @@ -6,7 +6,6 @@ test { 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 c: u8 = 42; f(&[_:null]?u8{c}); diff --git a/test/behavior/bugs/13064.zig b/test/behavior/bugs/13064.zig index f997bb46b9c44c01244b3c282b89cb45f1c85993..a6fea11e868f193d1579dde2fcbb2a01ac9fbc48 100644 --- a/test/behavior/bugs/13064.zig +++ b/test/behavior/bugs/13064.zig @@ -6,7 +6,6 @@ test { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: [10][10]u32 = undefined; diff --git a/test/behavior/bugs/13065.zig b/test/behavior/bugs/13065.zig index d6c63db84bc2549d230250d6a481460c8c4bc077..74f1d01c8c8ffdecfc9109fb973539d0425039c0 100644 --- a/test/behavior/bugs/13065.zig +++ b/test/behavior/bugs/13065.zig @@ -11,7 +11,6 @@ test { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x = U{ .array = undefined }; diff --git a/test/behavior/bugs/13366.zig b/test/behavior/bugs/13366.zig index b6c034104428aac12180ace12f6802ce3d3b91b4..9b08bcd3fc46fba2b9c07d8c944408a9583c0e52 100644 --- a/test/behavior/bugs/13366.zig +++ b/test/behavior/bugs/13366.zig @@ -16,7 +16,6 @@ test { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; var a: u32 = 16; var reason = .{ .c_import = .{ .a = a } }; diff --git a/test/behavior/bugs/1381.zig b/test/behavior/bugs/1381.zig index cd0b289e5f73bb9645f6e9dcf049439fe72d9bb9..c9ea2102f59fa0f4259b7ee4f03a2543ad21563e 100644 --- a/test/behavior/bugs/1381.zig +++ b/test/behavior/bugs/1381.zig @@ -15,7 +15,6 @@ test "union that needs padding bytes inside an array" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var as = [_]A{ A{ .B = B{ .D = 1 } }, diff --git a/test/behavior/bugs/1442.zig b/test/behavior/bugs/1442.zig index 7ce138dfd73ff9da8ed4202c8704d66690ee9cd7..02170ccabe3d55e024f2571d50f44086e8693410 100644 --- a/test/behavior/bugs/1442.zig +++ b/test/behavior/bugs/1442.zig @@ -10,7 +10,6 @@ test "const error union field alignment" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var union_or_err: anyerror!Union = Union{ .Color = 1234 }; try std.testing.expect((union_or_err catch unreachable).Color == 1234); diff --git a/test/behavior/bugs/1607.zig b/test/behavior/bugs/1607.zig index 32d5b38ba3ee8fc7c98ae62d906d876359a39ddf..6fbd8fe07554f02aea80f1f4fc14e7a542a42494 100644 --- a/test/behavior/bugs/1607.zig +++ b/test/behavior/bugs/1607.zig @@ -14,7 +14,6 @@ test "slices pointing at the same address as global array." { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try checkAddress(&a); try comptime checkAddress(&a); diff --git a/test/behavior/bugs/1741.zig b/test/behavior/bugs/1741.zig index 0d56808f4582b584f7564bf682e273514aba3b63..f4da8e5c2e495c5f61655f5914283d226ca89913 100644 --- a/test/behavior/bugs/1741.zig +++ b/test/behavior/bugs/1741.zig @@ -4,7 +4,7 @@ const builtin = @import("builtin"); test "fixed" { 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; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky const x: f32 align(128) = 12.34; try std.testing.expect(@intFromPtr(&x) % 128 == 0); diff --git a/test/behavior/bugs/2346.zig b/test/behavior/bugs/2346.zig index 52c1e3ac6b5a10dd530519103125f011afd8ee90..3f3bbb9b56526e985c2f7ae0478e88443fc786d4 100644 --- a/test/behavior/bugs/2346.zig +++ b/test/behavior/bugs/2346.zig @@ -1,3 +1,5 @@ +const builtin = @import("builtin"); + test "fixed" { const a: *void = undefined; const b: *[1]void = a; diff --git a/test/behavior/bugs/2578.zig b/test/behavior/bugs/2578.zig index 9cf34e980d77b2ba4c582fa968d5db5dfacb3ee6..ff8ba141fa634476144dc2c7c833a6f7449e3275 100644 --- a/test/behavior/bugs/2578.zig +++ b/test/behavior/bugs/2578.zig @@ -15,7 +15,6 @@ test "fixed" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; bar(t); } diff --git a/test/behavior/bugs/2692.zig b/test/behavior/bugs/2692.zig index 0eed28b2e7b4dc06c01a48d7d6e66b719d5eee1f..d89b3b544906dca0d88b275ef7141815654b16e9 100644 --- a/test/behavior/bugs/2692.zig +++ b/test/behavior/bugs/2692.zig @@ -7,7 +7,6 @@ fn foo(a: []u8) void { test "address of 0 length array" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var pt: [0]u8 = undefined; foo(&pt); diff --git a/test/behavior/bugs/3046.zig b/test/behavior/bugs/3046.zig index 683ece874ee3e92fff2f4b2cf761a8b19529f3d5..24e18043a058ec5615cfa433049d3b6916f3cdfd 100644 --- a/test/behavior/bugs/3046.zig +++ b/test/behavior/bugs/3046.zig @@ -16,7 +16,6 @@ test "fixed" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; some_struct = SomeStruct{ .field = couldFail() catch @as(i32, 0), diff --git a/test/behavior/bugs/3367.zig b/test/behavior/bugs/3367.zig index 775e918f63c64fa4fd5f068594f98a92a7d59478..68b7d90ae8f05dbd21e2b3f4d4d256d67884640f 100644 --- a/test/behavior/bugs/3367.zig +++ b/test/behavior/bugs/3367.zig @@ -10,8 +10,6 @@ const Mixin = struct { }; test "container member access usingnamespace decls" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var foo = Foo{}; foo.two(); } diff --git a/test/behavior/bugs/3742.zig b/test/behavior/bugs/3742.zig index 09d209912ea66f34c9de6c096f89a2cf92ab6fb7..e0d46e72c39c53379c787b008833dca8026abc72 100644 --- a/test/behavior/bugs/3742.zig +++ b/test/behavior/bugs/3742.zig @@ -40,7 +40,6 @@ test "fixed" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; ArgSerializer.serializeCommand(GET.init("banana")); } diff --git a/test/behavior/bugs/3779.zig b/test/behavior/bugs/3779.zig index 088443d529691cc300ffe4d0623b2d72464a152d..c2bd1031188f851f60ba1f361e0f34a0249cabe9 100644 --- a/test/behavior/bugs/3779.zig +++ b/test/behavior/bugs/3779.zig @@ -34,7 +34,6 @@ const ptr_type_name: [*:0]const u8 = type_name; test "@typeName() returns a string literal" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try std.testing.expect(*const [type_name.len:0]u8 == @TypeOf(type_name)); try std.testing.expect(std.mem.eql(u8, "behavior.bugs.3779.TestType", type_name)); @@ -48,7 +47,6 @@ const expected_contents = "hello zig\n"; test "@embedFile() returns a string literal" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try std.testing.expect(*const [expected_contents.len:0]u8 == @TypeOf(actual_contents)); try std.testing.expect(std.mem.eql(u8, expected_contents, actual_contents)); @@ -63,7 +61,6 @@ fn testFnForSrc() std.builtin.SourceLocation { test "@src() returns a struct containing 0-terminated string slices" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const src = testFnForSrc(); try std.testing.expect([:0]const u8 == @TypeOf(src.file)); diff --git a/test/behavior/bugs/5487.zig b/test/behavior/bugs/5487.zig index ac9f15dfef8fdc9fccc03a1916045ba66595342d..3ea8cad220a08329e3d583cb8b8fb382b53a58cb 100644 --- a/test/behavior/bugs/5487.zig +++ b/test/behavior/bugs/5487.zig @@ -13,6 +13,5 @@ test "crash" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; _ = io.multiWriter(.{writer()}); } diff --git a/test/behavior/bugs/6905.zig b/test/behavior/bugs/6905.zig index 410adf03110faab79a856645e6ba33ced7d47715..be96efaacefd28cdb9193136c7d34336a842ddd2 100644 --- a/test/behavior/bugs/6905.zig +++ b/test/behavior/bugs/6905.zig @@ -5,7 +5,6 @@ test "sentinel-terminated 0-length slices" { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; var u32s: [4]u32 = [_]u32{ 0, 1, 2, 3 }; diff --git a/test/behavior/bugs/726.zig b/test/behavior/bugs/726.zig index 37e8d31cc942029c2942ecf961cb693bd7ee2469..c544e422a442bc2be1f0a15416325c049fc3939a 100644 --- a/test/behavior/bugs/726.zig +++ b/test/behavior/bugs/726.zig @@ -5,7 +5,6 @@ test "@ptrCast from const to nullable" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const c: u8 = 4; var x: ?*const u8 = @as(?*const u8, @ptrCast(&c)); @@ -16,7 +15,6 @@ test "@ptrCast from var in empty struct to nullable" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const container = struct { var c: u8 = 4; diff --git a/test/behavior/bugs/8646.zig b/test/behavior/bugs/8646.zig index e6dcbe4e64eeee3a14f41b5146ce96329f66bf8a..b835b81b54bf901e0d18cac36c185c62d65e6ae8 100644 --- a/test/behavior/bugs/8646.zig +++ b/test/behavior/bugs/8646.zig @@ -10,7 +10,6 @@ test { if (builtin.zig_backend == .stage2_x86) 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_spirv64) return error.SkipZigTest; try std.testing.expect(array[0].len == 1); try std.testing.expectEqualStrings("hello", array[0][0]); diff --git a/test/behavior/call.zig b/test/behavior/call.zig index beccb059d8256b7a0cd7dcd5440cb9f239c977dc..61aa48803b10a9102259a6b54cd4ef00eebfe8b6 100644 --- a/test/behavior/call.zig +++ b/test/behavior/call.zig @@ -90,7 +90,6 @@ test "result location of function call argument through runtime condition and st if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const E = enum { a, b }; const S = struct { @@ -400,7 +399,6 @@ test "recursive inline call with comptime known argument" { test "inline while with @call" { 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; const S = struct { fn inc(a: *u32) void { @@ -416,8 +414,6 @@ test "inline while with @call" { } test "method call as parameter type" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn foo(x: anytype, y: @TypeOf(x).Inner()) @TypeOf(y) { return y; @@ -436,7 +432,6 @@ test "non-anytype generic parameters provide result type" { 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; // TODO const S = struct { fn f(comptime T: type, y: T) !void { @@ -467,7 +462,6 @@ test "argument to generic function has correct result type" { 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; // TODO const S = struct { fn foo(_: anytype, e: enum { a, b }) bool { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 69e8c88b794db9dc4e5369073763cc0c2778f7eb..91e2812591ad6aa79645248664c6e68c11dff7dd 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -67,6 +67,8 @@ test "implicit cast comptime_int to comptime_float" { } test "comptime_int @floatFromInt" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + { const result = @as(f16, @floatFromInt(1234)); try expect(@TypeOf(result) == f16); @@ -463,7 +465,6 @@ fn castToOptionalTypeError(z: i32) !void { test "implicitly cast from [0]T to anyerror![]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testCastZeroArrayToErrSliceMut(); try comptime testCastZeroArrayToErrSliceMut(); @@ -481,7 +482,6 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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() anyerror!void { @@ -562,7 +562,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 { test "single-item pointer of array to slice to unknown length pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testCastPtrOfArrayToSliceAndPtr(); try comptime testCastPtrOfArrayToSliceAndPtr(); @@ -592,7 +591,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void { test "cast *[1][*]const u8 to [*]const ?[*]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const window_name = [1][*]const u8{"window name"}; const x: [*]const ?[*]const u8 = &window_name; @@ -663,7 +661,6 @@ test "@floatCast cast down" { test "peer type resolution: unreachable, error set, unreachable" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Error = error{ FileDescriptorAlreadyPresentInSet, @@ -822,7 +819,6 @@ test "peer cast *[0]T to E![]const T" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buffer: [5]u8 = "abcde".*; var buf: anyerror![]const u8 = buffer[0..]; @@ -837,7 +833,6 @@ test "peer cast *[0]T to []const T" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buffer: [5]u8 = "abcde".*; var buf: []const u8 = buffer[0..]; @@ -859,7 +854,6 @@ test "peer resolution of string literals" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 { const E = enum { a, b, c, d }; @@ -881,7 +875,6 @@ test "peer resolution of string literals" { test "peer cast [:x]T to []T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 { @@ -1185,7 +1178,6 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { test "peer type resolution: [0]u8 and []const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); @@ -1270,7 +1262,6 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void { test "implicit cast *[0]T to E![]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x = @as(anyerror![]const u8, &[0]u8{}); try expect((x catch unreachable).len == 0); @@ -1524,6 +1515,7 @@ test "implicit cast from [:0]T to [*c]T" { test "bitcast packed struct with u0" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = packed struct(u2) { a: u0, b: u2 }; const s = @as(S, @bitCast(@as(u2, 2))); @@ -1588,7 +1580,6 @@ test "peer type resolution: const sentinel slice and mutable non-sentinel slice" 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; // TODO const S = struct { fn doTheTest(comptime T: type, comptime s: T) !void { @@ -1617,7 +1608,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO const i: u8 = 100; var f: f32 = 1.234; @@ -1678,7 +1668,6 @@ test "peer type resolution: array and vector with same child type" { 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; // TODO var arr: [2]u32 = .{ 0, 1 }; var vec: @Vector(2, u32) = .{ 2, 3 }; @@ -1743,7 +1732,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" { 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; // TODO var a: [*c]c_int = 0x1000; const b = null; @@ -1826,7 +1814,6 @@ test "peer type resolution: optional fixed-width int and comptime_int" { 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; // TODO var a: ?i32 = 42; const b: comptime_int = 50; @@ -1869,7 +1856,6 @@ test "peer type resolution: vector and tuple" { if (builtin.zig_backend == .stage2_arm) 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; // TODO var vec: @Vector(3, i32) = .{ 1, 2, 3 }; const tup = .{ 4, 5, 6 }; @@ -1892,7 +1878,6 @@ test "peer type resolution: vector and array and tuple" { if (builtin.zig_backend == .stage2_arm) 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; // TODO var vec: @Vector(2, i8) = .{ 10, 20 }; var arr: [2]i8 = .{ 30, 40 }; @@ -2086,7 +2071,6 @@ test "peer type resolution: C pointer and many pointer" { 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; // TODO var buf = "hello".*; @@ -2389,7 +2373,6 @@ test "@intFromBool on vector" { test "numeric coercions with undefined" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const from: i32 = undefined; var to: f32 = from; @@ -2401,7 +2384,6 @@ test "numeric coercions with undefined" { test "15-bit int to float" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var a: u15 = 42; var b: f32 = @floatFromInt(a); diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig index aacb06b40d68d73b16a7ba64ccd0a2057f71be7d..5232c828d06cd9e0c41f92a9bbca66f72816aa3f 100644 --- a/test/behavior/cast_int.zig +++ b/test/behavior/cast_int.zig @@ -149,6 +149,8 @@ const Piece = packed struct { test "load non byte-sized optional value" { // Originally reported at https://github.com/ziglang/zig/issues/14200 + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + // note: this bug is triggered by the == operator, expectEqual will hide it var opt: ?Piece = try Piece.charToPiece('p'); try expect(opt.?.type == .PAWN); @@ -162,6 +164,7 @@ test "load non byte-sized optional value" { test "load non byte-sized value in struct" { if (builtin.cpu.arch.endian() != .Little) return error.SkipZigTest; // packed struct TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // note: this bug is triggered by the == operator, expectEqual will hide it // using ptrCast not to depend on unitialised memory state diff --git a/test/behavior/comptime_memory.zig b/test/behavior/comptime_memory.zig index d6b3ae39935cbf6443d21d917477a0b7ebcd8b9b..84ecb8fbc925c9818343125cf8be3187939b04d5 100644 --- a/test/behavior/comptime_memory.zig +++ b/test/behavior/comptime_memory.zig @@ -426,8 +426,6 @@ test "mutate entire slice at comptime" { } test "dereference undefined pointer to zero-bit type" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const p0: *void = undefined; try testing.expectEqual({}, p0.*); @@ -436,8 +434,6 @@ test "dereference undefined pointer to zero-bit type" { } test "type pun extern struct" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = extern struct { f: u8 }; comptime var s = S{ .f = 123 }; @as(*u8, @ptrCast(&s)).* = 72; diff --git a/test/behavior/const_slice_child.zig b/test/behavior/const_slice_child.zig index 68c6863bcd8129afb625a0f7a3747f90e58da88e..35bc007d8406c35a86733b90bc8c8d0af624f9a1 100644 --- a/test/behavior/const_slice_child.zig +++ b/test/behavior/const_slice_child.zig @@ -10,7 +10,6 @@ test "const slice child" { 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 strs = [_][*]const u8{ "one", "two", "three" }; argv = &strs; diff --git a/test/behavior/defer.zig b/test/behavior/defer.zig index c70fad4b45e5eda7fbccea84bd4c79370ace8e1c..593282ac5914fd1d49aad3a120121788fbdb0160 100644 --- a/test/behavior/defer.zig +++ b/test/behavior/defer.zig @@ -34,7 +34,6 @@ test "defer and labeled break" { test "errdefer does not apply to fn inside fn" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad); } @@ -95,7 +94,6 @@ test "mixing normal and error defers" { 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; try expect(runSomeErrorDefers(true) catch unreachable); try expect(result[0] == 'c'); @@ -160,7 +158,6 @@ test "reference to errdefer payload" { test "simple else prong doesn't emit an error for unreachable else prong" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn foo() error{Foo}!void { diff --git a/test/behavior/empty_union.zig b/test/behavior/empty_union.zig index 53408875ae1d520ecc37f52d5efe6b02a6405116..40bdd627f34e6c85c51a6adc1600cb571f7cd458 100644 --- a/test/behavior/empty_union.zig +++ b/test/behavior/empty_union.zig @@ -44,8 +44,6 @@ test "empty extern union" { } test "empty union passed as argument" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const U = union(enum) { fn f(u: @This()) void { switch (u) {} @@ -55,8 +53,6 @@ test "empty union passed as argument" { } test "empty enum passed as argument" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const E = enum { fn f(e: @This()) void { switch (e) {} diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 13d079ddf9a58b7e26f510f61689dd500f935cf7..efd0295a9797856eedb66b90e06fdb84aad7095b 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -617,7 +617,6 @@ test "enum with specified tag values" { test "non-exhaustive enum" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const E = enum(u8) { a, b, _ }; @@ -660,8 +659,6 @@ test "non-exhaustive enum" { } test "empty non-exhaustive enum" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { const E = enum(u8) { _ }; @@ -683,7 +680,6 @@ test "empty non-exhaustive enum" { test "single field non-exhaustive enum" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const E = enum(u8) { a, _ }; @@ -856,8 +852,6 @@ fn doALoopThing(id: EnumWithOneMember) void { } test "comparison operator on enum with one member is comptime-known" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - doALoopThing(EnumWithOneMember.Eof); } @@ -1211,8 +1205,6 @@ test "enum tag from a local variable" { } test "auto-numbered enum with signed tag type" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const E = enum(i32) { a, b }; try std.testing.expectEqual(@as(i32, 0), @intFromEnum(E.a)); diff --git a/test/behavior/error.zig b/test/behavior/error.zig index c0725f87791a1b7755ea54527663a3c220aebbbf..72003d1ea8f510445a9ae2f119f3e6609aa7a276 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -124,7 +124,6 @@ test "debug info for optional error set" { test "implicit cast to optional to error union to return result loc" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn entry() !void { @@ -218,7 +217,6 @@ fn testErrorSetType() !void { test "explicit error set cast" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testExplicitErrorSetCast(Set1.A); try comptime testExplicitErrorSetCast(Set1.A); @@ -320,7 +318,6 @@ test "error inference with an empty set" { test "error union peer type resolution" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testErrorUnionPeerTypeResolution(1); } @@ -404,7 +401,6 @@ test "nested error union function call in optional unwrap" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 Foo = struct { @@ -469,7 +465,6 @@ test "optional error set is the same size as 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_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try comptime expect(@sizeOf(?anyerror) == @sizeOf(anyerror)); try comptime expect(@alignOf(?anyerror) == @alignOf(anyerror)); @@ -485,7 +480,6 @@ test "optional error set is the same size as error set" { test "nested catch" { if (builtin.zig_backend == .stage2_aarch64) 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 entry() !void { @@ -536,7 +530,6 @@ test "return result loc as peer result loc in inferred error set function" { 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 { @@ -568,7 +561,6 @@ test "error payload type is correctly resolved" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const MyIntWrapper = struct { const Self = @This(); @@ -736,7 +728,6 @@ test "ret_ptr doesn't cause own inferred error set to be resolved" { test "simple else prong allowed even when all errors handled" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn foo() !u8 { @@ -920,7 +911,6 @@ test "optional error union return type" { test "optional error set return type" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const E = error{ A, B }; const S = struct { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 39bfbe1ba73334d861c418fdf2e75b74bfd6107a..a57d537c30df37f5990c3bb1ff579f52fecf9bb4 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -441,7 +441,6 @@ test "binary math operator in partially inlined function" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var s: [4]u32 = undefined; var b: [16]u8 = undefined; @@ -710,7 +709,6 @@ fn loopNTimes(comptime n: usize) void { } test "variable inside inline loop that has different types on different iterations" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testVarInsideInlineLoop(.{ true, @as(u32, 42) }); } @@ -760,7 +758,6 @@ test "array concatenation peer resolves element types - value" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var a = [2]u3{ 1, 7 }; var b = [3]u8{ 200, 225, 255 }; @@ -777,7 +774,6 @@ test "array concatenation peer resolves element types - pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var a = [2]u3{ 1, 7 }; var b = [3]u8{ 200, 225, 255 }; @@ -794,7 +790,6 @@ test "array concatenation sets the sentinel - value" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var a = [2]u3{ 1, 7 }; var b = [3:69]u8{ 200, 225, 255 }; @@ -812,7 +807,6 @@ test "array concatenation sets the sentinel - value" { test "array concatenation sets the sentinel - pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var a = [2]u3{ 1, 7 }; var b = [3:69]u8{ 200, 225, 255 }; @@ -1668,8 +1662,6 @@ test "early exit in container level const" { } test "@inComptime" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn inComptime() bool { return @inComptime(); diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 05ac8a6a894cd974ca9e7757119297e17b887173..f114f30fa9b979dd2012663586be82e2dad6a976 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -29,6 +29,7 @@ test "add f32/f64" { test "add f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testAdd(f80); try comptime testAdd(f80); @@ -60,6 +61,7 @@ test "sub f32/f64" { test "sub f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testSub(f80); try comptime testSub(f80); @@ -91,6 +93,7 @@ test "mul f32/f64" { test "mul f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testMul(f80); try comptime testMul(f80); @@ -200,7 +203,6 @@ test "different sized float comparisons" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; try testDifferentSizedFloatComparisons(); @@ -235,6 +237,7 @@ fn testDifferentSizedFloatComparisons() !void { test "negative f128 intFromFloat at compile-time" { 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 a: f128 = -2; var b = @as(i64, @intFromFloat(a)); @@ -908,6 +911,7 @@ test "@abs f16" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testFabs(f16); try comptime testFabs(f16); @@ -917,6 +921,7 @@ test "@abs f32/f64" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testFabs(f32); try comptime testFabs(f32); @@ -930,6 +935,7 @@ test "@abs f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testFabs(f80); try comptime testFabs(f80); @@ -1007,6 +1013,7 @@ test "@floor f16" { 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_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testFloor(f16); try comptime testFloor(f16); @@ -1017,6 +1024,7 @@ test "@floor f32/f64" { 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_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testFloor(f32); try comptime testFloor(f32); @@ -1030,6 +1038,7 @@ test "@floor f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/12602 @@ -1089,6 +1098,7 @@ test "@ceil f16" { 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_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testCeil(f16); try comptime testCeil(f16); @@ -1099,6 +1109,7 @@ test "@ceil f32/f64" { 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_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testCeil(f32); try comptime testCeil(f32); @@ -1112,6 +1123,7 @@ test "@ceil f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/12602 @@ -1148,8 +1160,8 @@ fn testCeil(comptime T: type) !void { test "@ceil with vectors" { 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; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; @@ -1171,6 +1183,7 @@ test "@trunc f16" { 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_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) { // https://github.com/ziglang/zig/issues/16846 @@ -1186,6 +1199,7 @@ test "@trunc f32/f64" { 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_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) { // https://github.com/ziglang/zig/issues/16846 @@ -1204,6 +1218,7 @@ test "@trunc f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/12602 @@ -1390,6 +1405,7 @@ test "comptime fixed-width float non-zero divided by zero produces signed Inf" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; inline for (.{ f16, f32, f64, f80, f128 }) |F| { const pos = @as(F, 1) / @as(F, 0); diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index ed69a8d8e9aa09b5e2d377a4ead237775140210e..aad7f575902ff7686ce43c741a19507bc722cc27 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -201,7 +201,6 @@ fn addPointCoords(pt: Point) i32 { test "pass by non-copying value through var arg" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3); } @@ -257,7 +256,6 @@ test "implicit cast fn call result to optional in field result" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn entry() !void { @@ -284,7 +282,6 @@ test "implicit cast fn call result to optional in field result" { test "void parameters" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try voidFun(1, void{}, 2, {}); } @@ -348,7 +345,6 @@ test "function call with anon list literal" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 { @@ -369,7 +365,6 @@ test "function call with anon list literal - 2D" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 { @@ -415,7 +410,6 @@ test "function with inferred error set but returning no error" { test "import passed byref to function in return type" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn get() @import("std").ArrayListUnmanaged(i32) { @@ -451,7 +445,6 @@ test "implicit cast function to function ptr" { test "method call with optional and error union first param" { 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 { x: i32 = 1234, @@ -471,7 +464,6 @@ test "method call with optional and error union first param" { test "method call with optional pointer first param" { 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 { x: i32 = 1234, @@ -528,7 +520,6 @@ test "function returns function returning type" { test "peer type resolution of inferred error set with non-void payload" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn openDataFile(mode: enum { read, write }) !u32 { @@ -571,8 +562,6 @@ test "lazy values passed to anytype parameter" { } test "pass and return comptime-only types" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn returnNull(comptime x: @Type(.Null)) @Type(.Null) { return x; diff --git a/test/behavior/for.zig b/test/behavior/for.zig index bf90d661fb09f5178fb357a0c3cb8376ac5e4024..5a41f75077e58bad06fc4291c51910815b357514 100644 --- a/test/behavior/for.zig +++ b/test/behavior/for.zig @@ -7,7 +7,6 @@ const mem = std.mem; test "continue in for loop" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const array = [_]i32{ 1, 2, 3, 4, 5 }; var sum: i32 = 0; @@ -113,7 +112,6 @@ test "for with null and T peer types and inferred result location type" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest(slice: []const u8) !void { @@ -134,7 +132,6 @@ test "for with null and T peer types and inferred result location type" { test "2 break statements and an else" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn entry(t: bool, f: bool) !void { @@ -182,7 +179,6 @@ fn mangleString(s: []u8) void { test "for copies its payload" { if (builtin.zig_backend == .stage2_aarch64) 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 { @@ -217,7 +213,6 @@ test "for on slice with allowzero ptr" { test "else continue outer for" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var i: usize = 6; var buf: [5]u8 = undefined; @@ -279,7 +274,6 @@ test "two counters" { test "1-based counter and ptr to array" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var ok: usize = 0; @@ -360,7 +354,6 @@ test "raw pointer and slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [10]u8 = undefined; const slice: []const u8 = "blah"; @@ -380,7 +373,6 @@ test "raw pointer and counter" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [10]u8 = undefined; const ptr: [*]u8 = &buf; @@ -429,7 +421,6 @@ test "inline for with counter as the comptime-known" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var runtime_slice = "hello"; var runtime_i: usize = 3; @@ -460,7 +451,6 @@ test "inline for on tuple pointer" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO const S = struct { u32, u32, u32 }; var s: S = .{ 100, 200, 300 }; @@ -476,7 +466,6 @@ test "ref counter that starts at zero" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO for ([_]usize{ 0, 1, 2 }, 0..) |i, j| { try expectEqual(i, j); diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index 8ecb069956f13344e53e84401253d6814a23e5b8..2981c73f22fbc64e00b95cd585338d19b59d1403 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -153,7 +153,6 @@ test "generic fn with implicit cast" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(getFirstByte(u8, &[_]u8{13}) == 13); try expect(getFirstByte(u16, &[_]u16{ @@ -280,7 +279,6 @@ test "generic function instantiation turns into comptime call" { test "generic function with void and comptime parameter" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { x: i32 }; const namespace = struct { @@ -315,7 +313,6 @@ test "generic function instantiation non-duplicates" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.os.tag == .wasi) return error.SkipZigTest; const S = struct { @@ -433,7 +430,6 @@ test "generic function passed as comptime argument" { test "return type of generic function is function pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn b(comptime T: type) ?*const fn () error{}!T { diff --git a/test/behavior/if.zig b/test/behavior/if.zig index a38f68cf91c973451cdffcdc7c03e8220c74bd08..68ea986c05b8fda10e21f7f823ebb0ac28499da7 100644 --- a/test/behavior/if.zig +++ b/test/behavior/if.zig @@ -45,7 +45,6 @@ var global_with_err: anyerror!u32 = error.SomeError; test "unwrap mutable global var" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (global_with_val) |v| { try expect(v == 0); @@ -116,7 +115,6 @@ test "if peer expressions inferred optional type" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var self: []const u8 = "abcdef"; var index: usize = 0; @@ -134,7 +132,6 @@ test "if-else expression with runtime condition result location is inferred opti if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const A = struct { b: u64, c: u64 }; var d: bool = true; diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig index 43a02df01d41c2c6b5aee29f4118de84a8c65f84..305b898bfc35814db265648dd2d0d1605ee70556 100644 --- a/test/behavior/inline_switch.zig +++ b/test/behavior/inline_switch.zig @@ -84,7 +84,6 @@ test "inline else bool" { test "inline else error" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Err = error{ a, b, c }; var a = Err.a; diff --git a/test/behavior/int_comparison_elision.zig b/test/behavior/int_comparison_elision.zig index 32c670fff425f0396ab76be7aac219c9fb82c71b..c384f6208677a167821f4aced86e2abd6df32982 100644 --- a/test/behavior/int_comparison_elision.zig +++ b/test/behavior/int_comparison_elision.zig @@ -4,8 +4,6 @@ const maxInt = std.math.maxInt; const builtin = @import("builtin"); test "int comparison elision" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - testIntEdges(u0); testIntEdges(i0); testIntEdges(u1); @@ -17,6 +15,7 @@ test "int comparison elision" { if (builtin.zig_backend == .stage2_wasm) 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_spirv64) return error.SkipZigTest; // TODO: panic: integer overflow with int types > 65528 bits wide // TODO: LLVM generates too many parameters for wasmtime when splitting up int > 64000 bits wide diff --git a/test/behavior/ir_block_deps.zig b/test/behavior/ir_block_deps.zig index 136f23409bfdded605c75f6ef7c9e60273551341..a46ad2d8a83a9bbd4b26d9388b53c378c83832f0 100644 --- a/test/behavior/ir_block_deps.zig +++ b/test/behavior/ir_block_deps.zig @@ -21,7 +21,6 @@ test "ir block deps" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; try expect((foo(1) catch unreachable) == 0); try expect((foo(2) catch unreachable) == 0); diff --git a/test/behavior/lower_strlit_to_vector.zig b/test/behavior/lower_strlit_to_vector.zig index 41faad14c0769c87a2557768eb059b479099a0cb..948d708aa7b63528400db510325aa8084df3afc8 100644 --- a/test/behavior/lower_strlit_to_vector.zig +++ b/test/behavior/lower_strlit_to_vector.zig @@ -6,7 +6,6 @@ test "strlit to vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const strlit = "0123456789abcdef0123456789ABCDEF"; const vec_from_strlit: @Vector(32, u8) = strlit.*; diff --git a/test/behavior/math.zig b/test/behavior/math.zig index aec2920eb1038bfb484efe509402099cff94c9a6..894d620d901cb05977e563c9a4b5ba618d5eb6f0 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -1119,6 +1119,8 @@ test "@shlWithOverflow" { } test "overflow arithmetic with u0 values" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + { var a: u0 = 0; const ov = @addWithOverflow(a, 0); @@ -1287,8 +1289,6 @@ fn testShrExact(x: u8) !void { } test "shift left/right on u0 operand" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn doTheTest() !void { var x: u0 = 0; @@ -1565,7 +1565,6 @@ test "vector comparison" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) 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 { diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index ecc32a33f6a6df0967e29272549813cc29c7b066..3fabe1aa591060aa3174b15c74890e9f61a1d4bd 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -147,8 +147,6 @@ test "@min/@max on lazy values" { } test "@min/@max more than two arguments" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const x: u32 = 30; const y: u32 = 10; const z: u32 = 20; @@ -161,7 +159,6 @@ test "@min/@max more than two vector arguments" { 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 x: @Vector(2, u32) = .{ 3, 2 }; const y: @Vector(2, u32) = .{ 4, 1 }; @@ -174,7 +171,6 @@ test "@min/@max notices bounds" { 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; var x: u16 = 20; const y = 30; @@ -224,7 +220,6 @@ test "@min/@max notices bounds from types" { 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; var x: u16 = 123; var y: u32 = 456; @@ -305,8 +300,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known } test "@min/@max of signed and unsigned runtime integers" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var x: i32 = -1; var y: u31 = 1; diff --git a/test/behavior/merge_error_sets.zig b/test/behavior/merge_error_sets.zig index 62aa77fb18c8856528da450fe4d2b98025e4682c..492cb276999f508d6010eef7bb9fdee7c60a2717 100644 --- a/test/behavior/merge_error_sets.zig +++ b/test/behavior/merge_error_sets.zig @@ -13,7 +13,6 @@ fn foo() C!void { test "merge error sets" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (foo()) { @panic("unexpected"); diff --git a/test/behavior/null.zig b/test/behavior/null.zig index e9fc66f4b8b6ddc803677aeea4827a2bb8930b03..ec57819580a9489ae81efd2b2f1d148551c6af9d 100644 --- a/test/behavior/null.zig +++ b/test/behavior/null.zig @@ -53,7 +53,6 @@ test "maybe return" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try maybeReturnImpl(); try comptime maybeReturnImpl(); @@ -84,7 +83,6 @@ fn testTestNullRuntime(x: ?i32) !void { test "optional void" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try optionalVoidImpl(); try comptime optionalVoidImpl(); @@ -108,7 +106,6 @@ const Empty = struct {}; test "optional struct{}" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; _ = try optionalEmptyStructImpl(); _ = try comptime optionalEmptyStructImpl(); @@ -134,7 +131,6 @@ test "null with default unwrap" { test "optional pointer to 0 bit type null value at runtime" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const EmptyStruct = struct {}; var x: ?*EmptyStruct = null; diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index 3bd171e9d4e5f221060b5ea18db70cc441cc2bf7..3528b3f571a3ffa325ec639ee4cf6debde3eef01 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -34,8 +34,6 @@ test "optional pointer to size zero struct" { } test "equality compare optional pointers" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try testNullPtrsEql(); try comptime testNullPtrsEql(); } @@ -60,7 +58,6 @@ test "optional with void type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 Foo = struct { x: ?void, @@ -95,7 +92,6 @@ test "nested optional field in struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 S2 = struct { y: u8, @@ -113,7 +109,6 @@ test "equality compare optional with non-optional" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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; try test_cmp_optional_non_optional(); try comptime test_cmp_optional_non_optional(); @@ -172,7 +167,6 @@ test "unwrap function call with optional pointer return value" { test "nested orelse" { 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 entry() !void { @@ -255,7 +249,6 @@ test "0-bit child type coerced to optional return ptr result location" { 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 { @@ -308,7 +301,6 @@ test "array of optional unaligned types" { 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 Enum = enum { one, two, three }; @@ -444,7 +436,6 @@ test "Optional slice size is optimized" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(@sizeOf(?[]u8) == @sizeOf([]u8)); var a: ?[]const u8 = null; @@ -456,7 +447,6 @@ test "Optional slice size is optimized" { test "peer type resolution in nested if expressions" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Thing = struct { n: i32 }; var a = false; @@ -496,8 +486,6 @@ test "cast slice to const slice nested in error union and optional" { } test "variable of optional of noreturn" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var null_opv: ?noreturn = null; try std.testing.expectEqual(@as(?noreturn, null), null_opv); } diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index de98b3e27dee410f0eb312f13c74e7df99a1fb2f..8f89ab748e7516c9e7510a280dce9f8786a11ce4 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -622,6 +622,7 @@ test "@intFromPtr on a packed struct field unaligned and nested" { test "packed struct fields modification" { // Originally reported at https://github.com/ziglang/zig/issues/16615 + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Small = packed struct { val: u8 = 0, @@ -980,6 +981,8 @@ test "store undefined to packed result location" { } test "bitcast back and forth" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + // Originally reported at https://github.com/ziglang/zig/issues/9914 const S = packed struct { one: u6, two: u1 }; const s = S{ .one = 0b110101, .two = 0b1 }; @@ -991,6 +994,7 @@ test "bitcast back and forth" { test "field access of packed struct smaller than its abi size inside struct initialized with rls" { // Originally reported at https://github.com/ziglang/zig/issues/14200 + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { ps: packed struct { x: i2, y: i2 }, @@ -1039,6 +1043,7 @@ test "modify nested packed struct aligned field" { test "assigning packed struct inside another packed struct" { // Originally reported at https://github.com/ziglang/zig/issues/9674 + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const Inner = packed struct { diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig index ab14bf38e760eac27fdfec0a603e19b3b068cffa..cd71f965c40bcfcc5cb547c980d09631d8002316 100644 --- a/test/behavior/packed-union.zig +++ b/test/behavior/packed-union.zig @@ -88,6 +88,7 @@ test "flags in packed union at offset" { test "packed union in packed struct" { // Originally reported at https://github.com/ziglang/zig/issues/16581 + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const ReadRequest = packed struct { key: i32 }; const RequestType = enum { diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index ad3d9717e14ec1ecd2fb77280b81f7d3747eb51d..0a781cc0578aa9bb312224eabe461f41fcc219c6 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -191,7 +191,6 @@ test "allowzero pointer and slice" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var ptr = @as([*]allowzero i32, @ptrFromInt(0)); var opt_ptr: ?[*]allowzero i32 = ptr; @@ -276,7 +275,6 @@ test "array initialization types" { test "null terminated pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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 { @@ -411,7 +409,6 @@ test "indexing array with sentinel returns correct type" { 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; var s: [:0]const u8 = "abc"; try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0]))); @@ -496,7 +493,6 @@ test "ptrCast comptime known slice to C pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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: [:0]const u8 = "foo"; var p = @as([*c]const u8, @ptrCast(s)); @@ -507,7 +503,6 @@ test "intFromPtr on a generic function" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn generic(i: anytype) @TypeOf(i) { diff --git a/test/behavior/ptrcast.zig b/test/behavior/ptrcast.zig index 8837c42a864c0b2077822fdf6ca8b4588d46359c..7f6323084f3e4457b3c065a5ca54e7173e063700 100644 --- a/test/behavior/ptrcast.zig +++ b/test/behavior/ptrcast.zig @@ -233,7 +233,6 @@ test "implicit optional pointer to optional anyopaque pointer" { 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_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [4]u8 = "aoeu".*; var x: ?[*]u8 = &buf; @@ -246,7 +245,6 @@ test "@ptrCast slice to slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 foo(slice: []u32) []i32 { @@ -286,6 +284,8 @@ test "@ptrCast undefined value at comptime" { } test "comptime @ptrCast with packed struct leaves value unmodified" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const S = packed struct { three: u3 }; const st: S = .{ .three = 6 }; try expect(st.three == 6); diff --git a/test/behavior/ptrfromint.zig b/test/behavior/ptrfromint.zig index 2cf72936a12c028c9e6633d5bfc8bafaac3df92e..72244aa7d122178eabb8624a52bc6f0176565d64 100644 --- a/test/behavior/ptrfromint.zig +++ b/test/behavior/ptrfromint.zig @@ -33,7 +33,6 @@ test "@ptrFromInt creates null pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const ptr = @as(?*u32, @ptrFromInt(0)); try expectEqual(@as(?*u32, null), ptr); @@ -43,7 +42,6 @@ test "@ptrFromInt creates allowzero zero pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const ptr = @as(*allowzero u32, @ptrFromInt(0)); try expectEqual(@as(usize, 0), @intFromPtr(ptr)); diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index a161be66eb0526aae2648ca10f83185f53e621fa..ddb384cb7b31c78aa8ea723884fc16c3c3fc4011 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -18,8 +18,6 @@ test "@sizeOf on compile-time types" { } test "@TypeOf() with multiple arguments" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - { var var_1: u32 = undefined; var var_2: u8 = undefined; @@ -268,7 +266,6 @@ test "runtime instructions inside typeof in comptime only scope" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; { var y: i8 = 2; diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index cbd3b5416341c63181298516a6f33b5310aaf926..b195b3a5c1a484cd4094d6b1febfe8341bdfc5c3 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -227,7 +227,6 @@ test "runtime safety lets us slice from len..len" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var an_array = [_]u8{ 1, 2, 3 }; try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); @@ -240,7 +239,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { test "C pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf"; var len: u32 = 10; @@ -252,7 +250,6 @@ test "C pointer slice access" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [10]u32 = [1]u32{42} ** 10; const c_ptr = @as([*c]const u32, @ptrCast(&buf)); @@ -282,7 +279,6 @@ fn sliceSum(comptime q: []const u8) i32 { test "slice type with custom alignment" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const LazilyResolvedType = struct { anything: i32, @@ -356,7 +352,6 @@ test "slice syntax resulting in pointer-to-array" { 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 { @@ -615,7 +610,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" { 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 { const U = union { @@ -830,7 +824,6 @@ test "empty slice ptr is non null" { test "slice decays to many pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var buf: [8]u8 = "abcdefg\x00".*; const p: [*:0]const u8 = buf[0..7 :0]; @@ -841,7 +834,6 @@ test "write through pointer to optional slice arg" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn bar(foo: *?[]const u8) !void { @@ -861,7 +853,6 @@ test "modify slice length at comptime" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const arr: [2]u8 = .{ 10, 20 }; comptime var s: []const u8 = arr[0..0]; diff --git a/test/behavior/src.zig b/test/behavior/src.zig index 71c2753dad912274afda30b05c7ea4798711f21a..89a8e424aacaaf00b6e1a5378d476b232dd9094c 100644 --- a/test/behavior/src.zig +++ b/test/behavior/src.zig @@ -33,8 +33,6 @@ test "@src used as a comptime parameter" { } test "@src in tuple passed to anytype function" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn Foo(a: anytype) u32 { return a[0].line; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index a914ff946c271882e423d9f34040f85c76610ab4..8e7aa598446e9d2973adedae42de88713c5f7c57 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -134,8 +134,6 @@ test "invoke static method in global scope" { const empty_global_instance = StructWithNoFields{}; test "return empty struct instance" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - _ = returnEmptyStructInstance(); } fn returnEmptyStructInstance() StructWithNoFields { @@ -328,7 +326,6 @@ const VoidStructFieldsFoo = struct { test "return empty struct from fn" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; _ = testReturnEmptyStructFromFn(); } diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 8460798c5372f6566d8c8a623c35d2f4c3b5f4b9..df4d2af7d0e706bed3092f5fe0604239c491018d 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -623,7 +623,6 @@ test "switch capture copies its payload" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 { @@ -710,8 +709,6 @@ test "comptime inline switch" { } test "switch capture peer type resolution" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const U = union(enum) { a: u32, b: u64, @@ -727,8 +724,6 @@ test "switch capture peer type resolution" { } test "switch capture peer type resolution for in-memory coercible payloads" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const T1 = c_int; const T2 = @Type(@typeInfo(T1)); @@ -777,8 +772,6 @@ test "switch pointer capture peer type resolution" { } test "inline switch range that includes the maximum value of the switched type" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const inputs: [3]u8 = .{ 0, 254, 255 }; for (inputs) |input| { switch (input) { diff --git a/test/behavior/switch_prong_err_enum.zig b/test/behavior/switch_prong_err_enum.zig index f09e2fb7d36cc21b7fcca9b34f15d9530369db11..15d366d04f1f20c632354f982f375eaeeebb53c9 100644 --- a/test/behavior/switch_prong_err_enum.zig +++ b/test/behavior/switch_prong_err_enum.zig @@ -24,7 +24,6 @@ test "switch prong returns error enum" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; switch (doThing(17) catch unreachable) { FormValue.Address => |payload| { diff --git a/test/behavior/switch_prong_implicit_cast.zig b/test/behavior/switch_prong_implicit_cast.zig index 4be8f82085152cbb45b241c6ec9c1eb9a7725a06..54107bb6bd1e9ff60b9ca58faffc3b2868674354 100644 --- a/test/behavior/switch_prong_implicit_cast.zig +++ b/test/behavior/switch_prong_implicit_cast.zig @@ -18,7 +18,6 @@ test "switch prong implicit cast" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const result = switch (foo(2) catch unreachable) { FormValue.One => false, diff --git a/test/behavior/threadlocal.zig b/test/behavior/threadlocal.zig index 9a6e0542e87d39d4d08ba370ebbacb8f8b0c773a..e5a9e9542d8a4a375966c22a49df3ad0e0fc8672 100644 --- a/test/behavior/threadlocal.zig +++ b/test/behavior/threadlocal.zig @@ -33,7 +33,6 @@ test "pointer to thread local array" { else => 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 = "Hello world"; std.mem.copy(u8, buffer[0..], s); diff --git a/test/behavior/try.zig b/test/behavior/try.zig index 49581977f9a3a6143b7c682f8e608842009b3bd9..d2ac927338536fd49a2e92c8fa01951a890792ea 100644 --- a/test/behavior/try.zig +++ b/test/behavior/try.zig @@ -4,7 +4,6 @@ const expect = std.testing.expect; test "try on error union" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try tryOnErrorUnionImpl(); try comptime tryOnErrorUnionImpl(); @@ -40,8 +39,6 @@ fn failIfTrue(ok: bool) anyerror!void { } test "try then not executed with assignment" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (failIfTrue(true)) { unreachable; } else |err| { diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 49872dde2a93e83b89d4456014071d6b875ac7ef..04da0ee47b2a9da12efe577d5257d143766a1c6f 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -10,7 +10,6 @@ test "tuple concatenation" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 { @@ -269,7 +268,6 @@ test "tuple in tuple passed to generic function" { 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 pair(x: f32, y: f32) std.meta.Tuple(&.{ f32, f32 }) { @@ -310,8 +308,6 @@ test "tuple type with void field" { } test "zero sized struct in tuple handled correctly" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const State = struct { const Self = @This(); data: @Type(.{ @@ -351,7 +347,6 @@ test "branching inside tuple literal" { 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 foo(a: anytype) !void { @@ -366,7 +361,6 @@ test "tuple initialized with a runtime known value" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const E = union(enum) { e: []const u8 }; const W = union(enum) { w: E }; @@ -380,7 +374,6 @@ test "tuple of struct concatenation and coercion to array" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const StructWithDefault = struct { value: f32 = 42 }; const SomeStruct = struct { array: [4]StructWithDefault }; @@ -395,7 +388,6 @@ test "nested runtime conditionals in tuple initializer" { 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; var data: u8 = 0; const x = .{ @@ -430,7 +422,6 @@ test "tuple pointer is indexable" { 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; // TODO const S = struct { u32, bool }; @@ -454,7 +445,6 @@ test "coerce anon tuple to tuple" { 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; // TODO var x: u8 = 1; var y: u16 = 2; diff --git a/test/behavior/tuple_declarations.zig b/test/behavior/tuple_declarations.zig index 1936d770432defc7ed603aba67a85982076cf272..8ffc25613d28a7c1fd31d78d25fdd9d8a1f7ffee 100644 --- a/test/behavior/tuple_declarations.zig +++ b/test/behavior/tuple_declarations.zig @@ -7,7 +7,6 @@ const expectEqualStrings = testing.expectEqualStrings; test "tuple declaration type info" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; { const T = struct { comptime u32 align(2) = 1, []const u8 }; @@ -36,7 +35,6 @@ test "tuple declaration type info" { test "Tuple declaration usage" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const T = struct { u32, []const u8 }; var t: T = .{ 1, "foo" }; diff --git a/test/behavior/type.zig b/test/behavior/type.zig index 56dca635907ae9f10fcd178332166bc27fabee76..7d0147c508090f8918d7d803d178840667f418aa 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -202,7 +202,6 @@ test "Type.Opaque" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Opaque = @Type(.{ .Opaque = .{ @@ -260,7 +259,6 @@ test "Type.Struct" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const A = @Type(@typeInfo(struct { x: u8, y: u32 })); const infoA = @typeInfo(A).Struct; @@ -348,7 +346,6 @@ test "Type.Struct" { test "Type.Enum" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Foo = @Type(.{ .Enum = .{ diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig index 30db77e0ea088c3adba7263ce0b38b00d5d584ea..bc4737a5524b4fc0a6beffb5382d4b129fba4f5d 100644 --- a/test/behavior/type_info.zig +++ b/test/behavior/type_info.zig @@ -565,7 +565,6 @@ test "value from struct @typeInfo default_value can be loaded at comptime" { test "@typeInfo decls and usingnamespace" { 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; const A = struct { pub const x = 5; diff --git a/test/behavior/type_info_only_pub_decls.zig b/test/behavior/type_info_only_pub_decls.zig index 80d05d8ba1bfc13a2c3156d102a71c50798e8a3f..5d08d631b9c003af06459d33fbadc9ad47ade1d3 100644 --- a/test/behavior/type_info_only_pub_decls.zig +++ b/test/behavior/type_info_only_pub_decls.zig @@ -15,8 +15,6 @@ const other = struct { }; test { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const ti = @typeInfo(other); const decls = ti.Struct.decls; diff --git a/test/behavior/typename.zig b/test/behavior/typename.zig index fa675aa93b0965f5064185151982c2f8ed95da26..03bfa15d5f0d61138a380cc77c7085e68ea9525b 100644 --- a/test/behavior/typename.zig +++ b/test/behavior/typename.zig @@ -67,7 +67,6 @@ test "basic" { 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; try expectEqualStrings("i64", @typeName(i64)); try expectEqualStrings("*usize", @typeName(*usize)); @@ -231,7 +230,6 @@ test "comptime parameters not converted to anytype in function type" { 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 T = fn (fn (type) void, void) void; try expectEqualStrings("fn (comptime fn (comptime type) void, void) void", @typeName(T)); diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 3b1ddf527d5ba04a3d8362e9285afeac0c84f96e..6b87ab96ce69361e41bc349902caae157a029f24 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -97,7 +97,6 @@ const FooExtern = extern union { test "basic extern unions" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var foo = FooExtern{ .int = 1 }; try expect(foo.int == 1); @@ -218,7 +217,6 @@ test "union with specified enum tag" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try doTest(); try comptime doTest(); @@ -381,7 +379,6 @@ test "tagged union initialization with runtime void" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(testTaggedUnionInit({})); } @@ -466,7 +463,6 @@ test "initialize global array of union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; glbl_array[1] = FooUnion{ .U1 = 2 }; glbl_array[0] = FooUnion{ .U0 = 1 }; @@ -966,7 +962,6 @@ test "cast from anonymous struct to union" { 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 { const U = union(enum) { @@ -1056,7 +1051,6 @@ test "containers with single-field enums" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) 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 A = union(enum) { f1 }; @@ -1573,7 +1567,6 @@ test "undefined-layout union field pointer has correct alignment" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest(comptime U: type) !void { @@ -1659,6 +1652,8 @@ test "union with 128 bit integer" { } test "memset extern union" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const U = extern union { foo: u8, bar: u32, @@ -1678,6 +1673,8 @@ test "memset extern union" { } test "memset packed union" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const U = packed union { a: u32, b: u8, @@ -1703,6 +1700,8 @@ fn littleToNativeEndian(comptime T: type, v: T) T { } test "reinterpret extern union" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const U = extern union { foo: u8, baz: u32 align(8), @@ -1771,6 +1770,8 @@ test "reinterpret extern union" { } test "reinterpret packed union" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const U = packed union { foo: u8, bar: u29, @@ -1842,6 +1843,8 @@ test "reinterpret packed union" { } test "reinterpret packed union inside packed struct" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const U = packed union { a: u7, b: u1, diff --git a/test/behavior/usingnamespace.zig b/test/behavior/usingnamespace.zig index 212edb353de3c1dd2ee75675f4421aa2a1511d0d..d67a0958e3b6dd127ffc9592bda5d55831282d94 100644 --- a/test/behavior/usingnamespace.zig +++ b/test/behavior/usingnamespace.zig @@ -55,7 +55,6 @@ usingnamespace @import("usingnamespace/a.zig"); test "two files usingnamespace import each other" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(@This().ok()); } diff --git a/test/behavior/var_args.zig b/test/behavior/var_args.zig index d2a9817a96f6af8ee2163c9bf92dc79fde116a69..7fda8b208aabee787140bbd8a381830cbdb0b4a7 100644 --- a/test/behavior/var_args.zig +++ b/test/behavior/var_args.zig @@ -14,8 +14,6 @@ fn add(args: anytype) i32 { } test "add arbitrary args" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); try expect(add(.{@as(i32, 1234)}) == 1234); try expect(add(.{}) == 0); @@ -26,15 +24,12 @@ fn readFirstVarArg(args: anytype) void { } test "send void arg to var args" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - readFirstVarArg(.{{}}); } test "pass args directly" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234); @@ -48,7 +43,6 @@ fn addSomeStuff(args: anytype) i32 { test "runtime parameter before var args" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect((try extraFn(10, .{})) == 0); try expect((try extraFn(10, .{false})) == 1); @@ -87,15 +81,11 @@ fn foo2(args: anytype) bool { } test "array of var args functions" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(foos[0](.{})); try expect(!foos[1](.{})); } test "pass zero length array to var args param" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - doNothingWithFirstArg(.{""}); } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index caf92f17cbb6785b1d870800518de3d0b27d979f..e9d7bade24f07a6ae828a7306b06784c98fff287 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -11,7 +11,6 @@ test "implicit cast vector to array - bool" { 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 { diff --git a/test/behavior/void.zig b/test/behavior/void.zig index b726dbe0045888845fa7bebb7e415e255f94685a..8c6269123d9ade29c05984eaaf2768b32d6d74ba 100644 --- a/test/behavior/void.zig +++ b/test/behavior/void.zig @@ -20,7 +20,6 @@ test "compare void with void compile time known" { test "iterate over a void slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var j: usize = 0; for (times(10), 0..) |_, i| { @@ -37,7 +36,6 @@ test "void optional" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: ?void = {}; try expect(x != null); diff --git a/test/behavior/while.zig b/test/behavior/while.zig index bc051aca3289c8ae222d59170c385891fd14be56..5dc3aef3f0844f1973dee906c110991bced9d744 100644 --- a/test/behavior/while.zig +++ b/test/behavior/while.zig @@ -172,7 +172,6 @@ test "while with optional as condition with else" { test "while with error union condition" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; numbers_left = 10; var sum: i32 = 0; diff --git a/test/behavior/widening.zig b/test/behavior/widening.zig index 1f70ad124271d2bb98228bdcac653f1b643300c2..f44f577dcb21114ba69b6eb903c24141a8447e91 100644 --- a/test/behavior/widening.zig +++ b/test/behavior/widening.zig @@ -22,8 +22,6 @@ fn zero() u0 { return 0; } test "integer widening u0 to u8" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const a: u8 = zero(); try expect(a == 0); } -- 2.54.0 From 8c153221b9e1ff34edd18382770d02aae36dbe74 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 15 Oct 2023 20:07:24 +0200 Subject: [PATCH 36/36] wasm: disable division test Seems that bit integers are not properly supported --- test/behavior/math.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 894d620d901cb05977e563c9a4b5ba618d5eb6f0..579e73b17d995fe0b90b89df0a4889cb57723ebe 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -413,6 +413,7 @@ test "division" { 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; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) { -- 2.54.0