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 a4d3ec7f46..39dd1e6cb0 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 68fea5c47a..7f5590344c 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)))) }, 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 39dd1e6cb0..64850ad63f 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 d3906a13d7..e3efc0f671 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 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 64850ad63f..8a3745edb2 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 9f430a105a..0ebdffd16c 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, 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 8a3745edb2..b2aab968e9 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 0ebdffd16c..8049abb8dd 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 { 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 e18ffece3d..cddd4340d7 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 b2aab968e9..adb9155cfd 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 e3efc0f671..89aec81578 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| { 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 81b97ebae5..2aacc5b748 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 89aec81578..f22fe13467 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| { 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 adb9155cfd..93ae552b10 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 2aacc5b748..c16e1a6d72 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; 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 93ae552b10..3a751fed68 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 f22fe13467..58d8ca6841 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 { 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 3a751fed68..2fdec5675f 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 416ef0c29c..f91bbe6edf 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 3f9e41b470..8db14affcf 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 { 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 2fdec5675f..fd984c78d5 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 8db14affcf..316bc6d2cc 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, }; 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 fd984c78d5..293ef5860b 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, 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 293ef5860b..82e172c0d7 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 211fba932b..b1fc2f0fb9 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"; 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 82e172c0d7..41848644c4 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 cc4723405f..a642860e4e 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 b1fc2f0fb9..bf90d661fb 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; 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 41848644c4..0ab87b4df0 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 a642860e4e..ec198c3133 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 8974b75dbe..ad3d9717e1 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); 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 0ab87b4df0..86232c6149 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 ec198c3133..388d6f4750 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.* = {}; 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 86232c6149..7528c40cca 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 0b2d7d1110..3bd171e9d4 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(); 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 7528c40cca..6881b2c598 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 58d8ca6841..325bb30fe0 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 388d6f4750..4a6b4db2ce 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; 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 6881b2c598..e8e1b89507 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 8049abb8dd..cbd3b54163 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{}; 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 e8e1b89507..dc572d390e 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 40224e5026..a8d42f6589 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| 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 dc572d390e..638bf7b187 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 4a6b4db2ce..ca491a0a22 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; 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 638bf7b187..62f945dd81 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 7f5590344c..ad2d3442e5 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 ca491a0a22..20867fa7e8 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; 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 62f945dd81..42a11120b5 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 c76dd7573d..0b9ca8c636 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(); 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 14490c21db..36a5c65deb 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| { 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 4dda8a0d0d..d4d162721d 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 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 42a11120b5..fab69da39b 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 0bf1e93078..aec2920eb1 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, 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 fab69da39b..6fff39f951 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; 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 d4d162721d..95f1b156c1 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 f91bbe6edf..3436cba9ba 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 20867fa7e8..69e8c88b79 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 9c81bcde89..71c2753dad 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 316bc6d2cc..a914ff946c 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 { 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 6fff39f951..bb2fe4219c 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) { 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 bb2fe4219c..c9c11dd44e 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 { 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 4c8e64768b..c912f561c6 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 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 c9c11dd44e..3a5c9b876b 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 81e51f4983..ed118be641 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 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 ebcccd781d..3eac273164 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 0b9ca8c636..ecc32a33f6 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)); + } } }; 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 | 84 ++++++++++++++++++++++++++++++++++------ test/behavior/vector.zig | 19 --------- 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3a5c9b876b..0f0adf5646 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,13 +2089,30 @@ const DeclGen = struct { try self.inst_results.putNoClobber(self.gpa, inst, 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); + 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(self.typeOfIndex(inst)); + 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, @@ -2104,6 +2122,17 @@ const DeclGen = struct { 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 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 { if (self.liveness.isUnused(inst)) return null; const bin_op = self.air.instructions.items(.data)[inst].bin_op; @@ -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 ed118be641..caf92f17cb 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 { 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 c16e1a6d72..1936b78826 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.*; 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 98ca04a5a5..51ade3dbcf 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 4b5dfafdc8..00fbfc2cb5 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 a8d42f6589..2586770c6f 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 3436cba9ba..b85f2e6d2b 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 d01700ed89..e21ae2b20c 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 f2b0e09bbd..f09dd35771 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 9aca002c90..26d863d901 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 6bf6041a65..a13e02e45c 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 85b2e6957b..7af8b59101 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 875c12697b..7f13b6efd8 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 0c470bee5b..8ddf80fd8e 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 e438539f55..e5e89a9c58 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 ca66b1f8f5..14fb8af15a 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 b2a79c0847..df01e5cbdd 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 3c0cc5656f..d1514d2e47 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 a832f14cef..1316c2745e 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 82995eb019..354d9e856e 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 329e993ab8..3c256a19f8 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 f997bb46b9..a6fea11e86 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 d6c63db84b..74f1d01c8c 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 b6c0341044..9b08bcd3fc 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 cd0b289e5f..c9ea2102f5 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 7ce138dfd7..02170ccabe 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 32d5b38ba3..6fbd8fe075 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 0d56808f45..f4da8e5c2e 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 52c1e3ac6b..3f3bbb9b56 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 9cf34e980d..ff8ba141fa 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 0eed28b2e7..d89b3b5449 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 683ece874e..24e18043a0 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 775e918f63..68b7d90ae8 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 09d209912e..e0d46e72c3 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 088443d529..c2bd103118 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 ac9f15dfef..3ea8cad220 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 410adf0311..be96efaace 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 37e8d31cc9..c544e422a4 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 e6dcbe4e64..b835b81b54 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 beccb059d8..61aa48803b 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 69e8c88b79..91e2812591 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 aacb06b40d..5232c828d0 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 d6b3ae3993..84ecb8fbc9 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 68c6863bcd..35bc007d84 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 c70fad4b45..593282ac59 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 53408875ae..40bdd627f3 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 13d079ddf9..efd0295a97 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 c0725f8779..72003d1ea8 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 39bfbe1ba7..a57d537c30 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 05ac8a6a89..f114f30fa9 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 ed69a8d8e9..aad7f57590 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 bf90d661fb..5a41f75077 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 8ecb069956..2981c73f22 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 a38f68cf91..68ea986c05 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 43a02df01d..305b898bfc 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 32c670fff4..c384f62086 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 136f23409b..a46ad2d8a8 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 41faad14c0..948d708aa7 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 aec2920eb1..894d620d90 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 ecc32a33f6..3fabe1aa59 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 62aa77fb18..492cb27699 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 e9fc66f4b8..ec57819580 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 3bd171e9d4..3528b3f571 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 de98b3e27d..8f89ab748e 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 ab14bf38e7..cd71f965c4 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 ad3d9717e1..0a781cc057 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 8837c42a86..7f6323084f 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 2cf72936a1..72244aa7d1 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 a161be66eb..ddb384cb7b 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 cbd3b54163..b195b3a5c1 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 71c2753dad..89a8e424aa 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 a914ff946c..8e7aa59844 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 8460798c53..df4d2af7d0 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 f09e2fb7d3..15d366d04f 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 4be8f82085..54107bb6bd 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 9a6e0542e8..e5a9e9542d 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 49581977f9..d2ac927338 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 49872dde2a..04da0ee47b 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 1936d77043..8ffc25613d 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 56dca63590..7d0147c508 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 30db77e0ea..bc4737a552 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 80d05d8ba1..5d08d631b9 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 fa675aa93b..03bfa15d5f 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 3b1ddf527d..6b87ab96ce 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 212edb353d..d67a0958e3 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 d2a9817a96..7fda8b208a 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 caf92f17cb..e9d7bade24 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 b726dbe004..8c6269123d 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 bc051aca32..5dc3aef3f0 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 1f70ad1242..f44f577dcb 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); } 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 894d620d90..579e73b17d 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()) {