diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 644bb95cca11..cb8b5a787d95 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -242,7 +242,7 @@ pub const DeclGen = struct { return self.spv.declPtr(spv_decl_index).result_id; } - return try self.constant(ty, val); + return try self.constant(ty, val, .direct); } const index = Air.refToIndex(inst).?; return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. @@ -369,21 +369,11 @@ pub const DeclGen = struct { .composite_integer, }; }, - .Enum => blk: { - var buffer: Type.Payload.Bits = undefined; - const int_ty = ty.intTagType(&buffer); - const int_info = int_ty.intInfo(target); - break :blk ArithmeticTypeInfo{ - .bits = int_info.bits, - .is_vector = false, - .signedness = int_info.signedness, - .class = .integer, - }; - }, // 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? - else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), + // else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), + else => unreachable, }; } @@ -452,6 +442,37 @@ pub const DeclGen = struct { } } + /// Construct a struct at runtime. + /// result_ty_ref must be a struct type. + fn constructStruct(self: *DeclGen, result_ty_ref: SpvType.Ref, constituents: []const IdRef) !IdRef { + // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' + // operands are not constant. + // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 + // For now, just initialize the struct by setting the fields manually... + // TODO: Make this OpCompositeConstruct when we can + const ptr_composite_id = try self.alloc(result_ty_ref, null); + // Note: using 32-bit ints here because usize crashes the translator as well + const index_ty_ref = try self.intType(.unsigned, 32); + const spv_composite_ty = self.spv.typeRefType(result_ty_ref); + const members = spv_composite_ty.payload(.@"struct").members; + for (constituents, members, 0..) |constitent_id, member, index| { + const index_id = try self.constInt(index_ty_ref, index); + const ptr_member_ty_ref = try self.spv.ptrType(member.ty, .Generic, 0); + const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{index_id}); + try self.func.body.emit(self.spv.gpa, .OpStore, .{ + .pointer = ptr_id, + .object = constitent_id, + }); + } + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpLoad, .{ + .id_result_type = self.typeId(result_ty_ref), + .id_result = result_id, + .pointer = ptr_composite_id, + }); + return result_id; + } + const IndirectConstantLowering = struct { const undef = 0xAA; @@ -705,6 +726,10 @@ pub const DeclGen = struct { try self.lower(ptr_ty, slice.ptr); try self.addInt(Type.usize, slice.len); }, + .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)), + .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { + try self.addInt(Type.usize, val); + }, else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}), }, .Struct => { @@ -996,14 +1021,16 @@ pub const DeclGen = struct { /// the constant is more complicated however, it needs to be lowered to an indirect constant, which /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default. /// This function should only be called during function code generation. - fn constant(self: *DeclGen, ty: Type, val: Value) !IdRef { + fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef { const target = self.getTarget(); const section = &self.spv.sections.types_globals_constants; - const result_ty_ref = try self.resolveType(ty, .direct); + const result_ty_ref = try self.resolveType(ty, repr); const result_ty_id = self.typeId(result_ty_ref); - const result_id = self.spv.allocId(); + + log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) }); if (val.isUndef()) { + const result_id = self.spv.allocId(); try section.emit(self.spv.gpa, .OpUndef, .{ .id_result_type = result_ty_id, .id_result = result_id, @@ -1014,24 +1041,76 @@ pub const DeclGen = struct { switch (ty.zigTypeTag()) { .Int => { if (ty.isSignedInt()) { - try self.genConstInt(result_ty_ref, result_id, val.toSignedInt(target)); + return try self.constInt(result_ty_ref, val.toSignedInt(target)); } else { - try self.genConstInt(result_ty_ref, result_id, val.toUnsignedInt(target)); + return try self.constInt(result_ty_ref, val.toUnsignedInt(target)); } }, - .Bool => { - const operands = .{ .id_result_type = result_ty_id, .id_result = result_id }; - if (val.toBool()) { - try section.emit(self.spv.gpa, .OpConstantTrue, operands); + .Bool => switch (repr) { + .direct => { + const result_id = self.spv.allocId(); + const operands = .{ .id_result_type = result_ty_id, .id_result = result_id }; + if (val.toBool()) { + try section.emit(self.spv.gpa, .OpConstantTrue, operands); + } else { + try section.emit(self.spv.gpa, .OpConstantFalse, operands); + } + return result_id; + }, + .indirect => return try self.constInt(result_ty_ref, @boolToInt(val.toBool())), + }, + .Float => { + const result_id = self.spv.allocId(); + switch (ty.floatBits(target)) { + 16 => try self.spv.emitConstant(result_ty_id, result_id, .{ .float32 = val.toFloat(f16) }), + 32 => try self.spv.emitConstant(result_ty_id, result_id, .{ .float32 = val.toFloat(f32) }), + 64 => try self.spv.emitConstant(result_ty_id, result_id, .{ .float64 = val.toFloat(f64) }), + 80, 128 => unreachable, // TODO + else => unreachable, + } + return result_id; + }, + .ErrorSet => { + const value = switch (val.tag()) { + .@"error" => blk: { + const err_name = val.castTag(.@"error").?.data.name; + const kv = try self.module.getErrorValue(err_name); + break :blk @intCast(u16, kv.value); + }, + .zero => 0, + else => unreachable, + }; + + return try self.constInt(result_ty_ref, value); + }, + .ErrorUnion => { + const payload_ty = ty.errorUnionPayload(); + const is_pl = val.errorUnionIsPayload(); + const error_val = if (!is_pl) val else Value.initTag(.zero); + + const eu_layout = self.errorUnionLayout(payload_ty); + if (!eu_layout.payload_has_bits) { + return try self.constant(Type.anyerror, error_val, repr); + } + + const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); + + var members: [2]IdRef = undefined; + if (eu_layout.error_first) { + members[0] = try self.constant(Type.anyerror, error_val, .indirect); + members[1] = try self.constant(payload_ty, payload_val, .indirect); } else { - try section.emit(self.spv.gpa, .OpConstantFalse, operands); + members[0] = try self.constant(payload_ty, payload_val, .indirect); + members[1] = try self.constant(Type.anyerror, error_val, .indirect); } + return try self.spv.constComposite(result_ty_ref, &members); }, // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra // OpVariable that is not really required. else => { // The value cannot be generated directly, so generate it as an indirect constant, // and then perform an OpLoad. + const result_id = self.spv.allocId(); const alignment = ty.abiAlignment(target); const spv_decl_index = try self.spv.allocDecl(.global); @@ -1053,10 +1132,9 @@ pub const DeclGen = struct { }); // TODO: Convert bools? This logic should hook into `load`. It should be a dead // path though considering .Bool is handled above. + return result_id; }, } - - return result_id; } /// Turn a Zig type into a SPIR-V Type, and return its type result-id. @@ -1592,10 +1670,23 @@ pub const DeclGen = struct { } } + fn boolToInt(self: *DeclGen, result_ty_ref: SpvType.Ref, condition_id: IdRef) !IdRef { + const zero_id = try self.constInt(result_ty_ref, 0); + const one_id = try self.constInt(result_ty_ref, 1); + 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 = condition_id, + .object_1 = one_id, + .object_2 = zero_id, + }); + return result_id; + } + /// Convert representation from indirect (in memory) to direct (in 'register') /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct). fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { - // const direct_ty_ref = try self.resolveType(ty, .direct); return switch (ty.zigTypeTag()) { .Bool => blk: { const direct_bool_ty_ref = try self.resolveType(ty, .direct); @@ -1620,17 +1711,7 @@ pub const DeclGen = struct { return switch (ty.zigTypeTag()) { .Bool => blk: { const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); - const zero_id = try self.constInt(indirect_bool_ty_ref, 0); - const one_id = try self.constInt(indirect_bool_ty_ref, 1); - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpSelect, .{ - .id_result_type = self.typeId(indirect_bool_ty_ref), - .id_result = result_id, - .condition = operand_id, - .object_1 = one_id, - .object_2 = zero_id, - }); - break :blk result_id; + break :blk self.boolToInt(indirect_bool_ty_ref, operand_id); }, else => operand_id, }; @@ -1714,6 +1795,9 @@ pub const DeclGen = struct { .shuffle => try self.airShuffle(inst), + .ptr_add => try self.airPtrAdd(inst), + .ptr_sub => try self.airPtrSub(inst), + .bit_and => try self.airBinOpSimple(inst, .OpBitwiseAnd), .bit_or => try self.airBinOpSimple(inst, .OpBitwiseOr), .xor => try self.airBinOpSimple(inst, .OpBitwiseXor), @@ -1722,8 +1806,8 @@ pub const DeclGen = struct { .shl => try self.airShift(inst, .OpShiftLeftLogical), - .bitcast => try self.airBitcast(inst), - .intcast, .trunc => try self.airIntcast(inst), + .bitcast => try self.airBitCast(inst), + .intcast, .trunc => try self.airIntCast(inst), .ptrtoint => try self.airPtrToInt(inst), .int_to_float => try self.airIntToFloat(inst), .float_to_int => try self.airFloatToInt(inst), @@ -1734,6 +1818,7 @@ pub const DeclGen = struct { .slice_elem_ptr => try self.airSliceElemPtr(inst), .slice_elem_val => try self.airSliceElemVal(inst), .ptr_elem_ptr => try self.airPtrElemPtr(inst), + .ptr_elem_val => try self.airPtrElemVal(inst), .get_union_tag => try self.airGetUnionTag(inst), .struct_field_val => try self.airStructFieldVal(inst), @@ -1743,12 +1828,12 @@ pub 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, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual), - .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual), - .cmp_gt => try self.airCmp(inst, .OpFOrdGreaterThan, .OpSGreaterThan, .OpUGreaterThan), - .cmp_gte => try self.airCmp(inst, .OpFOrdGreaterThanEqual, .OpSGreaterThanEqual, .OpUGreaterThanEqual), - .cmp_lt => try self.airCmp(inst, .OpFOrdLessThan, .OpSLessThan, .OpULessThan), - .cmp_lte => try self.airCmp(inst, .OpFOrdLessThanEqual, .OpSLessThanEqual, .OpULessThanEqual), + .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), .arg => self.airArg(), .alloc => try self.airAlloc(inst), @@ -1944,64 +2029,83 @@ pub const DeclGen = struct { .float, .bool => unreachable, } - // The operand type must be the same as the result type in SPIR-V. + // The operand type must be the same as the result type in SPIR-V, which + // is the same as in Zig. const operand_ty_ref = try self.resolveType(operand_ty, .direct); const operand_ty_id = self.typeId(operand_ty_ref); - const op_result_id = blk: { - // Construct the SPIR-V result type. - // It is almost the same as the zig one, except that the fields must be the same type - // and they must be unsigned. - const overflow_result_ty_ref = try self.spv.simpleStructType(&.{ - .{ .ty = operand_ty_ref, .name = "res" }, - .{ .ty = operand_ty_ref, .name = "ov" }, - }); - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpIAddCarry, .{ - .id_result_type = self.typeId(overflow_result_ty_ref), - .id_result = result_id, - .operand_1 = lhs, - .operand_2 = rhs, - }); - break :blk result_id; - }; - - // Now convert the SPIR-V flavor result into a Zig-flavor result. - // First, extract the two fields. - const unsigned_result = try self.extractField(operand_ty, op_result_id, 0); - const overflow = try self.extractField(operand_ty, op_result_id, 1); - - // We need to convert the results to the types that Zig expects here. - // The `result` is the same type except unsigned, so we can just bitcast that. - // TODO: This can be removed in Kernels as there are only unsigned ints. Maybe for - // shaders as well? - const result = try self.bitcast(operand_ty_id, unsigned_result); - - // The overflow needs to be converted into whatever is used to represent it in Zig. - const casted_overflow = blk: { - const ov_ty = result_ty.tupleFields().types[1]; - const ov_ty_id = try self.resolveTypeId(ov_ty); - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ - .id_result_type = ov_ty_id, - .id_result = result_id, - .unsigned_value = overflow, - }); - break :blk result_id; - }; + const bool_ty_ref = try self.resolveType(Type.bool, .direct); - // TODO: If copying this function for borrow, make sure to convert -1 to 1 as appropriate. + const ov_ty = result_ty.tupleFields().types[1]; + // Note: result is stored in a struct, so indirect representation. + const ov_ty_ref = try self.resolveType(ov_ty, .indirect); - // Finally, construct the Zig type. - // Layout is result, overflow. - const result_id = self.spv.allocId(); - const constituents = [_]IdRef{ result, casted_overflow }; - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ + // TODO: Operations other than addition. + const value_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpIAdd, .{ .id_result_type = operand_ty_id, - .id_result = result_id, - .constituents = &constituents, + .id_result = value_id, + .operand_1 = lhs, + .operand_2 = rhs, + }); + + const overflowed_id = switch (info.signedness) { + .unsigned => blk: { + // Overflow happened if the result is smaller than either of the operands. It doesn't matter which. + const overflowed_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpULessThan, .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = overflowed_id, + .operand_1 = value_id, + .operand_2 = lhs, + }); + break :blk overflowed_id; + }, + .signed => blk: { + // Overflow happened if: + // - rhs is negative and value > lhs + // - rhs is positive and value < lhs + // This can be shortened to: + // (rhs < 0 && value > lhs) || (rhs >= 0 && value <= lhs) + // = (rhs < 0) == (value > lhs) + // Note that signed overflow is also wrapping in spir-v. + + const rhs_lt_zero_id = self.spv.allocId(); + const zero_id = try self.constInt(operand_ty_ref, 0); + try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = rhs_lt_zero_id, + .operand_1 = rhs, + .operand_2 = zero_id, + }); + + const value_gt_lhs_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpSGreaterThan, .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = value_gt_lhs_id, + .operand_1 = value_id, + .operand_2 = lhs, + }); + + const overflowed_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{ + .id_result_type = self.typeId(bool_ty_ref), + .id_result = overflowed_id, + .operand_1 = rhs_lt_zero_id, + .operand_2 = value_gt_lhs_id, + }); + break :blk overflowed_id; + }, + }; + + // Construct the struct that Zig wants as result. + // The value should already be the correct type. + const ov_id = try self.boolToInt(ov_ty_ref, overflowed_id); + const result_ty_ref = try self.resolveType(result_ty, .direct); + return try self.constructStruct(result_ty_ref, &.{ + value_id, + ov_id, }); - return result_id; } fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { @@ -2040,85 +2144,262 @@ pub const DeclGen = struct { return result_id; } - fn airCmp(self: *DeclGen, inst: Air.Inst.Index, comptime fop: Opcode, comptime sop: Opcode, comptime uop: Opcode) !?IdRef { - if (self.liveness.isUnused(inst)) return null; - 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); + /// AccessChain is essentially PtrAccessChain with 0 as initial argument. The effective + /// difference lies in whether the resulting type of the first dereference will be the + /// same as that of the base pointer, or that of a dereferenced base pointer. AccessChain + /// is the latter and PtrAccessChain is the former. + fn accessChain( + self: *DeclGen, + result_ty_ref: SpvType.Ref, + base: IdRef, + indexes: []const IdRef, + ) !IdRef { const result_id = self.spv.allocId(); - const result_type_id = try self.resolveTypeId(Type.bool); - const op_ty = self.air.typeOf(bin_op.lhs); - assert(op_ty.eql(self.air.typeOf(bin_op.rhs), self.module)); + try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ + .id_result_type = self.typeId(result_ty_ref), + .id_result = result_id, + .base = base, + .indexes = indexes, + }); + return result_id; + } - // Comparisons 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(op_ty); + fn ptrAccessChain( + self: *DeclGen, + result_ty_ref: SpvType.Ref, + base: IdRef, + element: IdRef, + indexes: []const IdRef, + ) !IdRef { + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ + .id_result_type = self.typeId(result_ty_ref), + .id_result = result_id, + .base = base, + .element = element, + .indexes = indexes, + }); + return result_id; + } - const opcode_index: usize = switch (info.class) { - .composite_integer => { - return self.todo("binary operations for composite integers", .{}); + fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef { + const result_ty_ref = try self.resolveType(result_ty, .direct); + + switch (ptr_ty.ptrSize()) { + .One => { + // Pointer to array + // TODO: Is this correct? + return try self.accessChain(result_ty_ref, ptr_id, &.{offset_id}); }, - .float => 0, - .bool => 1, - .strange_integer => blk: { - const op_ty_ref = try self.resolveType(op_ty, .direct); - lhs_id = try self.maskStrangeInt(op_ty_ref, lhs_id, info.bits); - rhs_id = try self.maskStrangeInt(op_ty_ref, rhs_id, info.bits); - break :blk switch (info.signedness) { - .signed => @as(usize, 1), - .unsigned => @as(usize, 2), - }; + .C, .Many => { + return try self.ptrAccessChain(result_ty_ref, ptr_id, offset_id, &.{}); }, - .integer => switch (info.signedness) { - .signed => @as(usize, 1), - .unsigned => @as(usize, 2), + .Slice => { + // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does. + const slice_ptr_id = try self.extractField(result_ty, ptr_id, 0); + return try self.ptrAccessChain(result_ty_ref, slice_ptr_id, offset_id, &.{}); }, - }; + } + } - const operands = .{ - .id_result_type = result_type_id, - .id_result = result_id, - .operand_1 = lhs_id, - .operand_2 = rhs_id, - }; + fn airPtrAdd(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 bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; + const ptr_id = try self.resolve(bin_op.lhs); + const offset_id = try self.resolve(bin_op.rhs); + const ptr_ty = self.air.typeOf(bin_op.lhs); + const result_ty = self.air.typeOfIndex(inst); - switch (opcode_index) { - 0 => try self.func.body.emit(self.spv.gpa, fop, operands), - 1 => try self.func.body.emit(self.spv.gpa, sop, operands), - 2 => try self.func.body.emit(self.spv.gpa, uop, operands), - else => unreachable, - } + return try self.ptrAdd(result_ty, ptr_ty, ptr_id, offset_id); + } + + fn airPtrSub(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 bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; + const ptr_id = try self.resolve(bin_op.lhs); + const ptr_ty = self.air.typeOf(bin_op.lhs); + const offset_id = try self.resolve(bin_op.rhs); + const offset_ty = self.air.typeOf(bin_op.rhs); + const offset_ty_ref = try self.resolveType(offset_ty, .direct); + const result_ty = self.air.typeOfIndex(inst); + + const negative_offset_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpSNegate, .{ + .id_result_type = self.typeId(offset_ty_ref), + .id_result = negative_offset_id, + .operand = offset_id, + }); + return try self.ptrAdd(result_ty, ptr_ty, ptr_id, negative_offset_id); + } + + fn cmp( + self: *DeclGen, + comptime op: std.math.CompareOperator, + bool_ty_id: IdRef, + ty: Type, + lhs_id: IdRef, + rhs_id: IdRef, + ) !IdRef { + var cmp_lhs_id = lhs_id; + var cmp_rhs_id = rhs_id; + const opcode: Opcode = opcode: { + var int_buffer: Type.Payload.Bits = undefined; + const op_ty = switch (ty.zigTypeTag()) { + .Int, .Bool, .Float => ty, + .Enum => ty.intTagType(&int_buffer), + .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 => { + return self.todo("binary operations for composite integers", .{}); + }, + .float => break :opcode switch (op) { + .eq => .OpFOrdEqual, + .neq => .OpFOrdNotEqual, + .lt => .OpFOrdLessThan, + .lte => .OpFOrdLessThanEqual, + .gt => .OpFOrdGreaterThan, + .gte => .OpFOrdGreaterThanEqual, + }, + .bool => break :opcode switch (op) { + .eq => .OpIEqual, + .neq => .OpINotEqual, + else => unreachable, + }, + .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); + break :sign info.signedness; + }, + .integer => info.signedness, + }; + + break :opcode switch (signedness) { + .unsigned => switch (op) { + .eq => .OpIEqual, + .neq => .OpINotEqual, + .lt => .OpULessThan, + .lte => .OpULessThanEqual, + .gt => .OpUGreaterThan, + .gte => .OpUGreaterThanEqual, + }, + .signed => switch (op) { + .eq => .OpIEqual, + .neq => .OpINotEqual, + .lt => .OpSLessThan, + .lte => .OpSLessThanEqual, + .gt => .OpSGreaterThan, + .gte => .OpSGreaterThanEqual, + }, + }; + }; + + 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.IdResult, result_id); + self.func.body.writeOperand(spec.IdResultType, cmp_lhs_id); + self.func.body.writeOperand(spec.IdResultType, cmp_rhs_id); return result_id; } - fn bitcast(self: *DeclGen, target_type_id: IdResultType, value_id: IdRef) !IdRef { + fn airCmp( + self: *DeclGen, + inst: Air.Inst.Index, + comptime 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 bool_ty_id = try self.resolveTypeId(Type.bool); + const ty = self.air.typeOf(bin_op.lhs); + assert(ty.eql(self.air.typeOf(bin_op.rhs), self.module)); + + return try self.cmp(op, bool_ty_id, ty, lhs_id, rhs_id); + } + + fn bitCast( + self: *DeclGen, + dst_ty: Type, + src_ty: Type, + src_id: IdRef, + ) !IdRef { + const dst_ty_ref = try self.resolveType(dst_ty, .direct); const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ - .id_result_type = target_type_id, - .id_result = result_id, - .operand = value_id, - }); + + // TODO: Some more cases are missing here + // See fn bitCast in llvm.zig + + if (src_ty.zigTypeTag() == .Int and dst_ty.isPtrAtRuntime()) { + 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 { + 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; } - fn airBitcast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + fn airBitCast(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 result_type_id = try self.resolveTypeId(self.air.typeOfIndex(inst)); - return try self.bitcast(result_type_id, operand_id); + const operand_ty = self.air.typeOf(ty_op.operand); + const result_ty = self.air.typeOfIndex(inst); + return try self.bitCast(result_ty, operand_ty, operand_id); } - fn airIntcast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + fn airIntCast(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.air.typeOfIndex(inst); - const dest_info = try self.arithmeticTypeInfo(dest_ty); const dest_ty_id = try self.resolveTypeId(dest_ty); + const target = self.getTarget(); + const dest_info = dest_ty.intInfo(target); + + // TODO: Masking? + const result_id = self.spv.allocId(); switch (dest_info.signedness) { .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{ @@ -2221,11 +2502,7 @@ pub const DeclGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const field_ty = self.air.typeOfIndex(inst); const operand_id = try self.resolve(ty_op.operand); - return try self.extractField( - field_ty, - operand_id, - field, - ); + return try self.extractField(field_ty, operand_id, field); } fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { @@ -2233,30 +2510,14 @@ pub const DeclGen = struct { const slice_ty = self.air.typeOf(bin_op.lhs); if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; - const slice = try self.resolve(bin_op.lhs); - const index = try self.resolve(bin_op.rhs); - - const spv_ptr_ty = try self.resolveTypeId(self.air.typeOfIndex(inst)); + const slice_id = try self.resolve(bin_op.lhs); + const index_id = try self.resolve(bin_op.rhs); - const slice_ptr = blk: { - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ - .id_result_type = spv_ptr_ty, - .id_result = result_id, - .composite = slice, - .indexes = &.{0}, - }); - break :blk result_id; - }; + const ptr_ty = self.air.typeOfIndex(inst); + const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ - .id_result_type = spv_ptr_ty, - .id_result = result_id, - .base = slice_ptr, - .element = index, - }); - return result_id; + const slice_ptr = try self.extractField(ptr_ty, slice_id, 0); + return try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{}); } fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { @@ -2264,61 +2525,64 @@ pub const DeclGen = struct { const slice_ty = self.air.typeOf(bin_op.lhs); if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; - const slice = try self.resolve(bin_op.lhs); - const index = try self.resolve(bin_op.rhs); + const slice_id = try self.resolve(bin_op.lhs); + const index_id = try self.resolve(bin_op.rhs); var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_ty_id = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf)); - - const slice_ptr = blk: { - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ - .id_result_type = ptr_ty_id, - .id_result = result_id, - .composite = slice, - .indexes = &.{0}, - }); - break :blk result_id; - }; - - const elem_ptr = blk: { - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ - .id_result_type = ptr_ty_id, - .id_result = result_id, - .base = slice_ptr, - .element = index, - }); - break :blk result_id; - }; + const ptr_ty = slice_ty.slicePtrFieldType(&slice_buf); + const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); + const slice_ptr = try self.extractField(ptr_ty, slice_id, 0); + const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{}); return try self.load(slice_ty, elem_ptr); } + fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { + // Construct new pointer type for the resulting pointer + const elem_ty = ptr_ty.elemType2(); // 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(ptr_ty.ptrAddressSpace()), 0); + if (ptr_ty.isSinglePointer()) { + // Pointer-to-array. In this case, the resulting pointer is not of the same type + // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. + return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id}); + } else { + // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain + return try self.ptrAccessChain(elem_ptr_ty_ref, ptr_id, index_id, &.{}); + } + } + fn airPtrElemPtr(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 bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_ty = self.air.typeOf(bin_op.lhs); - const result_ty = self.air.typeOfIndex(inst); const elem_ty = ptr_ty.childType(); // TODO: Make this return a null ptr or something if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; - const result_type_id = try self.resolveTypeId(result_ty); - const base_ptr = try self.resolve(bin_op.lhs); - const rhs = try self.resolve(bin_op.rhs); + 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); + } - const result_id = self.spv.allocId(); - const indexes = [_]IdRef{rhs}; - try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ - .id_result_type = result_type_id, - .id_result = result_id, - .base = base_ptr, - .indexes = &indexes, - }); - return result_id; + fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const ptr_ty = self.air.typeOf(bin_op.lhs); + const ptr_id = try self.resolve(bin_op.lhs); + const index_id = try self.resolve(bin_op.rhs); + + const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id); + + // If we have a pointer-to-array, construct an element pointer to use with load() + // If we pass ptr_ty directly, it will attempt to load the entire array rather than + // just an element. + var elem_ptr_info = ptr_ty.ptrInfo(); + elem_ptr_info.data.size = .One; + const elem_ptr_ty = Type.initPayload(&elem_ptr_info.base); + + return try self.load(elem_ptr_ty, elem_ptr_id); } fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { @@ -2344,24 +2608,15 @@ pub const DeclGen = struct { const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; const struct_ty = self.air.typeOf(struct_field.struct_operand); - const object = try self.resolve(struct_field.struct_operand); + const object_id = try self.resolve(struct_field.struct_operand); const field_index = struct_field.field_index; const field_ty = struct_ty.structFieldType(field_index); - const field_ty_id = try self.resolveTypeId(field_ty); if (!field_ty.hasRuntimeBitsIgnoreComptime()) return null; assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet. - const result_id = self.spv.allocId(); - const indexes = [_]u32{field_index}; - try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ - .id_result_type = field_ty_id, - .id_result = result_id, - .composite = object, - .indexes = &indexes, - }); - return result_id; + return try self.extractField(field_ty, object_id, field_index); } fn structFieldPtr( @@ -2379,16 +2634,8 @@ pub const DeclGen = struct { const u32_ty_id = self.typeId(try self.intType(.unsigned, 32)); const field_index_id = self.spv.allocId(); try self.spv.emitConstant(u32_ty_id, field_index_id, .{ .uint32 = field_index }); - const result_id = self.spv.allocId(); - const result_type_id = try self.resolveTypeId(result_ptr_ty); - const indexes = [_]IdRef{field_index_id}; - try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ - .id_result_type = result_type_id, - .id_result = result_id, - .base = object_ptr, - .indexes = &indexes, - }); - return result_id; + const result_ty_ref = try self.resolveType(result_ptr_ty, .direct); + return try self.accessChain(result_ty_ref, object_ptr, &.{field_index_id}); }, }, else => unreachable, // TODO @@ -2422,76 +2669,45 @@ pub const DeclGen = struct { return result_id; } - fn variable( + // Allocate a function-local variable, with possible initializer. + // This function returns a pointer to a variable of type `ty_ref`, + // which is in the Generic address space. The variable is actually + // placed in the Function address space. + fn alloc( self: *DeclGen, - comptime context: enum { function, global }, - result_id: IdRef, - ptr_ty_ref: SpvType.Ref, + ty_ref: SpvType.Ref, initializer: ?IdRef, - ) !void { - const storage_class = self.spv.typeRefType(ptr_ty_ref).payload(.pointer).storage_class; - const actual_storage_class = switch (storage_class) { - .Generic => switch (context) { - .function => .Function, - .global => .CrossWorkgroup, - }, - else => storage_class, - }; - const actual_ptr_ty_ref = switch (storage_class) { - .Generic => try self.spv.changePtrStorageClass(ptr_ty_ref, actual_storage_class), - else => ptr_ty_ref, - }; - const alloc_result_id = switch (storage_class) { - .Generic => self.spv.allocId(), - else => result_id, - }; + ) !IdRef { + const fn_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Function, 0); + const general_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Generic, 0); - const section = switch (actual_storage_class) { - .Generic => unreachable, - // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to - // directly generate them into func.prologue instead of the body. - .Function => &self.func.prologue, - else => &self.spv.sections.types_globals_constants, - }; - try section.emit(self.spv.gpa, .OpVariable, .{ - .id_result_type = self.typeId(actual_ptr_ty_ref), - .id_result = alloc_result_id, - .storage_class = actual_storage_class, + // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to + // directly generate them into func.prologue instead of the body. + const var_id = self.spv.allocId(); + try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ + .id_result_type = self.typeId(fn_ptr_ty_ref), + .id_result = var_id, + .storage_class = .Function, .initializer = initializer, }); - if (storage_class != .Generic) { - return; - } - - // Now we need to convert the pointer. - // If this is a function local, we need to perform the conversion at runtime. Otherwise, we can do - // it ahead of time using OpSpecConstantOp. - switch (actual_storage_class) { - .Function => try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ - .id_result_type = self.typeId(ptr_ty_ref), - .id_result = result_id, - .pointer = alloc_result_id, - }), - // TODO: Can we do without this cast or move it to runtime? - else => { - const const_ptr_id = try self.makePointerConstant(section, actual_ptr_ty_ref, alloc_result_id); - try section.emitSpecConstantOp(self.spv.gpa, .OpPtrCastToGeneric, .{ - .id_result_type = self.typeId(ptr_ty_ref), - .id_result = result_id, - .pointer = const_ptr_id, - }); - }, - } + // Convert to a generic pointer + const result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ + .id_result_type = self.typeId(general_ptr_ty_ref), + .id_result = result_id, + .pointer = var_id, + }); + return result_id; } fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { if (self.liveness.isUnused(inst)) return null; - const ty = self.air.typeOfIndex(inst); - const result_ty_ref = try self.resolveType(ty, .direct); - const result_id = self.spv.allocId(); - try self.variable(.function, result_id, result_ty_ref, null); - return result_id; + const ptr_ty = self.air.typeOfIndex(inst); + assert(ptr_ty.ptrAddressSpace() == .generic); + const child_ty = ptr_ty.childType(); + const child_ty_ref = try self.resolveType(child_ty, .indirect); + return try self.alloc(child_ty_ref, null); } fn airArg(self: *DeclGen) IdRef { @@ -2778,13 +2994,7 @@ pub const DeclGen = struct { } const err_union_ty_ref = try self.resolveType(err_union_ty, .direct); - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ - .id_result_type = self.typeId(err_union_ty_ref), - .id_result = result_id, - .constituents = members.slice(), - }); - return result_id; + return try self.constructStruct(err_union_ty_ref, members.slice()); } fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef { @@ -2884,14 +3094,8 @@ pub const DeclGen = struct { } const optional_ty_ref = try self.resolveType(optional_ty, .direct); - const result_id = self.spv.allocId(); const members = [_]IdRef{ operand_id, try self.constBool(true, .indirect) }; - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ - .id_result_type = self.typeId(optional_ty_ref), - .id_result = result_id, - .constituents = &members, - }); - return result_id; + return try self.constructStruct(optional_ty_ref, &members); } fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index 4bd6c834cefc..5e7e6508fad0 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -774,6 +774,16 @@ pub fn changePtrStorageClass(self: *Module, ptr_ty_ref: Type.Ref, new_storage_cl return try self.resolveType(Type.initPayload(&payload.base)); } +pub fn constComposite(self: *Module, ty_ref: Type.Ref, members: []const IdRef) !IdRef { + const result_id = self.allocId(); + try self.sections.types_globals_constants.emit(self.gpa, .OpSpecConstantComposite, .{ + .id_result_type = self.typeId(ty_ref), + .id_result = result_id, + .constituents = members, + }); + return result_id; +} + pub fn emitConstant( self: *Module, ty_id: IdRef, diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 4bd66666968f..dd0ea3171146 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -33,8 +33,6 @@ test "default alignment allows unspecified in type syntax" { } test "implicitly decreasing pointer alignment" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const a: u32 align(4) = 3; const b: u32 align(8) = 4; try expect(addUnaligned(&a, &b) == 7); @@ -45,8 +43,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { } test "@alignCast pointers" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var x: u32 align(4) = 1; expectsOnly1(&x); try expect(x == 2); @@ -219,8 +215,6 @@ test "alignment and size of structs with 128-bit fields" { } test "@ptrCast preserves alignment of bigger source" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var x: u32 align(16) = 1234; const ptr = @ptrCast(*u8, &x); try expect(@TypeOf(ptr) == *align(16) u8); diff --git a/test/behavior/array.zig b/test/behavior/array.zig index b4754a59a478..ed8b0216130f 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -347,7 +347,6 @@ test "read/write through global variable array of struct fields initialized via test "implicit cast single-item 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 testImplicitCastSingleItemPtr(); comptime try testImplicitCastSingleItemPtr(); @@ -542,7 +541,6 @@ test "sentinel element count towards the ABI size calculation" { 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/asm.zig b/test/behavior/asm.zig index 5c446e5f859e..e365936798e0 100644 --- a/test/behavior/asm.zig +++ b/test/behavior/asm.zig @@ -15,6 +15,10 @@ comptime { \\.type this_is_my_alias, @function; \\.set this_is_my_alias, derp; ); + } else if (builtin.zig_backend == .stage2_spirv64) { + asm ( + \\%a = OpString "hello there" + ); } } @@ -24,7 +28,6 @@ test "module level assembly" { 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_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly diff --git a/test/behavior/atomics.zig b/test/behavior/atomics.zig index d1b51207a4cf..99f08a6caeed 100644 --- a/test/behavior/atomics.zig +++ b/test/behavior/atomics.zig @@ -120,7 +120,6 @@ test "128-bit cmpxchg" { 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 test_u128_cmpxchg(); comptime try test_u128_cmpxchg(); @@ -313,7 +312,6 @@ test "atomicrmw with 128-bit ints" { 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_spirv64) return error.SkipZigTest; // TODO "ld.lld: undefined symbol: __sync_lock_test_and_set_16" on -mcpu x86_64 if (builtin.cpu.arch == .x86_64 and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 0de278fc5767..3024ad58c089 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -82,8 +82,6 @@ test "type equality" { } test "pointer dereferencing" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var x = @as(i32, 3); const y = &x; @@ -134,21 +132,18 @@ fn first4KeysOfHomeRow() []const u8 { test "return string from function" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); } test "hex escape" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); } test "multiline string" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const s1 = \\one @@ -161,7 +156,6 @@ test "multiline string" { test "multiline string comments at start" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const s1 = //\\one @@ -174,7 +168,6 @@ test "multiline string comments at start" { test "multiline string comments at end" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const s1 = \\one @@ -187,7 +180,6 @@ test "multiline string comments at end" { test "multiline string comments in middle" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const s1 = \\one @@ -200,7 +192,6 @@ test "multiline string comments in middle" { test "multiline string comments at multiple places" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const s1 = \\one @@ -214,14 +205,11 @@ test "multiline string comments at multiple places" { } test "string concatenation simple" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); } test "array mult operator" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(mem.eql(u8, "ab" ** 5, "ababababab")); } @@ -303,8 +291,6 @@ test "function closes over local const" { } test "volatile load and store" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var number: i32 = 1234; const ptr = @as(*volatile i32, &number); ptr.* += 1; @@ -387,7 +373,6 @@ test "take address of parameter" { 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 testTakeAddressOfParameter(12.34); } @@ -477,7 +462,6 @@ fn nine() u8 { test "struct inside function" { 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 testStructInFn(); comptime try testStructInFn(); @@ -599,7 +583,7 @@ test "comptime cast fn to ptr" { } test "equality compare fn ptrs" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // Test passes but should not var a = &emptyFn; try expect(a == a); @@ -690,8 +674,6 @@ test "explicit cast optional pointers" { } test "pointer comparison" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const a = @as([]const u8, "a"); const b = &a; try expect(ptrEql(b, b)); @@ -704,7 +686,6 @@ test "string concatenation" { 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 a = "OK" ++ " IT " ++ "WORKED"; const b = "OK IT WORKED"; @@ -770,7 +751,6 @@ fn maybe(x: bool) anyerror!?u32 { test "auto created variables have correct alignment" { 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(str: [*]const u8) u32 { @@ -892,8 +872,6 @@ test "catch in block has correct result location" { } test "labeled block with runtime branch forwards its result location type to break statements" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const E = enum { a, b }; var a = false; const e: E = blk: { @@ -1062,8 +1040,6 @@ test "switch inside @as gets correct type" { } test "inline call of function with a switch inside the return statement" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { inline fn foo(x: anytype) @TypeOf(x) { return switch (x) { @@ -1147,7 +1123,6 @@ test "returning an opaque type from a function" { test "orelse coercion as function argument" { 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 Loc = struct { start: i32 = -1 }; const Container = struct { diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 4b8c363ac2d7..28eb00c6c120 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -9,7 +9,6 @@ const native_endian = builtin.target.cpu.arch.endian(); test "@bitCast iX -> uX (32, 64)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const bit_values = [_]usize{ 32, 64 }; diff --git a/test/behavior/bitreverse.zig b/test/behavior/bitreverse.zig index 87cea942d05f..8d98f65b55d1 100644 --- a/test/behavior/bitreverse.zig +++ b/test/behavior/bitreverse.zig @@ -5,7 +5,6 @@ const minInt = std.math.minInt; test "@bitReverse large exotic integer" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try expect(@bitReverse(@as(u95, 0x123456789abcdef111213141)) == 0x4146424447bd9eac8f351624); } diff --git a/test/behavior/call.zig b/test/behavior/call.zig index e7d59d7e756d..c1bd1ae76dc8 100644 --- a/test/behavior/call.zig +++ b/test/behavior/call.zig @@ -109,7 +109,6 @@ test "result location of function call argument through runtime condition and st test "function call with 40 arguments" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest(thirty_nine: i32) !void { @@ -374,8 +373,6 @@ test "Enum constructed by @Type passed as generic argument" { } test "generic function with generic function parameter" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn f(comptime a: fn (anytype) anyerror!void, b: anytype) anyerror!void { try a(b); @@ -388,8 +385,6 @@ test "generic function with generic function parameter" { } test "recursive inline call with comptime known argument" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { inline fn foo(x: i32) i32 { if (x <= 0) { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 847abc17981f..594bf683e5bd 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -322,7 +322,6 @@ test "peer result null and comptime_int" { test "*const ?[*]const T to [*c]const [*c]const 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 array = [_]u8{ 'o', 'k' }; const opt_array_ptr: ?[*]const u8 = &array; @@ -366,7 +365,6 @@ test "return u8 coercing into ?u32 return type" { 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 S = struct { fn doTheTest() !void { @@ -428,7 +426,6 @@ test "peer resolve array and const 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; try testPeerResolveArrayConstSlice(true); comptime try testPeerResolveArrayConstSlice(true); diff --git a/test/behavior/decltest.zig b/test/behavior/decltest.zig index 7aa8fb631880..b01a431e2859 100644 --- a/test/behavior/decltest.zig +++ b/test/behavior/decltest.zig @@ -5,7 +5,5 @@ pub fn the_add_function(a: u32, b: u32) u32 { } test the_add_function { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (the_add_function(1, 2) != 3) unreachable; } diff --git a/test/behavior/defer.zig b/test/behavior/defer.zig index 5aa8c2f02bb8..c97350cd7599 100644 --- a/test/behavior/defer.zig +++ b/test/behavior/defer.zig @@ -23,8 +23,6 @@ fn testBreakContInDefer(x: usize) void { } test "defer and labeled break" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var i = @as(usize, 0); blk: { @@ -58,7 +56,6 @@ test "return variable while defer expression in scope to modify it" { 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() !void { diff --git a/test/behavior/duplicated_test_names.zig b/test/behavior/duplicated_test_names.zig index 81b9ebdf50ce..52930ea31819 100644 --- a/test/behavior/duplicated_test_names.zig +++ b/test/behavior/duplicated_test_names.zig @@ -15,7 +15,5 @@ comptime { test "thingy" {} test thingy { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (thingy(1, 2) != 3) unreachable; } diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 61ad010ed75a..f652d7fe5b46 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1045,7 +1045,6 @@ test "tag name with assigned enum values" { test "@tagName on enum literals" { 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(mem.eql(u8, @tagName(.FooBar), "FooBar")); comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); diff --git a/test/behavior/error.zig b/test/behavior/error.zig index 54d53eec4a06..618af87e1033 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -16,14 +16,12 @@ fn expectError(expected_err: anyerror, observed_err_union: anytype) !void { } test "error values" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const a = @errorToInt(error.err1); const b = @errorToInt(error.err2); try expect(a != b); } test "redefinition of error values allowed" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; shouldBeNotEqual(error.AnError, error.SecondError); } fn shouldBeNotEqual(a: anyerror, b: anyerror) void { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index d22eba4fa0eb..68d43ef0b660 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -23,7 +23,6 @@ test "static add one" { 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(should_be_1235 == 1235); } @@ -48,8 +47,6 @@ test "inline variable gets result of const if" { } test "static function evaluation" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(statically_added_number == 3); } const statically_added_number = staticAdd(1, 2); diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 21fc87ff2266..9391aa939878 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -506,7 +506,6 @@ test "@fabs" { 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; comptime try testFabs(); try testFabs(); @@ -621,7 +620,6 @@ test "@floor" { 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; comptime try testFloor(); try testFloor(); diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index c84eb48d2e66..4f05054522f1 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -5,8 +5,6 @@ const expect = testing.expect; const expectEqual = testing.expectEqual; test "params" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(testParamsAdd(22, 11) == 33); } fn testParamsAdd(a: i32, b: i32) i32 { @@ -14,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { } test "local variables" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - testLocVars(2); } fn testLocVars(b: i32) void { diff --git a/test/behavior/fn_delegation.zig b/test/behavior/fn_delegation.zig index d7a2ba2125b3..95dbfeb4b2b7 100644 --- a/test/behavior/fn_delegation.zig +++ b/test/behavior/fn_delegation.zig @@ -34,7 +34,6 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 { test "fn delegation" { 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 = Foo{}; try expect(foo.one() == 11); diff --git a/test/behavior/fn_in_struct_in_comptime.zig b/test/behavior/fn_in_struct_in_comptime.zig index 427b08e6a46c..a7d8e779cc21 100644 --- a/test/behavior/fn_in_struct_in_comptime.zig +++ b/test/behavior/fn_in_struct_in_comptime.zig @@ -13,8 +13,6 @@ fn get_foo() fn (*u8) usize { } test "define a function in an anonymous struct in comptime" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const foo = get_foo(); try expect(foo(@intToPtr(*u8, 12345)) == 12345); } diff --git a/test/behavior/for.zig b/test/behavior/for.zig index 8c9eeb083e16..c41fccfc80a1 100644 --- a/test/behavior/for.zig +++ b/test/behavior/for.zig @@ -22,8 +22,6 @@ test "continue in for loop" { } test "break from outer for loop" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try testBreakOuter(); comptime try testBreakOuter(); } @@ -41,8 +39,6 @@ fn testBreakOuter() !void { } test "continue outer for loop" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try testContinueOuter(); comptime try testContinueOuter(); } diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index e8d064154b56..97257d75a339 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -5,8 +5,6 @@ const expect = testing.expect; const expectEqual = testing.expectEqual; test "one param, explicit comptime" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var x: usize = 0; x += checkSize(i32); x += checkSize(bool); @@ -21,7 +19,6 @@ fn checkSize(comptime T: type) usize { test "simple generic 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; try expect(max(i32, 3, -1) == 3); try expect(max(u8, 1, 100) == 100); diff --git a/test/behavior/if.zig b/test/behavior/if.zig index 7369435cd324..c17f2c989163 100644 --- a/test/behavior/if.zig +++ b/test/behavior/if.zig @@ -71,8 +71,6 @@ test "labeled break inside comptime if inside runtime if" { } test "const result loc, runtime if cond, else unreachable" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const Num = enum { One, Two }; var t = true; diff --git a/test/behavior/inttoptr.zig b/test/behavior/inttoptr.zig index a05ed83b9b52..29a263b2ce87 100644 --- a/test/behavior/inttoptr.zig +++ b/test/behavior/inttoptr.zig @@ -14,7 +14,6 @@ test "mutate through ptr initialized with constant intToPtr 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; forceCompilerAnalyzeBranchHardCodedPtrDereference(false); } diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 2d43ac306d65..14f90ee3fa6e 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -208,7 +208,6 @@ test "float equality" { 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: f64 = 0.012; const y: f64 = x + 1.0; @@ -684,7 +683,6 @@ test "@addWithOverflow" { 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: u8 = 250; diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index db6cad221fd2..648d4d94936c 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -129,8 +129,6 @@ test "@min/max for floats" { } test "@min/@max on lazy values" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const A = extern struct { u8_4: [4]u8 }; const B = extern struct { u8_16: [16]u8 }; const size = @max(@sizeOf(A), @sizeOf(B)); diff --git a/test/behavior/memcpy.zig b/test/behavior/memcpy.zig index af86c0911306..b7c5eb29d975 100644 --- a/test/behavior/memcpy.zig +++ b/test/behavior/memcpy.zig @@ -67,14 +67,16 @@ fn testMemcpyDestManyPtr() !void { } comptime { - const S = struct { - buffer: [8]u8 = undefined, - fn set(self: *@This(), items: []const u8) void { - @memcpy(self.buffer[0..items.len], items); - } - }; + if (builtin.zig_backend != .stage2_spirv64) { + const S = struct { + buffer: [8]u8 = undefined, + fn set(self: *@This(), items: []const u8) void { + @memcpy(self.buffer[0..items.len], items); + } + }; - var s = S{}; - s.set("hello"); - if (!std.mem.eql(u8, s.buffer[0..5], "hello")) @compileError("bad"); + var s = S{}; + s.set("hello"); + if (!std.mem.eql(u8, s.buffer[0..5], "hello")) @compileError("bad"); + } } diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index e62065cf2551..4a043c6a6ec8 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -8,7 +8,6 @@ const expectEqualStrings = std.testing.expectEqualStrings; test "passing an optional integer as a parameter" { 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() bool { @@ -422,7 +421,6 @@ test "optional of noreturn used with orelse" { } test "orelse on C pointer" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO https://github.com/ziglang/zig/issues/6597 const foo: [*c]const u8 = "hey"; diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 36e37786f116..0bd6390796d9 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -7,7 +7,6 @@ const native_endian = builtin.cpu.arch.endian(); test "flags in packed structs" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Flags1 = packed struct { // first 8 bits @@ -94,7 +93,6 @@ test "flags in packed structs" { test "consistent size of packed structs" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const TxData1 = packed struct { data: u8, _23: u23, full: bool = false }; const TxData2 = packed struct { data: u9, _22: u22, full: bool = false }; diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index 26d841a1fd5f..70bc6ad47e08 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -5,7 +5,6 @@ const expect = testing.expect; const expectError = testing.expectError; test "dereference pointer" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; comptime try testDerefPtr(); try testDerefPtr(); } @@ -20,7 +19,6 @@ fn testDerefPtr() !void { test "pointer arithmetic" { 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: [*]const u8 = "abcd"; @@ -53,7 +51,6 @@ fn PtrOf(comptime T: type) type { test "implicit cast single item pointer to C pointer and back" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var y: u8 = 11; var x: [*c]u8 = &y; @@ -70,7 +67,6 @@ test "initialize const optional C pointer to null" { test "assigning integer to C pointer" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: i32 = 0; var y: i32 = 1; @@ -87,7 +83,6 @@ test "assigning integer to C pointer" { test "C pointer comparison and arithmetic" { 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 { @@ -304,7 +299,6 @@ test "null terminated pointer" { test "allow any sentinel" { 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 { diff --git a/test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig b/test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig index 41d7f566622a..bb6d5b1359a4 100644 --- a/test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig +++ b/test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig @@ -8,7 +8,6 @@ test "reference a variable in an if after an if in the 2nd switch prong" { 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 foo(true, Num.Two, false, "aoeu"); try expect(!ok); diff --git a/test/behavior/reflection.zig b/test/behavior/reflection.zig index b62838f24387..aea84bc45ad4 100644 --- a/test/behavior/reflection.zig +++ b/test/behavior/reflection.zig @@ -28,7 +28,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 { test "reflection: @field" { 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 f = Foo{ .one = 42, diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index e01e20e5441b..e463e51753cd 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -140,8 +140,6 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" { } test "@TypeOf() has no runtime side effects" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const S = struct { fn foo(comptime T: type, ptr: *T) T { ptr.* += 1; @@ -156,7 +154,6 @@ test "@TypeOf() has no runtime side effects" { test "branching logic inside @TypeOf" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { var data: i32 = 0; diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index bff90518ed80..5a5aa5ec72a9 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -200,8 +200,6 @@ test "slicing pointer by length" { const x = @intToPtr([*]i32, 0x1000)[0..0x500]; const y = x[0x100..]; test "compile time slice of pointer to hard coded address" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(@ptrToInt(x) == 0x1000); try expect(x.len == 0x500); @@ -673,7 +671,6 @@ test "array mult of slice gives ptr to array" { test "slice bounds in comptime concatenation" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const bs = comptime blk: { const b = "........1........"; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 659acbf56be5..4553596c4177 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -11,7 +11,6 @@ top_level_field: i32, test "top level 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; var instance = @This(){ .top_level_field = 1234, @@ -122,8 +121,6 @@ test "struct byval assign" { } test "call struct static method" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const result = StructWithNoFields.add(3, 4); try expect(result == 7); } diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index f66446632bc9..3f6cd3729873 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -215,7 +215,6 @@ fn poll() void { test "switch on global mutable var isn't constant-folded" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; while (state < 2) { poll(); @@ -349,8 +348,6 @@ fn returnsFalse() bool { } } test "switch on const enum with var" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(!returnsFalse()); } diff --git a/test/behavior/this.zig b/test/behavior/this.zig index 8fd8af92a358..0bc765c8a715 100644 --- a/test/behavior/this.zig +++ b/test/behavior/this.zig @@ -21,8 +21,6 @@ fn add(x: i32, y: i32) i32 { } test "this refer to module call private fn" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try expect(module.add(1, 2) == 3); } diff --git a/test/behavior/threadlocal.zig b/test/behavior/threadlocal.zig index a1214fff218d..763c87605c6a 100644 --- a/test/behavior/threadlocal.zig +++ b/test/behavior/threadlocal.zig @@ -11,7 +11,6 @@ test "thread local variable" { 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 = struct { threadlocal var t: i32 = 1234; @@ -47,7 +46,6 @@ test "reference a global threadlocal variable" { else => return error.SkipZigTest, }; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; _ = nrfx_uart_rx(&g_uart0); } diff --git a/test/behavior/type.zig b/test/behavior/type.zig index 936d9663ad3e..2fff4b05afcf 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -491,7 +491,6 @@ test "Type.Fn" { 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 some_opaque = opaque {}; const some_ptr = *some_opaque; diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig index d55688c5eec1..2fdb112a729a 100644 --- a/test/behavior/type_info.zig +++ b/test/behavior/type_info.zig @@ -285,7 +285,6 @@ fn testUnion() !void { test "type info: struct info" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testStruct(); comptime try testStruct(); @@ -513,7 +512,6 @@ test "type info for async frames" { test "Declarations are returned in declaration order" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const a = 1; diff --git a/test/behavior/undefined.zig b/test/behavior/undefined.zig index e0f3e00fffce..6c99b4bbcefa 100644 --- a/test/behavior/undefined.zig +++ b/test/behavior/undefined.zig @@ -81,7 +81,6 @@ test "assign undefined to struct with method" { test "type name of undefined" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const x = undefined; try expect(mem.eql(u8, @typeName(@TypeOf(x)), "@TypeOf(undefined)")); diff --git a/test/behavior/var_args.zig b/test/behavior/var_args.zig index adb5491f7fc4..a2a0e7b4c62b 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); @@ -32,7 +30,6 @@ test "send void arg to var args" { 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); diff --git a/test/behavior/while.zig b/test/behavior/while.zig index a6634b672f45..a051a8fd3bad 100644 --- a/test/behavior/while.zig +++ b/test/behavior/while.zig @@ -5,7 +5,6 @@ const assert = std.debug.assert; test "while loop" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var i: i32 = 0; while (i < 4) { @@ -39,8 +38,6 @@ fn staticWhileLoop2() i32 { } test "while with continue expression" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - var sum: i32 = 0; { var i: i32 = 0;