authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-23 12:37:48-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-09-23 12:37:48-07:00
logb00287175c044682ea025805de05a6ac26a42771
tree1c6ef32977a615238c231c79c020c16a8b98da5d
parent865b2e259bf78dbf1d4c1051b5fff68b90bca65f
parentcff8ab88f5ffe24771aa9c6e839eef03bc22f3d2
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17174 from Snektron/spirv-stuffies

spirv gaming

71 files changed, 1301 insertions(+), 1158 deletions(-)

src/codegen/spirv.zig+1137-811
......@@ -12,6 +12,7 @@ const LazySrcLoc = Module.LazySrcLoc;
1212const Air = @import("../Air.zig");
1313const Zir = @import("../Zir.zig");
1414const Liveness = @import("../Liveness.zig");
15const InternPool = @import("../InternPool.zig");
1516
1617const spec = @import("spirv/spec.zig");
1718const Opcode = spec.Opcode;
......@@ -30,15 +31,26 @@ const SpvAssembler = @import("spirv/Assembler.zig");
3031
3132const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);
3233
34/// We want to store some extra facts about types as mapped from Zig to SPIR-V.
35/// This structure is used to keep that extra information, as well as
36/// the cached reference to the type.
37const SpvTypeInfo = struct {
38 ty_ref: CacheRef,
39};
40
41const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, SpvTypeInfo);
42
3343const IncomingBlock = struct {
3444 src_label_id: IdRef,
3545 break_value_id: IdRef,
3646};
3747
38const BlockMap = std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
39 label_id: IdRef,
40 incoming_blocks: *std.ArrayListUnmanaged(IncomingBlock),
41});
48const Block = struct {
49 label_id: ?IdRef,
50 incoming_blocks: std.ArrayListUnmanaged(IncomingBlock),
51};
52
53const BlockMap = std.AutoHashMapUnmanaged(Air.Inst.Index, *Block);
4254
4355/// Maps Zig decl indices to linking SPIR-V linking information.
4456pub const DeclLinkMap = std.AutoHashMap(Module.Decl.Index, SpvModule.Decl.Index);
......@@ -78,6 +90,15 @@ pub const DeclGen = struct {
7890 /// A map keeping track of which instruction generated which result-id.
7991 inst_results: InstMap = .{},
8092
93 /// A map that maps AIR intern pool indices to SPIR-V cache references (which
94 /// is basically the same thing except for SPIR-V).
95 /// This map is typically only used for structures that are deemed heavy enough
96 /// that it is worth to store them here. The SPIR-V module also interns types,
97 /// and so the main purpose of this map is to avoid recomputation and to
98 /// cache extra information about the type rather than to aid in validity
99 /// of the SPIR-V module.
100 type_map: TypeMap = .{},
101
81102 /// We need to keep track of result ids for block labels, as well as the 'incoming'
82103 /// blocks for a block.
83104 blocks: BlockMap = .{},
......@@ -88,6 +109,10 @@ pub const DeclGen = struct {
88109 /// The code (prologue and body) for the function we are currently generating code for.
89110 func: SpvModule.Fn = .{},
90111
112 /// Stack of the base offsets of the current decl, which is what `dbg_stmt` is relative to.
113 /// This is a stack to keep track of inline functions.
114 base_line_stack: std.ArrayListUnmanaged(u32) = .{},
115
91116 /// If `gen` returned `Error.CodegenFail`, this contains an explanatory message.
92117 /// Memory is owned by `module.gpa`.
93118 error_msg: ?*Module.ErrorMsg,
......@@ -186,6 +211,7 @@ pub const DeclGen = struct {
186211 self.blocks.clearRetainingCapacity();
187212 self.current_block_label_id = undefined;
188213 self.func.reset();
214 self.base_line_stack.items.len = 0;
189215 self.error_msg = null;
190216
191217 self.genDecl() catch |err| switch (err) {
......@@ -207,8 +233,10 @@ pub const DeclGen = struct {
207233 pub fn deinit(self: *DeclGen) void {
208234 self.args.deinit(self.gpa);
209235 self.inst_results.deinit(self.gpa);
236 self.type_map.deinit(self.gpa);
210237 self.blocks.deinit(self.gpa);
211238 self.func.deinit(self.gpa);
239 self.base_line_stack.deinit(self.gpa);
212240 }
213241
214242 /// Return the target which we are currently compiling for.
......@@ -388,7 +416,7 @@ pub const DeclGen = struct {
388416 switch (repr) {
389417 .indirect => {
390418 const int_ty_ref = try self.intType(.unsigned, 1);
391 return self.spv.constInt(int_ty_ref, @intFromBool(value));
419 return self.constInt(int_ty_ref, @intFromBool(value));
392420 },
393421 .direct => {
394422 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
......@@ -397,25 +425,49 @@ pub const DeclGen = struct {
397425 }
398426 }
399427
428 /// Emits an integer constant.
429 /// This function, unlike SpvModule.constInt, takes care to bitcast
430 /// the value to an unsigned int first for Kernels.
431 fn constInt(self: *DeclGen, ty_ref: CacheRef, value: anytype) !IdRef {
432 if (value < 0) {
433 const ty = self.spv.cache.lookup(ty_ref).int_type;
434 // Manually truncate the value so that the resulting value
435 // fits within the unsigned type.
436 const bits: u64 = @bitCast(@as(i64, @intCast(value)));
437 const truncated_bits = if (ty.bits == 64)
438 bits
439 else
440 bits & (@as(u64, 1) << @intCast(ty.bits)) - 1;
441 return try self.spv.constInt(ty_ref, truncated_bits);
442 } else {
443 return try self.spv.constInt(ty_ref, value);
444 }
445 }
446
400447 /// Construct a struct at runtime.
401448 /// result_ty_ref must be a struct type.
449 /// Constituents should be in `indirect` representation (as the elements of a struct should be).
450 /// Result is in `direct` representation.
402451 fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef {
403452 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
404453 // operands are not constant.
405454 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
406455 // For now, just initialize the struct by setting the fields manually...
407456 // TODO: Make this OpCompositeConstruct when we can
408 const ptr_composite_id = try self.alloc(result_ty_ref, null);
409 // Note: using 32-bit ints here because usize crashes the translator as well
410 const index_ty_ref = try self.intType(.unsigned, 32);
457 const ptr_ty_ref = try self.spv.ptrType(result_ty_ref, .Function);
458 const ptr_composite_id = self.spv.allocId();
459 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
460 .id_result_type = self.typeId(ptr_ty_ref),
461 .id_result = ptr_composite_id,
462 .storage_class = .Function,
463 });
411464
412465 const spv_composite_ty = self.spv.cache.lookup(result_ty_ref).struct_type;
413466 const member_types = spv_composite_ty.member_types;
414467
415468 for (constituents, member_types, 0..) |constitent_id, member_ty_ref, index| {
416 const index_id = try self.spv.constInt(index_ty_ref, index);
417 const ptr_member_ty_ref = try self.spv.ptrType(member_ty_ref, .Generic);
418 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{index_id});
469 const ptr_member_ty_ref = try self.spv.ptrType(member_ty_ref, .Function);
470 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
419471 try self.func.body.emit(self.spv.gpa, .OpStore, .{
420472 .pointer = ptr_id,
421473 .object = constitent_id,
......@@ -430,598 +482,122 @@ pub const DeclGen = struct {
430482 return result_id;
431483 }
432484
433 const IndirectConstantLowering = struct {
434 const undef = 0xAA;
435
436 dg: *DeclGen,
437 /// Cached reference of the u32 type.
438 u32_ty_ref: CacheRef,
439 /// The members of the resulting structure type
440 members: std.ArrayList(CacheRef),
441 /// The initializers of each of the members.
442 initializers: std.ArrayList(IdRef),
443 /// The current size of the structure. Includes
444 /// the bytes in partial_word.
445 size: u32 = 0,
446 /// The partially filled last constant.
447 /// If full, its flushed.
448 partial_word: std.BoundedArray(u8, @sizeOf(Word)) = .{},
449 /// The declaration dependencies of the constant we are lowering.
450 decl_deps: std.AutoArrayHashMap(SpvModule.Decl.Index, void),
451
452 /// Utility function to get the section that instructions should be lowered to.
453 fn section(self: *@This()) *SpvSection {
454 return &self.dg.spv.globals.section;
455 }
456
457 /// Flush the partial_word to the members. If the partial_word is not
458 /// filled, this adds padding bytes (which are undefined).
459 fn flush(self: *@This()) !void {
460 if (self.partial_word.len == 0) {
461 // No need to add it there.
462 return;
463 }
464
465 for (self.partial_word.unusedCapacitySlice()) |*unused| {
466 // TODO: Perhaps we should generate OpUndef for these bytes?
467 unused.* = undef;
468 }
469
470 const word = @as(Word, @bitCast(self.partial_word.buffer));
471 const result_id = try self.dg.spv.constInt(self.u32_ty_ref, word);
472 try self.members.append(self.u32_ty_ref);
473 try self.initializers.append(result_id);
474
475 self.partial_word.len = 0;
476 self.size = std.mem.alignForward(u32, self.size, @sizeOf(Word));
477 }
478
479 /// Fill the buffer with undefined values until the size is aligned to `align`.
480 fn fillToAlign(self: *@This(), alignment: u32) !void {
481 const target_size = std.mem.alignForward(u32, self.size, alignment);
482 try self.addUndef(target_size - self.size);
483 }
484
485 fn addUndef(self: *@This(), amt: u64) !void {
486 for (0..@as(usize, @intCast(amt))) |_| {
487 try self.addByte(undef);
488 }
489 }
490
491 /// Add a single byte of data to the constant.
492 fn addByte(self: *@This(), data: u8) !void {
493 self.partial_word.append(data) catch {
494 try self.flush();
495 self.partial_word.append(data) catch unreachable;
496 };
497 self.size += 1;
498 }
499
500 /// Add many bytes of data to the constnat.
501 fn addBytes(self: *@This(), data: []const u8) !void {
502 // TODO: Improve performance by adding in bulk, or something?
503 for (data) |byte| {
504 try self.addByte(byte);
505 }
506 }
507
508 fn addPtr(self: *@This(), ptr_ty_ref: CacheRef, ptr_id: IdRef) !void {
509 // TODO: Double check pointer sizes here.
510 // shared pointers might be u32...
511 const target = self.dg.getTarget();
512 const width = @divExact(target.ptrBitWidth(), 8);
513 if (self.size % width != 0) {
514 return self.dg.todo("misaligned pointer constants", .{});
515 }
516 try self.members.append(ptr_ty_ref);
517 try self.initializers.append(ptr_id);
518 self.size += width;
519 }
520
521 fn addNullPtr(self: *@This(), ptr_ty_ref: CacheRef) !void {
522 const result_id = try self.dg.spv.constNull(ptr_ty_ref);
523 try self.addPtr(ptr_ty_ref, result_id);
524 }
525
526 fn addConstInt(self: *@This(), comptime T: type, value: T) !void {
527 if (@bitSizeOf(T) % 8 != 0) {
528 @compileError("todo: non byte aligned int constants");
529 }
530
531 // TODO: Swap endianness if the compiler is big endian.
532 try self.addBytes(std.mem.asBytes(&value));
533 }
534
535 fn addConstBool(self: *@This(), value: bool) !void {
536 try self.addByte(@intFromBool(value)); // TODO: Keep in sync with something?
537 }
538
539 fn addInt(self: *@This(), ty: Type, val: Value) !void {
540 const mod = self.dg.module;
541 const len = ty.abiSize(mod);
542 if (val.isUndef(mod)) {
543 try self.addUndef(len);
544 return;
545 }
546
547 const int_info = ty.intInfo(mod);
548 const int_bits = switch (int_info.signedness) {
549 .signed => @as(u64, @bitCast(val.toSignedInt(mod))),
550 .unsigned => val.toUnsignedInt(mod),
551 };
552
553 // TODO: Swap endianess if the compiler is big endian.
554 try self.addBytes(std.mem.asBytes(&int_bits)[0..@as(usize, @intCast(len))]);
555 }
485 /// Construct a struct at runtime.
486 /// result_ty_ref must be an array type.
487 /// Constituents should be in `indirect` representation (as the elements of an array should be).
488 /// Result is in `direct` representation.
489 fn constructArray(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef {
490 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
491 // operands are not constant.
492 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
493 // For now, just initialize the struct by setting the fields manually...
494 // TODO: Make this OpCompositeConstruct when we can
495 // TODO: Make this Function storage type
496 const ptr_ty_ref = try self.spv.ptrType(result_ty_ref, .Function);
497 const ptr_composite_id = self.spv.allocId();
498 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
499 .id_result_type = self.typeId(ptr_ty_ref),
500 .id_result = ptr_composite_id,
501 .storage_class = .Function,
502 });
556503
557 fn addFloat(self: *@This(), ty: Type, val: Value) !void {
558 const mod = self.dg.module;
559 const target = self.dg.getTarget();
560 const len = ty.abiSize(mod);
504 const spv_composite_ty = self.spv.cache.lookup(result_ty_ref).array_type;
505 const elem_ty_ref = spv_composite_ty.element_type;
506 const ptr_elem_ty_ref = try self.spv.ptrType(elem_ty_ref, .Function);
561507
562 // TODO: Swap endianess if the compiler is big endian.
563 switch (ty.floatBits(target)) {
564 16 => {
565 const float_bits = val.toFloat(f16, mod);
566 try self.addBytes(std.mem.asBytes(&float_bits)[0..@as(usize, @intCast(len))]);
567 },
568 32 => {
569 const float_bits = val.toFloat(f32, mod);
570 try self.addBytes(std.mem.asBytes(&float_bits)[0..@as(usize, @intCast(len))]);
571 },
572 64 => {
573 const float_bits = val.toFloat(f64, mod);
574 try self.addBytes(std.mem.asBytes(&float_bits)[0..@as(usize, @intCast(len))]);
575 },
576 else => unreachable,
577 }
508 for (constituents, 0..) |constitent_id, index| {
509 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
510 try self.func.body.emit(self.spv.gpa, .OpStore, .{
511 .pointer = ptr_id,
512 .object = constitent_id,
513 });
578514 }
515 const result_id = self.spv.allocId();
516 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
517 .id_result_type = self.typeId(result_ty_ref),
518 .id_result = result_id,
519 .pointer = ptr_composite_id,
520 });
521 return result_id;
522 }
579523
580 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
581 const dg = self.dg;
582 const mod = dg.module;
583
584 const ty_ref = try self.dg.resolveType(ty, .indirect);
585 const ty_id = dg.typeId(ty_ref);
586
587 const decl = dg.module.declPtr(decl_index);
588 const spv_decl_index = try dg.resolveDecl(decl_index);
589
590 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
591 .func => {
592 // TODO: Properly lower function pointers. For now we are going to hack around it and
593 // just generate an empty pointer. Function pointers are represented by usize for now,
594 // though.
595 try self.addInt(Type.usize, Value.zero_usize);
596 // TODO: Add dependency
597 return;
598 },
599 .extern_func => unreachable, // TODO
600 else => {
601 const result_id = dg.spv.allocId();
524 fn constructDeclRef(self: *DeclGen, ty: Type, decl_index: Decl.Index) !IdRef {
525 const mod = self.module;
526 const ty_ref = try self.resolveType(ty, .direct);
527 const ty_id = self.typeId(ty_ref);
528 const decl = mod.declPtr(decl_index);
529 const spv_decl_index = try self.resolveDecl(decl_index);
530 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
531 .func => {
532 // TODO: Properly lower function pointers. For now we are going to hack around it and
533 // just generate an empty pointer. Function pointers are represented by a pointer to usize.
534 // TODO: Add dependency
535 return try self.spv.constNull(ty_ref);
536 },
537 .extern_func => unreachable, // TODO
538 else => {
539 const decl_id = self.spv.declPtr(spv_decl_index).result_id;
540 try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {});
602541
603 try self.decl_deps.put(spv_decl_index, {});
542 const final_storage_class = spvStorageClass(decl.@"addrspace");
543
544 const decl_ty_ref = try self.resolveType(decl.ty, .indirect);
545 const decl_ptr_ty_ref = try self.spv.ptrType(decl_ty_ref, final_storage_class);
546
547 const ptr_id = switch (final_storage_class) {
548 .Generic => blk: {
549 // Pointer should be Generic, but is actually placed in CrossWorkgroup.
550 const result_id = self.spv.allocId();
551 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{
552 .id_result_type = self.typeId(decl_ptr_ty_ref),
553 .id_result = result_id,
554 .pointer = decl_id,
555 });
556 break :blk result_id;
557 },
558 else => decl_id,
559 };
604560
605 const decl_id = dg.spv.declPtr(spv_decl_index).result_id;
606 // TODO: Do we need a storage class cast here?
607 // TODO: We can probably eliminate these casts
608 try dg.spv.globals.section.emitSpecConstantOp(dg.spv.gpa, .OpBitcast, .{
561 if (decl_ptr_ty_ref != ty_ref) {
562 // Differing pointer types, insert a cast.
563 const casted_ptr_id = self.spv.allocId();
564 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
609565 .id_result_type = ty_id,
610 .id_result = result_id,
611 .operand = decl_id,
566 .id_result = casted_ptr_id,
567 .operand = ptr_id,
612568 });
613
614 try self.addPtr(ty_ref, result_id);
615 },
616 }
617 }
618
619 fn lower(self: *@This(), ty: Type, arg_val: Value) !void {
620 const dg = self.dg;
621 const mod = dg.module;
622 const ip = &mod.intern_pool;
623
624 var val = arg_val;
625 switch (ip.indexToKey(val.toIntern())) {
626 .runtime_value => |rt| val = rt.val.toValue(),
627 else => {},
628 }
629
630 if (val.isUndefDeep(mod)) {
631 const size = ty.abiSize(mod);
632 return try self.addUndef(size);
633 }
634
635 switch (ip.indexToKey(val.toIntern())) {
636 .int_type,
637 .ptr_type,
638 .array_type,
639 .vector_type,
640 .opt_type,
641 .anyframe_type,
642 .error_union_type,
643 .simple_type,
644 .struct_type,
645 .anon_struct_type,
646 .union_type,
647 .opaque_type,
648 .enum_type,
649 .func_type,
650 .error_set_type,
651 .inferred_error_set_type,
652 => unreachable, // types, not values
653
654 .undef, .runtime_value => unreachable, // handled above
655 .simple_value => |simple_value| switch (simple_value) {
656 .undefined,
657 .void,
658 .null,
659 .empty_struct,
660 .@"unreachable",
661 .generic_poison,
662 => unreachable, // non-runtime values
663 .false, .true => try self.addConstBool(val.toBool()),
664 },
665 .variable,
666 .extern_func,
667 .func,
668 .enum_literal,
669 .empty_enum_value,
670 => unreachable, // non-runtime values
671 .int => try self.addInt(ty, val),
672 .err => |err| {
673 const int = try mod.getErrorValue(err.name);
674 try self.addConstInt(u16, @as(u16, @intCast(int)));
675 },
676 .error_union => |error_union| {
677 const err_ty = switch (error_union.val) {
678 .err_name => ty.errorUnionSet(mod),
679 .payload => Type.err_int,
680 };
681 const err_val = switch (error_union.val) {
682 .err_name => |err_name| (try mod.intern(.{ .err = .{
683 .ty = ty.errorUnionSet(mod).toIntern(),
684 .name = err_name,
685 } })).toValue(),
686 .payload => try mod.intValue(Type.err_int, 0),
687 };
688 const payload_ty = ty.errorUnionPayload(mod);
689 const eu_layout = dg.errorUnionLayout(payload_ty);
690 if (!eu_layout.payload_has_bits) {
691 // We use the error type directly as the type.
692 try self.lower(err_ty, err_val);
693 return;
694 }
695
696 const payload_size = payload_ty.abiSize(mod);
697 const error_size = err_ty.abiSize(mod);
698 const ty_size = ty.abiSize(mod);
699 const padding = ty_size - payload_size - error_size;
700
701 const payload_val = switch (error_union.val) {
702 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
703 .payload => |payload| payload,
704 }.toValue();
705
706 if (eu_layout.error_first) {
707 try self.lower(err_ty, err_val);
708 try self.lower(payload_ty, payload_val);
709 } else {
710 try self.lower(payload_ty, payload_val);
711 try self.lower(err_ty, err_val);
712 }
713
714 try self.addUndef(padding);
715 },
716 .enum_tag => {
717 const int_val = try val.intFromEnum(ty, mod);
718
719 const int_ty = ty.intTagType(mod);
720
721 try self.lower(int_ty, int_val);
722 },
723 .float => try self.addFloat(ty, val),
724 .ptr => |ptr| {
725 const ptr_ty = switch (ptr.len) {
726 .none => ty,
727 else => ty.slicePtrFieldType(mod),
728 };
729 switch (ptr.addr) {
730 .decl => |decl| try self.addDeclRef(ptr_ty, decl),
731 .mut_decl => |mut_decl| try self.addDeclRef(ptr_ty, mut_decl.decl),
732 .int => |int| try self.addInt(Type.usize, int.toValue()),
733 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
734 }
735 if (ptr.len != .none) {
736 try self.addInt(Type.usize, ptr.len.toValue());
737 }
738 },
739 .opt => {
740 const payload_ty = ty.optionalChild(mod);
741 const payload_val = val.optionalValue(mod);
742 const abi_size = ty.abiSize(mod);
743
744 if (!payload_ty.hasRuntimeBits(mod)) {
745 try self.addConstBool(payload_val != null);
746 return;
747 } else if (ty.optionalReprIsPayload(mod)) {
748 // Optional representation is a nullable pointer or slice.
749 if (payload_val) |pl_val| {
750 try self.lower(payload_ty, pl_val);
751 } else {
752 const ptr_ty_ref = try dg.resolveType(ty, .indirect);
753 try self.addNullPtr(ptr_ty_ref);
754 }
755 return;
756 }
757
758 // Optional representation is a structure.
759 // { Payload, Bool }
760
761 // Subtract 1 for @sizeOf(bool).
762 // TODO: Make this not hardcoded.
763 const payload_size = payload_ty.abiSize(mod);
764 const padding = abi_size - payload_size - 1;
765
766 if (payload_val) |pl_val| {
767 try self.lower(payload_ty, pl_val);
768 } else {
769 try self.addUndef(payload_size);
770 }
771 try self.addConstBool(payload_val != null);
772 try self.addUndef(padding);
773 },
774 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
775 .array_type => |array_type| {
776 const elem_ty = array_type.child.toType();
777 switch (aggregate.storage) {
778 .bytes => |bytes| try self.addBytes(bytes),
779 .elems, .repeated_elem => {
780 for (0..@as(usize, @intCast(array_type.len))) |i| {
781 try self.lower(elem_ty, switch (aggregate.storage) {
782 .bytes => unreachable,
783 .elems => |elem_vals| elem_vals[@as(usize, @intCast(i))].toValue(),
784 .repeated_elem => |elem_val| elem_val.toValue(),
785 });
786 }
787 },
788 }
789 if (array_type.sentinel != .none) {
790 try self.lower(elem_ty, array_type.sentinel.toValue());
791 }
792 },
793 .vector_type => return dg.todo("indirect constant of type {}", .{ty.fmt(mod)}),
794 .struct_type => {
795 const struct_type = mod.typeToStruct(ty).?;
796 if (struct_type.layout == .Packed) {
797 return dg.todo("packed struct constants", .{});
798 }
799
800 // TODO iterate with runtime order instead so that struct field
801 // reordering can be enabled for this backend.
802 const struct_begin = self.size;
803 for (struct_type.field_types.get(ip), 0..) |field_ty, i_usize| {
804 const i: u32 = @intCast(i_usize);
805 if (struct_type.fieldIsComptime(ip, i)) continue;
806 if (!field_ty.toType().hasRuntimeBits(mod)) continue;
807
808 const field_val = switch (aggregate.storage) {
809 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
810 .ty = field_ty,
811 .storage = .{ .u64 = bytes[i] },
812 } }),
813 .elems => |elems| elems[i],
814 .repeated_elem => |elem| elem,
815 };
816 try self.lower(field_ty.toType(), field_val.toValue());
817
818 // Add padding if required.
819 // TODO: Add to type generation as well?
820 const unpadded_field_end = self.size - struct_begin;
821 const padded_field_end = ty.structFieldOffset(i + 1, mod);
822 const padding = padded_field_end - unpadded_field_end;
823 try self.addUndef(padding);
824 }
825 },
826 .anon_struct_type => unreachable, // TODO
827 else => unreachable,
828 },
829 .un => |un| {
830 const layout = ty.unionGetLayout(mod);
831
832 if (layout.payload_size == 0) {
833 return try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
834 }
835
836 const union_obj = mod.typeToUnion(ty).?;
837 if (union_obj.getLayout(ip) == .Packed) {
838 return dg.todo("packed union constants", .{});
839 }
840
841 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), dg.module).?;
842 const active_field_ty = union_obj.field_types.get(ip)[active_field].toType();
843
844 const has_tag = layout.tag_size != 0;
845 const tag_first = layout.tag_align.compare(.gte, layout.payload_align);
846
847 if (has_tag and tag_first) {
848 try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
849 }
850
851 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {
852 try self.lower(active_field_ty, un.val.toValue());
853 break :blk active_field_ty.abiSize(mod);
854 } else 0;
855
856 const payload_padding_len = layout.payload_size - active_field_size;
857 try self.addUndef(payload_padding_len);
858
859 if (has_tag and !tag_first) {
860 try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
861 }
862
863 try self.addUndef(layout.padding);
864 },
865 .memoized_call => unreachable,
866 }
867 }
868 };
869
870 /// Returns a pointer to `val`. The value is placed directly
871 /// into the storage class `storage_class`, and this is also where the resulting
872 /// pointer points to. Note: result is not necessarily an OpVariable instruction!
873 fn lowerIndirectConstant(
874 self: *DeclGen,
875 spv_decl_index: SpvModule.Decl.Index,
876 ty: Type,
877 val: Value,
878 storage_class: StorageClass,
879 cast_to_generic: bool,
880 alignment: u32,
881 ) Error!void {
882 // To simplify constant generation, we're going to generate constants as a word-array, and
883 // pointer cast the result to the right type.
884 // This means that the final constant will be generated as follows:
885 // %T = OpTypeStruct %members...
886 // %P = OpTypePointer %T
887 // %U = OpTypePointer %ty
888 // %1 = OpConstantComposite %T %initializers...
889 // %2 = OpVariable %P %1
890 // %result_id = OpSpecConstantOp OpBitcast %U %2
891 //
892 // The members consist of two options:
893 // - Literal values: ints, strings, etc. These are generated as u32 words.
894 // - Relocations, such as pointers: These are generated by embedding the pointer into the
895 // to-be-generated structure. There are two options here, depending on the alignment of the
896 // pointer value itself (not the alignment of the pointee).
897 // - Natively or over-aligned values. These can just be generated directly.
898 // - Underaligned pointers. These need to be packed into the word array by using a mixture of
899 // OpSpecConstantOp instructions such as OpConvertPtrToU, OpBitcast, OpShift, etc.
900
901 // TODO: Implement alignment here.
902 // This is hoing to require some hacks because there is no real way to
903 // set an OpVariable's alignment.
904 _ = alignment;
905
906 assert(storage_class != .Generic and storage_class != .Function);
907
908 const var_id = self.spv.allocId();
909 log.debug("lowerIndirectConstant: id = {}, index = {}, ty = {}, val = {}", .{ var_id.id, @intFromEnum(spv_decl_index), ty.fmt(self.module), val.fmtDebug() });
910
911 const section = &self.spv.globals.section;
912
913 const ty_ref = try self.resolveType(ty, .indirect);
914 const ptr_ty_ref = try self.spv.ptrType(ty_ref, storage_class);
915
916 // const target = self.getTarget();
917
918 // TODO: Fix the resulting global linking for these paths.
919 // if (val.isUndef(mod)) {
920 // // Special case: the entire value is undefined. In this case, we can just
921 // // generate an OpVariable with no initializer.
922 // return try section.emit(self.spv.gpa, .OpVariable, .{
923 // .id_result_type = self.typeId(ptr_ty_ref),
924 // .id_result = result_id,
925 // .storage_class = storage_class,
926 // });
927 // } else if (ty.abiSize(mod) == 0) {
928 // // Special case: if the type has no size, then return an undefined pointer.
929 // return try section.emit(self.spv.gpa, .OpUndef, .{
930 // .id_result_type = self.typeId(ptr_ty_ref),
931 // .id_result = result_id,
932 // });
933 // }
934
935 // TODO: Capture the above stuff in here as well...
936 const begin_inst = self.spv.beginGlobal();
937
938 const u32_ty_ref = try self.intType(.unsigned, 32);
939 var icl = IndirectConstantLowering{
940 .dg = self,
941 .u32_ty_ref = u32_ty_ref,
942 .members = std.ArrayList(CacheRef).init(self.gpa),
943 .initializers = std.ArrayList(IdRef).init(self.gpa),
944 .decl_deps = std.AutoArrayHashMap(SpvModule.Decl.Index, void).init(self.gpa),
945 };
946
947 defer icl.members.deinit();
948 defer icl.initializers.deinit();
949 defer icl.decl_deps.deinit();
950
951 try icl.lower(ty, val);
952 try icl.flush();
953
954 const constant_struct_ty_ref = try self.spv.resolve(.{ .struct_type = .{
955 .member_types = icl.members.items,
956 } });
957 const ptr_constant_struct_ty_ref = try self.spv.ptrType(constant_struct_ty_ref, storage_class);
958
959 const constant_struct_id = self.spv.allocId();
960 try section.emit(self.spv.gpa, .OpSpecConstantComposite, .{
961 .id_result_type = self.typeId(constant_struct_ty_ref),
962 .id_result = constant_struct_id,
963 .constituents = icl.initializers.items,
964 });
965
966 self.spv.globalPtr(spv_decl_index).?.result_id = var_id;
967 try section.emit(self.spv.gpa, .OpVariable, .{
968 .id_result_type = self.typeId(ptr_constant_struct_ty_ref),
969 .id_result = var_id,
970 .storage_class = storage_class,
971 .initializer = constant_struct_id,
972 });
973 // TODO: Set alignment of OpVariable.
974 // TODO: We may be able to eliminate these casts.
975
976 const const_ptr_id = try self.makePointerConstant(section, ptr_constant_struct_ty_ref, var_id);
977 const result_id = self.spv.declPtr(spv_decl_index).result_id;
978
979 const bitcast_result_id = if (cast_to_generic)
980 self.spv.allocId()
981 else
982 result_id;
983
984 try section.emitSpecConstantOp(self.spv.gpa, .OpBitcast, .{
985 .id_result_type = self.typeId(ptr_ty_ref),
986 .id_result = bitcast_result_id,
987 .operand = const_ptr_id,
988 });
989
990 if (cast_to_generic) {
991 const generic_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Generic);
992 try section.emitSpecConstantOp(self.spv.gpa, .OpPtrCastToGeneric, .{
993 .id_result_type = self.typeId(generic_ptr_ty_ref),
994 .id_result = result_id,
995 .pointer = bitcast_result_id,
996 });
569 return casted_ptr_id;
570 } else {
571 return ptr_id;
572 }
573 },
997574 }
998
999 try self.spv.declareDeclDeps(spv_decl_index, icl.decl_deps.keys());
1000 self.spv.endGlobal(spv_decl_index, begin_inst);
1001575 }
1002576
1003577 /// This function generates a load for a constant in direct (ie, non-memory) representation.
1004 /// When the constant is simple, it can be generated directly using OpConstant instructions. When
1005 /// the constant is more complicated however, it needs to be lowered to an indirect constant, which
1006 /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.
578 /// When the constant is simple, it can be generated directly using OpConstant instructions.
579 /// When the constant is more complicated however, it needs to be constructed using multiple values. This
580 /// is done by emitting a sequence of instructions that initialize the value.
581 //
1007582 /// This function should only be called during function code generation.
1008583 fn constant(self: *DeclGen, ty: Type, arg_val: Value, repr: Repr) !IdRef {
1009584 const mod = self.module;
1010585 const target = self.getTarget();
1011586 const result_ty_ref = try self.resolveType(ty, repr);
587 const ip = &mod.intern_pool;
1012588
1013589 var val = arg_val;
1014 switch (mod.intern_pool.indexToKey(val.toIntern())) {
590 switch (ip.indexToKey(val.toIntern())) {
1015591 .runtime_value => |rt| val = rt.val.toValue(),
1016592 else => {},
1017593 }
1018594
1019 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
1020 if (val.isUndef(mod)) {
595 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(ty, mod) });
596 if (val.isUndefDeep(mod)) {
1021597 return self.spv.constUndef(result_ty_ref);
1022598 }
1023599
1024 switch (mod.intern_pool.indexToKey(val.toIntern())) {
600 switch (ip.indexToKey(val.toIntern())) {
1025601 .int_type,
1026602 .ptr_type,
1027603 .array_type,
......@@ -1040,8 +616,7 @@ pub const DeclGen = struct {
1040616 .inferred_error_set_type,
1041617 => unreachable, // types, not values
1042618
1043 .undef => unreachable, // handled above
1044 .runtime_value => unreachable, // ???
619 .undef, .runtime_value => unreachable, // handled above
1045620
1046621 .variable,
1047622 .extern_func,
......@@ -1059,17 +634,14 @@ pub const DeclGen = struct {
1059634 .generic_poison,
1060635 => unreachable, // non-runtime values
1061636
1062 .false, .true => switch (repr) {
1063 .direct => return try self.spv.constBool(result_ty_ref, val.toBool()),
1064 .indirect => return try self.spv.constInt(result_ty_ref, @intFromBool(val.toBool())),
1065 },
637 .false, .true => return try self.constBool(val.toBool(), repr),
1066638 },
1067639
1068640 .int => {
1069641 if (ty.isSignedInt(mod)) {
1070 return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod));
642 return try self.constInt(result_ty_ref, val.toSignedInt(mod));
1071643 } else {
1072 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));
644 return try self.constInt(result_ty_ref, val.toUnsignedInt(mod));
1073645 }
1074646 },
1075647 .float => return switch (ty.floatBits(target)) {
......@@ -1081,40 +653,206 @@ pub const DeclGen = struct {
1081653 },
1082654 .err => |err| {
1083655 const value = try mod.getErrorValue(err.name);
1084 return try self.spv.constInt(result_ty_ref, value);
656 return try self.constInt(result_ty_ref, value);
1085657 },
1086 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1087 // OpVariable that is not really required.
1088 else => {
1089 // The value cannot be generated directly, so generate it as an indirect constant,
1090 // and then perform an OpLoad.
1091 const result_id = self.spv.allocId();
1092 const alignment = ty.abiAlignment(mod);
1093 const spv_decl_index = try self.spv.allocDecl(.global);
1094
1095 try self.lowerIndirectConstant(
1096 spv_decl_index,
1097 ty,
1098 val,
1099 .UniformConstant,
1100 false,
1101 @intCast(alignment.toByteUnits(0)),
1102 );
1103 log.debug("indirect constant: index = {}", .{@intFromEnum(spv_decl_index)});
1104 try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {});
658 .error_union => |error_union| {
659 // TODO: Error unions may be constructed with constant instructions if the payload type
660 // allows it. For now, just generate it here regardless.
661 const err_ty = switch (error_union.val) {
662 .err_name => ty.errorUnionSet(mod),
663 .payload => Type.err_int,
664 };
665 const err_val = switch (error_union.val) {
666 .err_name => |err_name| (try mod.intern(.{ .err = .{
667 .ty = ty.errorUnionSet(mod).toIntern(),
668 .name = err_name,
669 } })).toValue(),
670 .payload => try mod.intValue(Type.err_int, 0),
671 };
672 const payload_ty = ty.errorUnionPayload(mod);
673 const eu_layout = self.errorUnionLayout(payload_ty);
674 if (!eu_layout.payload_has_bits) {
675 // We use the error type directly as the type.
676 return try self.constant(err_ty, err_val, .indirect);
677 }
678
679 const payload_val = switch (error_union.val) {
680 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
681 .payload => |payload| payload,
682 }.toValue();
683
684 var constituents: [2]IdRef = undefined;
685 if (eu_layout.error_first) {
686 constituents[0] = try self.constant(err_ty, err_val, .indirect);
687 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);
688 } else {
689 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);
690 constituents[1] = try self.constant(err_ty, err_val, .indirect);
691 }
692
693 return try self.constructStruct(result_ty_ref, &constituents);
694 },
695 .enum_tag => {
696 const int_val = try val.intFromEnum(ty, mod);
697 const int_ty = ty.intTagType(mod);
698 return try self.constant(int_ty, int_val, repr);
699 },
700 .ptr => |ptr| {
701 const ptr_ty = switch (ptr.len) {
702 .none => ty,
703 else => ty.slicePtrFieldType(mod),
704 };
705 const ptr_id = try self.constantPtr(ptr_ty, val);
706 if (ptr.len == .none) {
707 return ptr_id;
708 }
709
710 const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect);
711 return try self.constructStruct(result_ty_ref, &.{ ptr_id, len_id });
712 },
713 .opt => {
714 const payload_ty = ty.optionalChild(mod);
715 const maybe_payload_val = val.optionalValue(mod);
716
717 if (!payload_ty.hasRuntimeBits(mod)) {
718 return try self.constBool(maybe_payload_val != null, .indirect);
719 } else if (ty.optionalReprIsPayload(mod)) {
720 // Optional representation is a nullable pointer or slice.
721 if (maybe_payload_val) |payload_val| {
722 return try self.constant(payload_ty, payload_val, .indirect);
723 } else {
724 const ptr_ty_ref = try self.resolveType(ty, .indirect);
725 return self.spv.constNull(ptr_ty_ref);
726 }
727 }
728
729 // Optional representation is a structure.
730 // { Payload, Bool }
731
732 const has_pl_id = try self.constBool(maybe_payload_val != null, .indirect);
733 const payload_id = if (maybe_payload_val) |payload_val|
734 try self.constant(payload_ty, payload_val, .indirect)
735 else
736 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
737
738 return try self.constructStruct(result_ty_ref, &.{ payload_id, has_pl_id });
739 },
740 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
741 .array_type => |array_type| {
742 const elem_ty = array_type.child.toType();
743 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
744
745 const constituents = try self.gpa.alloc(IdRef, @as(u32, @intCast(ty.arrayLenIncludingSentinel(mod))));
746 defer self.gpa.free(constituents);
747
748 switch (aggregate.storage) {
749 .bytes => |bytes| {
750 // TODO: This is really space inefficient, perhaps there is a better
751 // way to do it?
752 for (bytes, 0..) |byte, i| {
753 constituents[i] = try self.constInt(elem_ty_ref, byte);
754 }
755 },
756 .elems => |elems| {
757 for (0..@as(usize, @intCast(array_type.len))) |i| {
758 constituents[i] = try self.constant(elem_ty, elems[i].toValue(), .indirect);
759 }
760 },
761 .repeated_elem => |elem| {
762 const val_id = try self.constant(elem_ty, elem.toValue(), .indirect);
763 for (0..@as(usize, @intCast(array_type.len))) |i| {
764 constituents[i] = val_id;
765 }
766 },
767 }
768 if (array_type.sentinel != .none) {
769 constituents[constituents.len - 1] = try self.constant(elem_ty, array_type.sentinel.toValue(), .indirect);
770 }
771 return try self.constructArray(result_ty_ref, constituents);
772 },
773 .struct_type => {
774 const struct_type = mod.typeToStruct(ty).?;
775 if (struct_type.layout == .Packed) {
776 return self.todo("packed struct constants", .{});
777 }
778
779 var constituents = std.ArrayList(IdRef).init(self.gpa);
780 defer constituents.deinit();
781
782 var it = struct_type.iterateRuntimeOrder(ip);
783 while (it.next()) |field_index| {
784 const field_ty = struct_type.field_types.get(ip)[field_index].toType();
785 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
786 // This is a zero-bit field - we only needed it for the alignment.
787 continue;
788 }
789
790 // TODO: Padding?
791 const field_val = try val.fieldValue(mod, field_index);
792 const field_id = try self.constant(field_ty, field_val, .indirect);
1105793
1106 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
794 try constituents.append(field_id);
795 }
796
797 return try self.constructStruct(result_ty_ref, constituents.items);
798 },
799 .vector_type, .anon_struct_type => unreachable, // TODO
800 else => unreachable,
801 },
802 .un => |un| {
803 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
804 const layout = self.unionLayout(ty, active_field);
805 const payload = if (layout.active_field_size != 0)
806 try self.constant(layout.active_field_ty, un.val.toValue(), .indirect)
807 else
808 null;
809
810 return try self.unionInit(ty, active_field, payload);
811 },
812 .memoized_call => unreachable,
813 }
814 }
815
816 fn constantPtr(self: *DeclGen, ptr_ty: Type, ptr_val: Value) Error!IdRef {
817 const result_ty_ref = try self.resolveType(ptr_ty, .direct);
818 const mod = self.module;
819 switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {
820 .decl => |decl| return try self.constructDeclRef(ptr_ty, decl),
821 .mut_decl => |decl_mut| return try self.constructDeclRef(ptr_ty, decl_mut.decl),
822 .int => |int| {
823 const ptr_id = self.spv.allocId();
824 // TODO: This can probably be an OpSpecConstantOp Bitcast, but
825 // that is not implemented by Mesa yet. Therefore, just generate it
826 // as a runtime operation.
827 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
1107828 .id_result_type = self.typeId(result_ty_ref),
1108 .id_result = result_id,
1109 .pointer = self.spv.declPtr(spv_decl_index).result_id,
829 .id_result = ptr_id,
830 .integer_value = try self.constant(Type.usize, int.toValue(), .direct),
1110831 });
1111 // TODO: Convert bools? This logic should hook into `load`. It should be a dead
1112 // path though considering .Bool is handled above.
1113 return result_id;
832 return ptr_id;
833 },
834 .eu_payload => unreachable, // TODO
835 .opt_payload => unreachable, // TODO
836 .comptime_field => unreachable,
837 .elem => |elem_ptr| {
838 const elem_ptr_ty = mod.intern_pool.typeOf(elem_ptr.base).toType();
839 const parent_ptr_id = try self.constantPtr(elem_ptr_ty, elem_ptr.base.toValue());
840 const size_ty_ref = try self.sizeType();
841 const index_id = try self.constInt(size_ty_ref, elem_ptr.index);
842 return self.ptrAccessChain(result_ty_ref, parent_ptr_id, index_id, &.{});
1114843 },
844 .field => unreachable, // TODO
1115845 }
1116846 }
1117847
848 // Turn a Zig type's name into a cache reference.
849 fn resolveTypeName(self: *DeclGen, ty: Type) !CacheString {
850 var name = std.ArrayList(u8).init(self.gpa);
851 defer name.deinit();
852 try ty.print(name.writer(), self.module);
853 return try self.spv.resolveString(name.items);
854 }
855
1118856 /// Turn a Zig type into a SPIR-V Type, and return its type result-id.
1119857 fn resolveTypeId(self: *DeclGen, ty: Type) !IdResultType {
1120858 const type_ref = try self.resolveType(ty, .direct);
......@@ -1135,7 +873,9 @@ pub const DeclGen = struct {
1135873 // An array of largestSupportedIntBits.
1136874 return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits });
1137875 };
1138 return self.spv.intType(signedness, backing_bits);
876 // Kernel only supports unsigned ints.
877 // TODO: Only do this with Kernels
878 return self.spv.intType(.unsigned, backing_bits);
1139879 }
1140880
1141881 /// Create an integer type that represents 'usize'.
......@@ -1168,71 +908,70 @@ pub const DeclGen = struct {
1168908 fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef {
1169909 const mod = self.module;
1170910 const ip = &mod.intern_pool;
1171 const layout = ty.unionGetLayout(mod);
1172911 const union_obj = mod.typeToUnion(ty).?;
1173912
1174913 if (union_obj.getLayout(ip) == .Packed) {
1175914 return self.todo("packed union types", .{});
1176915 }
1177916
917 const layout = self.unionLayout(ty, maybe_active_field);
918
1178919 if (layout.payload_size == 0) {
1179920 // No payload, so represent this as just the tag type.
1180921 return try self.resolveType(union_obj.enum_tag_ty.toType(), .indirect);
1181922 }
1182923
1183 var member_types = std.BoundedArray(CacheRef, 4){};
1184 var member_names = std.BoundedArray(CacheString, 4){};
924 // TODO: We need to add the active field to the key, somehow.
925 if (maybe_active_field == null) {
926 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
927 }
928
929 var member_types: [4]CacheRef = undefined;
930 var member_names: [4]CacheString = undefined;
1185931
1186 const has_tag = layout.tag_size != 0;
1187 const tag_first = layout.tag_align.compare(.gte, layout.payload_align);
1188932 const u8_ty_ref = try self.intType(.unsigned, 8); // TODO: What if Int8Type is not enabled?
1189933
1190 if (has_tag and tag_first) {
934 if (layout.tag_size != 0) {
1191935 const tag_ty_ref = try self.resolveType(union_obj.enum_tag_ty.toType(), .indirect);
1192 member_types.appendAssumeCapacity(tag_ty_ref);
1193 member_names.appendAssumeCapacity(try self.spv.resolveString("tag"));
936 member_types[layout.tag_index] = tag_ty_ref;
937 member_names[layout.tag_index] = try self.spv.resolveString("(tag)");
1194938 }
1195939
1196 const active_field = maybe_active_field orelse layout.most_aligned_field;
1197 const active_field_ty = union_obj.field_types.get(ip)[active_field].toType();
1198
1199 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {
1200 const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect);
1201 member_types.appendAssumeCapacity(active_payload_ty_ref);
1202 member_names.appendAssumeCapacity(try self.spv.resolveString("payload"));
1203 break :blk active_field_ty.abiSize(mod);
1204 } else 0;
1205
1206 const payload_padding_len = layout.payload_size - active_field_size;
1207 if (payload_padding_len != 0) {
1208 const payload_padding_ty_ref = try self.spv.arrayType(@as(u32, @intCast(payload_padding_len)), u8_ty_ref);
1209 member_types.appendAssumeCapacity(payload_padding_ty_ref);
1210 member_names.appendAssumeCapacity(try self.spv.resolveString("payload_padding"));
940 if (layout.active_field_size != 0) {
941 const active_payload_ty_ref = try self.resolveType(layout.active_field_ty, .indirect);
942 member_types[layout.active_field_index] = active_payload_ty_ref;
943 member_names[layout.active_field_index] = try self.spv.resolveString("(payload)");
1211944 }
1212945
1213 if (has_tag and !tag_first) {
1214 const tag_ty_ref = try self.resolveType(union_obj.enum_tag_ty.toType(), .indirect);
1215 member_types.appendAssumeCapacity(tag_ty_ref);
1216 member_names.appendAssumeCapacity(try self.spv.resolveString("tag"));
946 if (layout.payload_padding_size != 0) {
947 const payload_padding_ty_ref = try self.spv.arrayType(@intCast(layout.payload_padding_size), u8_ty_ref);
948 member_types[layout.payload_padding_index] = payload_padding_ty_ref;
949 member_names[layout.payload_padding_index] = try self.spv.resolveString("(payload padding)");
1217950 }
1218951
1219 if (layout.padding != 0) {
1220 const padding_ty_ref = try self.spv.arrayType(layout.padding, u8_ty_ref);
1221 member_types.appendAssumeCapacity(padding_ty_ref);
1222 member_names.appendAssumeCapacity(try self.spv.resolveString("padding"));
952 if (layout.padding_size != 0) {
953 const padding_ty_ref = try self.spv.arrayType(@intCast(layout.padding_size), u8_ty_ref);
954 member_types[layout.padding_index] = padding_ty_ref;
955 member_names[layout.padding_index] = try self.spv.resolveString("(padding)");
1223956 }
1224957
1225 return try self.spv.resolve(.{ .struct_type = .{
1226 .member_types = member_types.slice(),
1227 .member_names = member_names.slice(),
958 const ty_ref = try self.spv.resolve(.{ .struct_type = .{
959 .name = try self.resolveTypeName(ty),
960 .member_types = member_types[0..layout.total_fields],
961 .member_names = member_names[0..layout.total_fields],
1228962 } });
963
964 if (maybe_active_field == null) {
965 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
966 }
967 return ty_ref;
1229968 }
1230969
1231970 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
1232971 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {
1233972 const mod = self.module;
1234973 const ip = &mod.intern_pool;
1235 log.debug("resolveType: ty = {}", .{ty.fmt(self.module)});
974 log.debug("resolveType: ty = {}", .{ty.fmt(mod)});
1236975 const target = self.getTarget();
1237976 switch (ty.zigTypeTag(mod)) {
1238977 .Void, .NoReturn => return try self.spv.resolve(.void_type),
......@@ -1242,6 +981,7 @@ pub const DeclGen = struct {
1242981 },
1243982 .Int => {
1244983 const int_info = ty.intInfo(mod);
984 // TODO: Integers in OpenCL kernels are always unsigned.
1245985 return try self.intType(int_info.signedness, int_info.bits);
1246986 },
1247987 .Enum => {
......@@ -1267,15 +1007,21 @@ pub const DeclGen = struct {
12671007 return try self.spv.resolve(.{ .float_type = .{ .bits = bits } });
12681008 },
12691009 .Array => {
1010 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1011
12701012 const elem_ty = ty.childType(mod);
1271 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
1013 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
12721014 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse {
12731015 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)});
12741016 };
1275 return self.spv.arrayType(total_len, elem_ty_ref);
1017 const ty_ref = try self.spv.arrayType(total_len, elem_ty_ref);
1018 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1019 return ty_ref;
12761020 },
12771021 .Fn => switch (repr) {
12781022 .direct => {
1023 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1024
12791025 const fn_info = mod.typeToFunc(ty).?;
12801026 // TODO: Put this somewhere in Sema.zig
12811027 if (fn_info.is_var_args)
......@@ -1288,10 +1034,13 @@ pub const DeclGen = struct {
12881034 }
12891035 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
12901036
1291 return try self.spv.resolve(.{ .function_type = .{
1037 const ty_ref = try self.spv.resolve(.{ .function_type = .{
12921038 .return_type = return_ty_ref,
12931039 .parameters = param_ty_refs,
12941040 } });
1041
1042 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1043 return ty_ref;
12951044 },
12961045 .indirect => {
12971046 // TODO: Represent function pointers properly.
......@@ -1337,6 +1086,8 @@ pub const DeclGen = struct {
13371086 } });
13381087 },
13391088 .Struct => {
1089 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1090
13401091 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
13411092 .anon_struct_type => |tuple| {
13421093 const member_types = try self.gpa.alloc(CacheRef, tuple.values.len);
......@@ -1350,9 +1101,13 @@ pub const DeclGen = struct {
13501101 member_index += 1;
13511102 }
13521103
1353 return try self.spv.resolve(.{ .struct_type = .{
1104 const ty_ref = try self.spv.resolve(.{ .struct_type = .{
1105 .name = try self.resolveTypeName(ty),
13541106 .member_types = member_types[0..member_index],
13551107 } });
1108
1109 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1110 return ty_ref;
13561111 },
13571112 .struct_type => |struct_type| struct_type,
13581113 else => unreachable,
......@@ -1376,13 +1131,14 @@ pub const DeclGen = struct {
13761131 try member_names.append(try self.spv.resolveString(field_name));
13771132 }
13781133
1379 const name = ip.stringToSlice(try mod.declPtr(struct_type.decl.unwrap().?).getFullyQualifiedName(mod));
1380
1381 return try self.spv.resolve(.{ .struct_type = .{
1382 .name = try self.spv.resolveString(name),
1134 const ty_ref = try self.spv.resolve(.{ .struct_type = .{
1135 .name = try self.resolveTypeName(ty),
13831136 .member_types = member_types.items,
13841137 .member_names = member_names.items,
13851138 } });
1139
1140 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1141 return ty_ref;
13861142 },
13871143 .Optional => {
13881144 const payload_ty = ty.optionalChild(mod);
......@@ -1399,15 +1155,20 @@ pub const DeclGen = struct {
13991155 return payload_ty_ref;
14001156 }
14011157
1158 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1159
14021160 const bool_ty_ref = try self.resolveType(Type.bool, .indirect);
14031161
1404 return try self.spv.resolve(.{ .struct_type = .{
1162 const ty_ref = try self.spv.resolve(.{ .struct_type = .{
14051163 .member_types = &.{ payload_ty_ref, bool_ty_ref },
14061164 .member_names = &.{
14071165 try self.spv.resolveString("payload"),
14081166 try self.spv.resolveString("valid"),
14091167 },
14101168 } });
1169
1170 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1171 return ty_ref;
14111172 },
14121173 .Union => return try self.resolveUnionType(ty, null),
14131174 .ErrorSet => return try self.intType(.unsigned, 16),
......@@ -1420,6 +1181,8 @@ pub const DeclGen = struct {
14201181 return error_ty_ref;
14211182 }
14221183
1184 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1185
14231186 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
14241187
14251188 var member_types: [2]CacheRef = undefined;
......@@ -1442,10 +1205,14 @@ pub const DeclGen = struct {
14421205 // TODO: ABI padding?
14431206 }
14441207
1445 return try self.spv.resolve(.{ .struct_type = .{
1208 const ty_ref = try self.spv.resolve(.{ .struct_type = .{
1209 .name = try self.resolveTypeName(ty),
14461210 .member_types = &member_types,
14471211 .member_names = &member_names,
14481212 } });
1213
1214 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1215 return ty_ref;
14491216 },
14501217
14511218 .Null,
......@@ -1509,6 +1276,85 @@ pub const DeclGen = struct {
15091276 };
15101277 }
15111278
1279 const UnionLayout = struct {
1280 active_field: u32,
1281 active_field_ty: Type,
1282 payload_size: u32,
1283
1284 tag_size: u32,
1285 tag_index: u32,
1286 active_field_size: u32,
1287 active_field_index: u32,
1288 payload_padding_size: u32,
1289 payload_padding_index: u32,
1290 padding_size: u32,
1291 padding_index: u32,
1292 total_fields: u32,
1293 };
1294
1295 fn unionLayout(self: *DeclGen, ty: Type, maybe_active_field: ?usize) UnionLayout {
1296 const mod = self.module;
1297 const ip = &mod.intern_pool;
1298 const layout = ty.unionGetLayout(self.module);
1299 const union_obj = mod.typeToUnion(ty).?;
1300
1301 const active_field = maybe_active_field orelse layout.most_aligned_field;
1302 const active_field_ty = union_obj.field_types.get(ip)[active_field].toType();
1303
1304 var union_layout = UnionLayout{
1305 .active_field = @intCast(active_field),
1306 .active_field_ty = active_field_ty,
1307 .payload_size = @intCast(layout.payload_size),
1308 .tag_size = @intCast(layout.tag_size),
1309 .tag_index = undefined,
1310 .active_field_size = undefined,
1311 .active_field_index = undefined,
1312 .payload_padding_size = undefined,
1313 .payload_padding_index = undefined,
1314 .padding_size = @intCast(layout.padding),
1315 .padding_index = undefined,
1316 .total_fields = undefined,
1317 };
1318
1319 union_layout.active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod))
1320 @intCast(active_field_ty.abiSize(mod))
1321 else
1322 0;
1323 union_layout.payload_padding_size = @intCast(layout.payload_size - union_layout.active_field_size);
1324
1325 const tag_first = layout.tag_align.compare(.gte, layout.payload_align);
1326 var field_index: u32 = 0;
1327
1328 if (union_layout.tag_size != 0 and tag_first) {
1329 union_layout.tag_index = field_index;
1330 field_index += 1;
1331 }
1332
1333 if (union_layout.active_field_size != 0) {
1334 union_layout.active_field_index = field_index;
1335 field_index += 1;
1336 }
1337
1338 if (union_layout.payload_padding_size != 0) {
1339 union_layout.payload_padding_index = field_index;
1340 field_index += 1;
1341 }
1342
1343 if (union_layout.tag_size != 0 and !tag_first) {
1344 union_layout.tag_index = field_index;
1345 field_index += 1;
1346 }
1347
1348 if (union_layout.padding_size != 0) {
1349 union_layout.padding_index = field_index;
1350 field_index += 1;
1351 }
1352
1353 union_layout.total_fields = field_index;
1354
1355 return union_layout;
1356 }
1357
15121358 /// The SPIR-V backend is not yet advanced enough to support the std testing infrastructure.
15131359 /// In order to be able to run tests, we "temporarily" lower test kernels into separate entry-
15141360 /// points. The test executor will then be able to invoke these to run the tests.
......@@ -1588,6 +1434,8 @@ pub const DeclGen = struct {
15881434
15891435 const decl_id = self.spv.declPtr(spv_decl_index).result_id;
15901436
1437 try self.base_line_stack.append(self.gpa, decl.src_line);
1438
15911439 if (decl.val.getFunction(mod)) |_| {
15921440 assert(decl.ty.zigTypeTag(mod) == .Fn);
15931441 const prototype_id = try self.resolveTypeId(decl.ty);
......@@ -1630,11 +1478,7 @@ pub const DeclGen = struct {
16301478 try self.spv.addFunction(spv_decl_index, self.func);
16311479
16321480 const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
1633
1634 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
1635 .target = decl_id,
1636 .name = fqn,
1637 });
1481 try self.spv.debugName(decl_id, fqn);
16381482
16391483 // Temporarily generate a test kernel declaration if this is a test function.
16401484 if (self.module.test_functions.contains(self.decl_index)) {
......@@ -1650,28 +1494,69 @@ pub const DeclGen = struct {
16501494 return self.todo("importing extern variables", .{});
16511495 }
16521496
1653 // TODO: integrate with variable().
1497 // Currently, initializers for CrossWorkgroup variables is not implemented
1498 // in Mesa. Therefore we generate an initialization kernel instead.
16541499
1500 const void_ty_ref = try self.resolveType(Type.void, .direct);
1501
1502 const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{
1503 .return_type = void_ty_ref,
1504 .parameters = &.{},
1505 } });
1506
1507 // Generate the actual variable for the global...
16551508 const final_storage_class = spvStorageClass(decl.@"addrspace");
16561509 const actual_storage_class = switch (final_storage_class) {
16571510 .Generic => .CrossWorkgroup,
16581511 else => final_storage_class,
16591512 };
16601513
1661 try self.lowerIndirectConstant(
1662 spv_decl_index,
1663 decl.ty,
1664 init_val,
1665 actual_storage_class,
1666 final_storage_class == .Generic,
1667 @intCast(decl.alignment.toByteUnits(0)),
1668 );
1514 const ty_ref = try self.resolveType(decl.ty, .indirect);
1515 const ptr_ty_ref = try self.spv.ptrType(ty_ref, actual_storage_class);
1516
1517 const begin = self.spv.beginGlobal();
1518 try self.spv.globals.section.emit(self.spv.gpa, .OpVariable, .{
1519 .id_result_type = self.typeId(ptr_ty_ref),
1520 .id_result = decl_id,
1521 .storage_class = actual_storage_class,
1522 });
1523
1524 // Now emit the instructions that initialize the variable.
1525 const initializer_id = self.spv.allocId();
1526 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
1527 .id_result_type = self.typeId(void_ty_ref),
1528 .id_result = initializer_id,
1529 .function_control = .{},
1530 .function_type = self.typeId(initializer_proto_ty_ref),
1531 });
1532 const root_block_id = self.spv.allocId();
1533 try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{
1534 .id_result = root_block_id,
1535 });
1536 self.current_block_label_id = root_block_id;
1537
1538 const val_id = try self.constant(decl.ty, init_val, .indirect);
1539 try self.func.body.emit(self.spv.gpa, .OpStore, .{
1540 .pointer = decl_id,
1541 .object = val_id,
1542 });
1543
1544 // TODO: We should be able to get rid of this by now...
1545 self.spv.endGlobal(spv_decl_index, begin, decl_id, initializer_id);
1546
1547 try self.func.body.emit(self.spv.gpa, .OpReturn, {});
1548 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
1549 try self.spv.addFunction(spv_decl_index, self.func);
1550
1551 const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
1552 try self.spv.debugName(decl_id, fqn);
1553 try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn});
16691554 }
16701555 }
16711556
16721557 fn intFromBool(self: *DeclGen, result_ty_ref: CacheRef, condition_id: IdRef) !IdRef {
1673 const zero_id = try self.spv.constInt(result_ty_ref, 0);
1674 const one_id = try self.spv.constInt(result_ty_ref, 1);
1558 const zero_id = try self.constInt(result_ty_ref, 0);
1559 const one_id = try self.constInt(result_ty_ref, 1);
16751560 const result_id = self.spv.allocId();
16761561 try self.func.body.emit(self.spv.gpa, .OpSelect, .{
16771562 .id_result_type = self.typeId(result_ty_ref),
......@@ -1691,7 +1576,7 @@ pub const DeclGen = struct {
16911576 .Bool => blk: {
16921577 const direct_bool_ty_ref = try self.resolveType(ty, .direct);
16931578 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);
1694 const zero_id = try self.spv.constInt(indirect_bool_ty_ref, 0);
1579 const zero_id = try self.constInt(indirect_bool_ty_ref, 0);
16951580 const result_id = self.spv.allocId();
16961581 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
16971582 .id_result_type = self.typeId(direct_bool_ty_ref),
......@@ -1732,13 +1617,11 @@ pub const DeclGen = struct {
17321617 return try self.convertToDirect(result_ty, result_id);
17331618 }
17341619
1735 fn load(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef) !IdRef {
1736 const mod = self.module;
1737 const value_ty = ptr_ty.childType(mod);
1620 fn load(self: *DeclGen, value_ty: Type, ptr_id: IdRef, is_volatile: bool) !IdRef {
17381621 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);
17391622 const result_id = self.spv.allocId();
17401623 const access = spec.MemoryAccess.Extended{
1741 .Volatile = ptr_ty.isVolatilePtr(mod),
1624 .Volatile = is_volatile,
17421625 };
17431626 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
17441627 .id_result_type = self.typeId(indirect_value_ty_ref),
......@@ -1749,12 +1632,10 @@ pub const DeclGen = struct {
17491632 return try self.convertToDirect(value_ty, result_id);
17501633 }
17511634
1752 fn store(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, value_id: IdRef) !void {
1753 const mod = self.module;
1754 const value_ty = ptr_ty.childType(mod);
1635 fn store(self: *DeclGen, value_ty: Type, ptr_id: IdRef, value_id: IdRef, is_volatile: bool) !void {
17551636 const indirect_value_id = try self.convertToIndirect(value_ty, value_id);
17561637 const access = spec.MemoryAccess.Extended{
1757 .Volatile = ptr_ty.isVolatilePtr(mod),
1638 .Volatile = is_volatile,
17581639 };
17591640 try self.func.body.emit(self.spv.gpa, .OpStore, .{
17601641 .pointer = ptr_id,
......@@ -1795,7 +1676,8 @@ pub const DeclGen = struct {
17951676 .rem_optimized,
17961677 => try self.airArithOp(inst, .OpFRem, .OpSRem, .OpSRem, false),
17971678
1798 .add_with_overflow => try self.airOverflowArithOp(inst),
1679 .add_with_overflow => try self.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan),
1680 .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan),
17991681
18001682 .shuffle => try self.airShuffle(inst),
18011683
......@@ -1812,19 +1694,27 @@ pub const DeclGen = struct {
18121694
18131695 .bitcast => try self.airBitCast(inst),
18141696 .intcast, .trunc => try self.airIntCast(inst),
1815 .int_from_ptr => try self.airIntFromPtr(inst),
1816 .float_from_int => try self.airFloatFromInt(inst),
1817 .int_from_float => try self.airIntFromFloat(inst),
1697 .int_from_ptr => try self.airIntFromPtr(inst),
1698 .float_from_int => try self.airFloatFromInt(inst),
1699 .int_from_float => try self.airIntFromFloat(inst),
18181700 .not => try self.airNot(inst),
18191701
1702 .array_to_slice => try self.airArrayToSlice(inst),
1703 .slice => try self.airSlice(inst),
1704 .aggregate_init => try self.airAggregateInit(inst),
1705
18201706 .slice_ptr => try self.airSliceField(inst, 0),
18211707 .slice_len => try self.airSliceField(inst, 1),
18221708 .slice_elem_ptr => try self.airSliceElemPtr(inst),
18231709 .slice_elem_val => try self.airSliceElemVal(inst),
18241710 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
18251711 .ptr_elem_val => try self.airPtrElemVal(inst),
1712 .array_elem_val => try self.airArrayElemVal(inst),
18261713
1714 .set_union_tag => return try self.airSetUnionTag(inst),
18271715 .get_union_tag => try self.airGetUnionTag(inst),
1716 .union_init => try self.airUnionInit(inst),
1717
18281718 .struct_field_val => try self.airStructFieldVal(inst),
18291719
18301720 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
......@@ -1851,7 +1741,6 @@ pub const DeclGen = struct {
18511741 .br => return self.airBr(inst),
18521742 .breakpoint => return,
18531743 .cond_br => return self.airCondBr(inst),
1854 .dbg_stmt => return self.airDbgStmt(inst),
18551744 .loop => return self.airLoop(inst),
18561745 .ret => return self.airRet(inst),
18571746 .ret_load => return self.airRetLoad(inst),
......@@ -1859,11 +1748,22 @@ pub const DeclGen = struct {
18591748 .switch_br => return self.airSwitchBr(inst),
18601749 .unreach, .trap => return self.airUnreach(),
18611750
1751 .dbg_stmt => return self.airDbgStmt(inst),
1752 .dbg_inline_begin => return self.airDbgInlineBegin(inst),
1753 .dbg_inline_end => return self.airDbgInlineEnd(inst),
1754 .dbg_var_ptr, .dbg_var_val => return self.airDbgVar(inst),
1755 .dbg_block_begin => return,
1756 .dbg_block_end => return,
1757
18621758 .unwrap_errunion_err => try self.airErrUnionErr(inst),
1759 .unwrap_errunion_payload => try self.airErrUnionPayload(inst),
18631760 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
1761 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
18641762
18651763 .is_null => try self.airIsNull(inst, .is_null),
18661764 .is_non_null => try self.airIsNull(inst, .is_non_null),
1765 .is_err => try self.airIsErr(inst, .is_err),
1766 .is_non_err => try self.airIsErr(inst, .is_non_err),
18671767
18681768 .optional_payload => try self.airUnwrapOptional(inst),
18691769 .wrap_optional => try self.airWrapOptional(inst),
......@@ -1874,13 +1774,6 @@ pub const DeclGen = struct {
18741774 .call_always_tail => try self.airCall(inst, .always_tail),
18751775 .call_never_tail => try self.airCall(inst, .never_tail),
18761776 .call_never_inline => try self.airCall(inst, .never_inline),
1877
1878 .dbg_inline_begin => return,
1879 .dbg_inline_end => return,
1880 .dbg_var_ptr => return,
1881 .dbg_var_val => return,
1882 .dbg_block_begin => return,
1883 .dbg_block_end => return,
18841777 // zig fmt: on
18851778
18861779 else => |tag| return self.todo("implement AIR tag {s}", .{@tagName(tag)}),
......@@ -1934,7 +1827,7 @@ pub const DeclGen = struct {
19341827 fn maskStrangeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, bits: u16) !IdRef {
19351828 const mask_value = if (bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(bits))) - 1;
19361829 const result_id = self.spv.allocId();
1937 const mask_id = try self.spv.constInt(ty_ref, mask_value);
1830 const mask_id = try self.constInt(ty_ref, mask_value);
19381831 try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{
19391832 .id_result_type = self.typeId(ty_ref),
19401833 .id_result = result_id,
......@@ -2012,7 +1905,13 @@ pub const DeclGen = struct {
20121905 return result_id;
20131906 }
20141907
2015 fn airOverflowArithOp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
1908 fn airAddSubOverflow(
1909 self: *DeclGen,
1910 inst: Air.Inst.Index,
1911 comptime add: Opcode,
1912 comptime ucmp: Opcode,
1913 comptime scmp: Opcode,
1914 ) !?IdRef {
20161915 if (self.liveness.isUnused(inst)) return null;
20171916
20181917 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
......@@ -2044,7 +1943,7 @@ pub const DeclGen = struct {
20441943
20451944 // TODO: Operations other than addition.
20461945 const value_id = self.spv.allocId();
2047 try self.func.body.emit(self.spv.gpa, .OpIAdd, .{
1946 try self.func.body.emit(self.spv.gpa, add, .{
20481947 .id_result_type = operand_ty_id,
20491948 .id_result = value_id,
20501949 .operand_1 = lhs,
......@@ -2054,8 +1953,9 @@ pub const DeclGen = struct {
20541953 const overflowed_id = switch (info.signedness) {
20551954 .unsigned => blk: {
20561955 // Overflow happened if the result is smaller than either of the operands. It doesn't matter which.
1956 // For subtraction the conditions need to be swapped.
20571957 const overflowed_id = self.spv.allocId();
2058 try self.func.body.emit(self.spv.gpa, .OpULessThan, .{
1958 try self.func.body.emit(self.spv.gpa, ucmp, .{
20591959 .id_result_type = self.typeId(bool_ty_ref),
20601960 .id_result = overflowed_id,
20611961 .operand_1 = value_id,
......@@ -2064,16 +1964,25 @@ pub const DeclGen = struct {
20641964 break :blk overflowed_id;
20651965 },
20661966 .signed => blk: {
2067 // Overflow happened if:
1967 // lhs - rhs
1968 // For addition, overflow happened if:
20681969 // - rhs is negative and value > lhs
20691970 // - rhs is positive and value < lhs
20701971 // This can be shortened to:
2071 // (rhs < 0 && value > lhs) || (rhs >= 0 && value <= lhs)
1972 // (rhs < 0 and value > lhs) or (rhs >= 0 and value <= lhs)
20721973 // = (rhs < 0) == (value > lhs)
1974 // = (rhs < 0) == (lhs < value)
20731975 // Note that signed overflow is also wrapping in spir-v.
1976 // For subtraction, overflow happened if:
1977 // - rhs is negative and value < lhs
1978 // - rhs is positive and value > lhs
1979 // This can be shortened to:
1980 // (rhs < 0 and value < lhs) or (rhs >= 0 and value >= lhs)
1981 // = (rhs < 0) == (value < lhs)
1982 // = (rhs < 0) == (lhs > value)
20741983
20751984 const rhs_lt_zero_id = self.spv.allocId();
2076 const zero_id = try self.spv.constInt(operand_ty_ref, 0);
1985 const zero_id = try self.constInt(operand_ty_ref, 0);
20771986 try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{
20781987 .id_result_type = self.typeId(bool_ty_ref),
20791988 .id_result = rhs_lt_zero_id,
......@@ -2082,11 +1991,11 @@ pub const DeclGen = struct {
20821991 });
20831992
20841993 const value_gt_lhs_id = self.spv.allocId();
2085 try self.func.body.emit(self.spv.gpa, .OpSGreaterThan, .{
1994 try self.func.body.emit(self.spv.gpa, scmp, .{
20861995 .id_result_type = self.typeId(bool_ty_ref),
20871996 .id_result = value_gt_lhs_id,
2088 .operand_1 = value_id,
2089 .operand_2 = lhs,
1997 .operand_1 = lhs,
1998 .operand_2 = value_id,
20901999 });
20912000
20922001 const overflowed_id = self.spv.allocId();
......@@ -2146,40 +2055,65 @@ pub const DeclGen = struct {
21462055 return result_id;
21472056 }
21482057
2149 /// AccessChain is essentially PtrAccessChain with 0 as initial argument. The effective
2150 /// difference lies in whether the resulting type of the first dereference will be the
2151 /// same as that of the base pointer, or that of a dereferenced base pointer. AccessChain
2152 /// is the latter and PtrAccessChain is the former.
2153 fn accessChain(
2058 fn indicesToIds(self: *DeclGen, indices: []const u32) ![]IdRef {
2059 const index_ty_ref = try self.intType(.unsigned, 32);
2060 const ids = try self.gpa.alloc(IdRef, indices.len);
2061 errdefer self.gpa.free(ids);
2062 for (indices, ids) |index, *id| {
2063 id.* = try self.constInt(index_ty_ref, index);
2064 }
2065
2066 return ids;
2067 }
2068
2069 fn accessChainId(
21542070 self: *DeclGen,
21552071 result_ty_ref: CacheRef,
21562072 base: IdRef,
2157 indexes: []const IdRef,
2073 indices: []const IdRef,
21582074 ) !IdRef {
21592075 const result_id = self.spv.allocId();
21602076 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
21612077 .id_result_type = self.typeId(result_ty_ref),
21622078 .id_result = result_id,
21632079 .base = base,
2164 .indexes = indexes,
2080 .indexes = indices,
21652081 });
21662082 return result_id;
21672083 }
21682084
2085 /// AccessChain is essentially PtrAccessChain with 0 as initial argument. The effective
2086 /// difference lies in whether the resulting type of the first dereference will be the
2087 /// same as that of the base pointer, or that of a dereferenced base pointer. AccessChain
2088 /// is the latter and PtrAccessChain is the former.
2089 fn accessChain(
2090 self: *DeclGen,
2091 result_ty_ref: CacheRef,
2092 base: IdRef,
2093 indices: []const u32,
2094 ) !IdRef {
2095 const ids = try self.indicesToIds(indices);
2096 defer self.gpa.free(ids);
2097 return try self.accessChainId(result_ty_ref, base, ids);
2098 }
2099
21692100 fn ptrAccessChain(
21702101 self: *DeclGen,
21712102 result_ty_ref: CacheRef,
21722103 base: IdRef,
21732104 element: IdRef,
2174 indexes: []const IdRef,
2105 indices: []const u32,
21752106 ) !IdRef {
2107 const ids = try self.indicesToIds(indices);
2108 defer self.gpa.free(ids);
2109
21762110 const result_id = self.spv.allocId();
21772111 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
21782112 .id_result_type = self.typeId(result_ty_ref),
21792113 .id_result = result_id,
21802114 .base = base,
21812115 .element = element,
2182 .indexes = indexes,
2116 .indexes = ids,
21832117 });
21842118 return result_id;
21852119 }
......@@ -2192,7 +2126,7 @@ pub const DeclGen = struct {
21922126 .One => {
21932127 // Pointer to array
21942128 // TODO: Is this correct?
2195 return try self.accessChain(result_ty_ref, ptr_id, &.{offset_id});
2129 return try self.accessChainId(result_ty_ref, ptr_id, &.{offset_id});
21962130 },
21972131 .C, .Many => {
21982132 return try self.ptrAccessChain(result_ty_ref, ptr_id, offset_id, &.{});
......@@ -2294,8 +2228,8 @@ pub const DeclGen = struct {
22942228 .gte => .OpFOrdGreaterThanEqual,
22952229 },
22962230 .bool => break :opcode switch (op) {
2297 .eq => .OpIEqual,
2298 .neq => .OpINotEqual,
2231 .eq => .OpLogicalEqual,
2232 .neq => .OpLogicalNotEqual,
22992233 else => unreachable,
23002234 },
23012235 .strange_integer => sign: {
......@@ -2491,16 +2425,110 @@ pub const DeclGen = struct {
24912425 if (self.liveness.isUnused(inst)) return null;
24922426 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
24932427 const operand_id = try self.resolve(ty_op.operand);
2428 const result_ty = self.typeOfIndex(inst);
2429 const result_ty_id = try self.resolveTypeId(result_ty);
2430 const info = try self.arithmeticTypeInfo(result_ty);
2431
24942432 const result_id = self.spv.allocId();
2495 const result_type_id = try self.resolveTypeId(Type.bool);
2496 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{
2497 .id_result_type = result_type_id,
2498 .id_result = result_id,
2499 .operand = operand_id,
2500 });
2433 switch (info.class) {
2434 .bool => {
2435 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{
2436 .id_result_type = result_ty_id,
2437 .id_result = result_id,
2438 .operand = operand_id,
2439 });
2440 },
2441 .float => unreachable,
2442 .composite_integer => unreachable, // TODO
2443 .strange_integer, .integer => {
2444 // Note: strange integer bits will be masked before operations that do not hold under modulo.
2445 try self.func.body.emit(self.spv.gpa, .OpNot, .{
2446 .id_result_type = result_ty_id,
2447 .id_result = result_id,
2448 .operand = operand_id,
2449 });
2450 },
2451 }
2452
25012453 return result_id;
25022454 }
25032455
2456 fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2457 if (self.liveness.isUnused(inst)) return null;
2458
2459 const mod = self.module;
2460 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2461 const array_ptr_ty = self.typeOf(ty_op.operand);
2462 const array_ty = array_ptr_ty.childType(mod);
2463 const elem_ty = array_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.
2464 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
2465 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(array_ptr_ty.ptrAddressSpace(mod)));
2466 const slice_ty = self.typeOfIndex(inst);
2467 const slice_ty_ref = try self.resolveType(slice_ty, .direct);
2468 const size_ty_ref = try self.sizeType();
2469
2470 const array_ptr_id = try self.resolve(ty_op.operand);
2471 const len_id = try self.constInt(size_ty_ref, array_ty.arrayLen(mod));
2472
2473 if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2474 unreachable; // TODO
2475 }
2476
2477 // Convert the pointer-to-array to a pointer to the first element.
2478 const elem_ptr_id = try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});
2479 return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id });
2480 }
2481
2482 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2483 if (self.liveness.isUnused(inst)) return null;
2484
2485 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2486 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2487 const ptr_id = try self.resolve(bin_op.lhs);
2488 const len_id = try self.resolve(bin_op.rhs);
2489 const slice_ty = self.typeOfIndex(inst);
2490 const slice_ty_ref = try self.resolveType(slice_ty, .direct);
2491
2492 return try self.constructStruct(slice_ty_ref, &.{
2493 ptr_id, // Note: Type should not need to be converted to direct.
2494 len_id, // Note: Type should not need to be converted to direct.
2495 });
2496 }
2497
2498 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2499 if (self.liveness.isUnused(inst)) return null;
2500
2501 const mod = self.module;
2502 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2503 const result_ty = self.typeOfIndex(inst);
2504 const result_ty_ref = try self.resolveType(result_ty, .direct);
2505 const len: usize = @intCast(result_ty.arrayLen(mod));
2506 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);
2507
2508 switch (result_ty.zigTypeTag(mod)) {
2509 .Vector => unreachable, // TODO
2510 .Struct => unreachable, // TODO
2511 .Array => {
2512 const array_info = result_ty.arrayInfo(mod);
2513 const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod));
2514 const elem_ids = try self.gpa.alloc(IdRef, n_elems);
2515 defer self.gpa.free(elem_ids);
2516
2517 for (elements, 0..) |elem_inst, i| {
2518 const id = try self.resolve(elem_inst);
2519 elem_ids[i] = try self.convertToIndirect(array_info.elem_type, id);
2520 }
2521
2522 if (array_info.sentinel) |sentinel_val| {
2523 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);
2524 }
2525
2526 return try self.constructArray(result_ty_ref, elem_ids);
2527 },
2528 else => unreachable,
2529 }
2530 }
2531
25042532 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
25052533 if (self.liveness.isUnused(inst)) return null;
25062534 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
......@@ -2539,7 +2567,7 @@ pub const DeclGen = struct {
25392567
25402568 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
25412569 const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{});
2542 return try self.load(slice_ty, elem_ptr);
2570 return try self.load(slice_ty.childType(mod), elem_ptr, slice_ty.isVolatilePtr(mod));
25432571 }
25442572
25452573 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {
......@@ -2551,7 +2579,7 @@ pub const DeclGen = struct {
25512579 if (ptr_ty.isSinglePointer(mod)) {
25522580 // Pointer-to-array. In this case, the resulting pointer is not of the same type
25532581 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
2554 return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id});
2582 return try self.accessChainId(elem_ptr_ty_ref, ptr_id, &.{index_id});
25552583 } else {
25562584 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
25572585 return try self.ptrAccessChain(elem_ptr_ty_ref, ptr_id, index_id, &.{});
......@@ -2574,39 +2602,199 @@ pub const DeclGen = struct {
25742602 return try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
25752603 }
25762604
2605 fn airArrayElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2606 if (self.liveness.isUnused(inst)) return null;
2607
2608 const mod = self.module;
2609 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2610 const array_ty = self.typeOf(bin_op.lhs);
2611 const array_ty_ref = try self.resolveType(array_ty, .direct);
2612 const elem_ty = array_ty.childType(mod);
2613 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
2614 const array_id = try self.resolve(bin_op.lhs);
2615 const index_id = try self.resolve(bin_op.rhs);
2616
2617 // SPIR-V doesn't have an array indexing function for some damn reason.
2618 // For now, just generate a temporary and use that.
2619 // TODO: This backend probably also should use isByRef from llvm...
2620
2621 const array_ptr_ty_ref = try self.spv.ptrType(array_ty_ref, .Function);
2622 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, .Function);
2623
2624 const tmp_id = self.spv.allocId();
2625 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
2626 .id_result_type = self.typeId(array_ptr_ty_ref),
2627 .id_result = tmp_id,
2628 .storage_class = .Function,
2629 });
2630 try self.func.body.emit(self.spv.gpa, .OpStore, .{
2631 .pointer = tmp_id,
2632 .object = array_id,
2633 });
2634
2635 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});
2636 return try self.load(elem_ty, elem_ptr_id, false);
2637 }
2638
25772639 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2640 if (self.liveness.isUnused(inst)) return null;
2641
25782642 const mod = self.module;
25792643 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
25802644 const ptr_ty = self.typeOf(bin_op.lhs);
2645 const elem_ty = self.typeOfIndex(inst);
25812646 const ptr_id = try self.resolve(bin_op.lhs);
25822647 const index_id = try self.resolve(bin_op.rhs);
2583
25842648 const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
2649 return try self.load(elem_ty, elem_ptr_id, ptr_ty.isVolatilePtr(mod));
2650 }
2651
2652 fn airSetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !void {
2653 const mod = self.module;
2654 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2655 const un_ptr_ty = self.typeOf(bin_op.lhs);
2656 const un_ty = un_ptr_ty.childType(mod);
2657 const layout = self.unionLayout(un_ty, null);
25852658
2586 // If we have a pointer-to-array, construct an element pointer to use with load()
2587 // If we pass ptr_ty directly, it will attempt to load the entire array rather than
2588 // just an element.
2589 var elem_ptr_info = ptr_ty.ptrInfo(mod);
2590 elem_ptr_info.flags.size = .One;
2591 const elem_ptr_ty = try mod.intern_pool.get(mod.gpa, .{ .ptr_type = elem_ptr_info });
2659 if (layout.tag_size == 0) return;
25922660
2593 return try self.load(elem_ptr_ty.toType(), elem_ptr_id);
2661 const tag_ty = un_ty.unionTagTypeSafety(mod).?;
2662 const tag_ty_ref = try self.resolveType(tag_ty, .indirect);
2663 const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, spvStorageClass(un_ptr_ty.ptrAddressSpace(mod)));
2664
2665 const union_ptr_id = try self.resolve(bin_op.lhs);
2666 const new_tag_id = try self.resolve(bin_op.rhs);
2667
2668 if (layout.payload_size == 0) {
2669 try self.store(tag_ty, union_ptr_id, new_tag_id, un_ptr_ty.isVolatilePtr(mod));
2670 } else {
2671 const ptr_id = try self.accessChain(tag_ptr_ty_ref, union_ptr_id, &.{layout.tag_index});
2672 try self.store(tag_ty, ptr_id, new_tag_id, un_ptr_ty.isVolatilePtr(mod));
2673 }
25942674 }
25952675
25962676 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2677 if (self.liveness.isUnused(inst)) return null;
2678
25972679 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
25982680 const un_ty = self.typeOf(ty_op.operand);
25992681
26002682 const mod = self.module;
2601 const layout = un_ty.unionGetLayout(mod);
2683 const layout = self.unionLayout(un_ty, null);
26022684 if (layout.tag_size == 0) return null;
26032685
26042686 const union_handle = try self.resolve(ty_op.operand);
26052687 if (layout.payload_size == 0) return union_handle;
26062688
26072689 const tag_ty = un_ty.unionTagTypeSafety(mod).?;
2608 const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align));
2609 return try self.extractField(tag_ty, union_handle, tag_index);
2690 return try self.extractField(tag_ty, union_handle, layout.tag_index);
2691 }
2692
2693 fn unionInit(
2694 self: *DeclGen,
2695 ty: Type,
2696 active_field: u32,
2697 payload: ?IdRef,
2698 ) !IdRef {
2699 // To initialize a union, generate a temporary variable with the
2700 // type that has the right field active, then pointer-cast and store
2701 // the active field, and finally load and return the entire union.
2702
2703 const mod = self.module;
2704 const ip = &mod.intern_pool;
2705 const union_ty = mod.typeToUnion(ty).?;
2706
2707 if (union_ty.getLayout(ip) == .Packed) {
2708 unreachable; // TODO
2709 }
2710
2711 const maybe_tag_ty = ty.unionTagTypeSafety(mod);
2712 const layout = self.unionLayout(ty, active_field);
2713
2714 const tag_int = if (layout.tag_size != 0) blk: {
2715 const tag_ty = maybe_tag_ty.?;
2716 const union_field_name = union_ty.field_names.get(ip)[active_field];
2717 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
2718 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
2719 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);
2720 break :blk tag_int_val.toUnsignedInt(mod);
2721 } else 0;
2722
2723 if (layout.payload_size == 0) {
2724 const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct);
2725 return try self.constInt(tag_ty_ref, tag_int);
2726 }
2727
2728 const un_active_ty_ref = try self.resolveUnionType(ty, active_field);
2729 const un_active_ptr_ty_ref = try self.spv.ptrType(un_active_ty_ref, .Function);
2730 const un_general_ty_ref = try self.resolveType(ty, .direct);
2731 const un_general_ptr_ty_ref = try self.spv.ptrType(un_general_ty_ref, .Function);
2732
2733 const tmp_id = self.spv.allocId();
2734 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
2735 .id_result_type = self.typeId(un_active_ptr_ty_ref),
2736 .id_result = tmp_id,
2737 .storage_class = .Function,
2738 });
2739
2740 if (layout.tag_size != 0) {
2741 const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct);
2742 const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, .Function);
2743 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
2744 const tag_id = try self.constInt(tag_ty_ref, tag_int);
2745 try self.func.body.emit(self.spv.gpa, .OpStore, .{
2746 .pointer = ptr_id,
2747 .object = tag_id,
2748 });
2749 }
2750
2751 if (layout.active_field_size != 0) {
2752 const active_field_ty_ref = try self.resolveType(layout.active_field_ty, .indirect);
2753 const active_field_ptr_ty_ref = try self.spv.ptrType(active_field_ty_ref, .Function);
2754 const ptr_id = try self.accessChain(active_field_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.active_field_index))});
2755 try self.func.body.emit(self.spv.gpa, .OpStore, .{
2756 .pointer = ptr_id,
2757 .object = payload.?,
2758 });
2759 } else {
2760 assert(payload == null);
2761 }
2762
2763 // Just leave the padding fields uninitialized...
2764 // TODO: Or should we initialize them with undef explicitly?
2765
2766 // Now cast the pointer and load it as the 'generic' union type.
2767
2768 const casted_var_id = self.spv.allocId();
2769 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
2770 .id_result_type = self.typeId(un_general_ptr_ty_ref),
2771 .id_result = casted_var_id,
2772 .operand = tmp_id,
2773 });
2774
2775 const result_id = self.spv.allocId();
2776 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
2777 .id_result_type = self.typeId(un_general_ty_ref),
2778 .id_result = result_id,
2779 .pointer = casted_var_id,
2780 });
2781
2782 return result_id;
2783 }
2784
2785 fn airUnionInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2786 if (self.liveness.isUnused(inst)) return null;
2787
2788 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2789 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
2790 const ty = self.typeOfIndex(inst);
2791 const layout = self.unionLayout(ty, extra.field_index);
2792
2793 const payload = if (layout.active_field_size != 0)
2794 try self.resolve(extra.init)
2795 else
2796 null;
2797 return try self.unionInit(ty, extra.field_index, payload);
26102798 }
26112799
26122800 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -2616,16 +2804,49 @@ pub const DeclGen = struct {
26162804 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
26172805 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
26182806
2619 const struct_ty = self.typeOf(struct_field.struct_operand);
2807 const object_ty = self.typeOf(struct_field.struct_operand);
26202808 const object_id = try self.resolve(struct_field.struct_operand);
26212809 const field_index = struct_field.field_index;
2622 const field_ty = struct_ty.structFieldType(field_index, mod);
2810 const field_ty = object_ty.structFieldType(field_index, mod);
26232811
26242812 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
26252813
2626 assert(struct_ty.zigTypeTag(mod) == .Struct); // Cannot do unions yet.
2627
2628 return try self.extractField(field_ty, object_id, field_index);
2814 switch (object_ty.zigTypeTag(mod)) {
2815 .Struct => switch (object_ty.containerLayout(mod)) {
2816 .Packed => unreachable, // TODO
2817 else => return try self.extractField(field_ty, object_id, field_index),
2818 },
2819 .Union => switch (object_ty.containerLayout(mod)) {
2820 .Packed => unreachable, // TODO
2821 else => {
2822 // Store, pointer-cast, load
2823 const un_general_ty_ref = try self.resolveType(object_ty, .indirect);
2824 const un_general_ptr_ty_ref = try self.spv.ptrType(un_general_ty_ref, .Function);
2825 const un_active_ty_ref = try self.resolveUnionType(object_ty, field_index);
2826 const un_active_ptr_ty_ref = try self.spv.ptrType(un_active_ty_ref, .Function);
2827 const field_ty_ref = try self.resolveType(field_ty, .indirect);
2828 const field_ptr_ty_ref = try self.spv.ptrType(field_ty_ref, .Function);
2829
2830 const tmp_id = self.spv.allocId();
2831 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
2832 .id_result_type = self.typeId(un_general_ptr_ty_ref),
2833 .id_result = tmp_id,
2834 .storage_class = .Function,
2835 });
2836 try self.store(object_ty, tmp_id, object_id, false);
2837 const casted_tmp_id = self.spv.allocId();
2838 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
2839 .id_result_type = self.typeId(un_active_ptr_ty_ref),
2840 .id_result = casted_tmp_id,
2841 .operand = tmp_id,
2842 });
2843 const layout = self.unionLayout(object_ty, field_index);
2844 const field_ptr_id = try self.accessChain(field_ptr_ty_ref, casted_tmp_id, &.{layout.active_field_index});
2845 return try self.load(field_ty, field_ptr_id, false);
2846 },
2847 },
2848 else => unreachable,
2849 }
26292850 }
26302851
26312852 fn structFieldPtr(
......@@ -2635,19 +2856,35 @@ pub const DeclGen = struct {
26352856 object_ptr: IdRef,
26362857 field_index: u32,
26372858 ) !?IdRef {
2859 const result_ty_ref = try self.resolveType(result_ptr_ty, .direct);
2860
26382861 const mod = self.module;
26392862 const object_ty = object_ptr_ty.childType(mod);
26402863 switch (object_ty.zigTypeTag(mod)) {
26412864 .Struct => switch (object_ty.containerLayout(mod)) {
26422865 .Packed => unreachable, // TODO
26432866 else => {
2644 const field_index_ty_ref = try self.intType(.unsigned, 32);
2645 const field_index_id = try self.spv.constInt(field_index_ty_ref, field_index);
2646 const result_ty_ref = try self.resolveType(result_ptr_ty, .direct);
2647 return try self.accessChain(result_ty_ref, object_ptr, &.{field_index_id});
2867 return try self.accessChain(result_ty_ref, object_ptr, &.{field_index});
26482868 },
26492869 },
2650 else => unreachable, // TODO
2870 .Union => switch (object_ty.containerLayout(mod)) {
2871 .Packed => unreachable, // TODO
2872 else => {
2873 const storage_class = spvStorageClass(object_ptr_ty.ptrAddressSpace(mod));
2874 const un_active_ty_ref = try self.resolveUnionType(object_ty, field_index);
2875 const un_active_ptr_ty_ref = try self.spv.ptrType(un_active_ty_ref, storage_class);
2876
2877 const casted_id = self.spv.allocId();
2878 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
2879 .id_result_type = self.typeId(un_active_ptr_ty_ref),
2880 .id_result = casted_id,
2881 .operand = object_ptr,
2882 });
2883 const layout = self.unionLayout(object_ty, field_index);
2884 return try self.accessChain(result_ty_ref, casted_id, &.{layout.active_field_index});
2885 },
2886 },
2887 else => unreachable,
26512888 }
26522889 }
26532890
......@@ -2726,50 +2963,50 @@ pub const DeclGen = struct {
27262963 }
27272964
27282965 fn airBlock(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2729 // In AIR, a block doesn't really define an entry point like a block, but more like a scope that breaks can jump out of and
2730 // "return" a value from. This cannot be directly modelled in SPIR-V, so in a block instruction, we're going to split up
2731 // the current block by first generating the code of the block, then a label, and then generate the rest of the current
2966 // In AIR, a block doesn't really define an entry point like a block, but
2967 // more like a scope that breaks can jump out of and "return" a value from.
2968 // This cannot be directly modelled in SPIR-V, so in a block instruction,
2969 // we're going to split up the current block by first generating the code
2970 // of the block, then a label, and then generate the rest of the current
27322971 // ir.Block in a different SPIR-V block.
27332972
27342973 const mod = self.module;
2735 const label_id = self.spv.allocId();
2736
2737 // 4 chosen as arbitrary initial capacity.
2738 var incoming_blocks = try std.ArrayListUnmanaged(IncomingBlock).initCapacity(self.gpa, 4);
2739
2740 try self.blocks.putNoClobber(self.gpa, inst, .{
2741 .label_id = label_id,
2742 .incoming_blocks = &incoming_blocks,
2743 });
2744 defer {
2745 assert(self.blocks.remove(inst));
2746 incoming_blocks.deinit(self.gpa);
2747 }
2748
27492974 const ty = self.typeOfIndex(inst);
27502975 const inst_datas = self.air.instructions.items(.data);
27512976 const extra = self.air.extraData(Air.Block, inst_datas[inst].ty_pl.payload);
27522977 const body = self.air.extra[extra.end..][0..extra.data.body_len];
2978 const have_block_result = ty.isFnOrHasRuntimeBitsIgnoreComptime(mod);
2979
2980 // 4 chosen as arbitrary initial capacity.
2981 var block = Block{
2982 // Label id is lazily allocated if needed.
2983 .label_id = null,
2984 .incoming_blocks = try std.ArrayListUnmanaged(IncomingBlock).initCapacity(self.gpa, 4),
2985 };
2986 defer block.incoming_blocks.deinit(self.gpa);
2987
2988 try self.blocks.putNoClobber(self.gpa, inst, &block);
2989 defer assert(self.blocks.remove(inst));
27532990
27542991 try self.genBody(body);
2755 try self.beginSpvBlock(label_id);
27562992
2757 // If this block didn't produce a value, simply return here.
2758 if (!ty.hasRuntimeBitsIgnoreComptime(mod))
2993 // Only begin a new block if there were actually any breaks towards it.
2994 if (block.label_id) |label_id| {
2995 try self.beginSpvBlock(label_id);
2996 }
2997
2998 if (!have_block_result)
27592999 return null;
27603000
2761 // Combine the result from the blocks using the Phi instruction.
3001 assert(block.label_id != null);
27623002 const result_id = self.spv.allocId();
2763
2764 // TODO: OpPhi is limited in the types that it may produce, such as pointers. Figure out which other types
2765 // are not allowed to be created from a phi node, and throw an error for those.
27663003 const result_type_id = try self.resolveTypeId(ty);
27673004
2768 try self.func.body.emitRaw(self.spv.gpa, .OpPhi, 2 + @as(u16, @intCast(incoming_blocks.items.len * 2))); // result type + result + variable/parent...
3005 try self.func.body.emitRaw(self.spv.gpa, .OpPhi, 2 + @as(u16, @intCast(block.incoming_blocks.items.len * 2))); // result type + result + variable/parent...
27693006 self.func.body.writeOperand(spec.IdResultType, result_type_id);
27703007 self.func.body.writeOperand(spec.IdRef, result_id);
27713008
2772 for (incoming_blocks.items) |incoming| {
3009 for (block.incoming_blocks.items) |incoming| {
27733010 self.func.body.writeOperand(spec.PairIdRefIdRef, .{ incoming.break_value_id, incoming.src_label_id });
27743011 }
27753012
......@@ -2778,17 +3015,24 @@ pub const DeclGen = struct {
27783015
27793016 fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void {
27803017 const br = self.air.instructions.items(.data)[inst].br;
2781 const block = self.blocks.get(br.block_inst).?;
27823018 const operand_ty = self.typeOf(br.operand);
3019 const block = self.blocks.get(br.block_inst).?;
27833020
27843021 const mod = self.module;
2785 if (operand_ty.hasRuntimeBits(mod)) {
3022 if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
27863023 const operand_id = try self.resolve(br.operand);
27873024 // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body.
2788 try block.incoming_blocks.append(self.gpa, .{ .src_label_id = self.current_block_label_id, .break_value_id = operand_id });
3025 try block.incoming_blocks.append(self.gpa, .{
3026 .src_label_id = self.current_block_label_id,
3027 .break_value_id = operand_id,
3028 });
27893029 }
27903030
2791 try self.func.body.emit(self.spv.gpa, .OpBranch, .{ .target_label = block.label_id });
3031 if (block.label_id == null) {
3032 block.label_id = self.spv.allocId();
3033 }
3034
3035 try self.func.body.emit(self.spv.gpa, .OpBranch, .{ .target_label = block.label_id.? });
27923036 }
27933037
27943038 fn airCondBr(self: *DeclGen, inst: Air.Inst.Index) !void {
......@@ -2817,44 +3061,25 @@ pub const DeclGen = struct {
28173061 try self.genBody(else_body);
28183062 }
28193063
2820 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
2821 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
2822 const src_fname_id = try self.spv.resolveSourceFileName(
2823 self.module,
2824 self.module.declPtr(self.decl_index),
2825 );
2826 try self.func.body.emit(self.spv.gpa, .OpLine, .{
2827 .file = src_fname_id,
2828 .line = dbg_stmt.line,
2829 .column = dbg_stmt.column,
2830 });
2831 }
2832
28333064 fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
28343065 const mod = self.module;
28353066 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
28363067 const ptr_ty = self.typeOf(ty_op.operand);
3068 const elem_ty = self.typeOfIndex(inst);
28373069 const operand = try self.resolve(ty_op.operand);
28383070 if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
28393071
2840 return try self.load(ptr_ty, operand);
3072 return try self.load(elem_ty, operand, ptr_ty.isVolatilePtr(mod));
28413073 }
28423074
28433075 fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void {
2844 const mod = self.module;
28453076 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
28463077 const ptr_ty = self.typeOf(bin_op.lhs);
3078 const elem_ty = ptr_ty.childType(self.module);
28473079 const ptr = try self.resolve(bin_op.lhs);
28483080 const value = try self.resolve(bin_op.rhs);
2849 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
28503081
2851 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
2852 if (val_is_undef) {
2853 const undef = try self.spv.constUndef(ptr_ty_ref);
2854 try self.store(ptr_ty, ptr, undef);
2855 } else {
2856 try self.store(ptr_ty, ptr, value);
2857 }
3082 try self.store(elem_ty, ptr, value, ptr_ty.isVolatilePtr(self.module));
28583083 }
28593084
28603085 fn airLoop(self: *DeclGen, inst: Air.Inst.Index) !void {
......@@ -2878,6 +3103,7 @@ pub const DeclGen = struct {
28783103 const operand_ty = self.typeOf(operand);
28793104 const mod = self.module;
28803105 if (operand_ty.hasRuntimeBits(mod)) {
3106 // TODO: If we return an empty struct, this branch is also hit incorrectly.
28813107 const operand_id = try self.resolve(operand);
28823108 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id });
28833109 } else {
......@@ -2897,7 +3123,7 @@ pub const DeclGen = struct {
28973123 }
28983124
28993125 const ptr = try self.resolve(un_op);
2900 const value = try self.load(ptr_ty, ptr);
3126 const value = try self.load(ret_ty, ptr, ptr_ty.isVolatilePtr(mod));
29013127 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{
29023128 .value = value,
29033129 });
......@@ -2924,7 +3150,7 @@ pub const DeclGen = struct {
29243150 else
29253151 err_union_id;
29263152
2927 const zero_id = try self.spv.constInt(err_ty_ref, 0);
3153 const zero_id = try self.constInt(err_ty_ref, 0);
29283154 const is_err_id = self.spv.allocId();
29293155 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
29303156 .id_result_type = self.typeId(bool_ty_ref),
......@@ -2988,6 +3214,21 @@ pub const DeclGen = struct {
29883214 return try self.extractField(Type.anyerror, operand_id, eu_layout.errorFieldIndex());
29893215 }
29903216
3217 fn airErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3218 if (self.liveness.isUnused(inst)) return null;
3219
3220 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3221 const operand_id = try self.resolve(ty_op.operand);
3222 const payload_ty = self.typeOfIndex(inst);
3223 const eu_layout = self.errorUnionLayout(payload_ty);
3224
3225 if (!eu_layout.payload_has_bits) {
3226 return null; // No error possible.
3227 }
3228
3229 return try self.extractField(payload_ty, operand_id, eu_layout.payloadFieldIndex());
3230 }
3231
29913232 fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
29923233 if (self.liveness.isUnused(inst)) return null;
29933234
......@@ -3003,20 +3244,35 @@ pub const DeclGen = struct {
30033244 }
30043245
30053246 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
3006 var members = std.BoundedArray(IdRef, 2){};
3007 const payload_id = try self.spv.constUndef(payload_ty_ref);
3008 if (eu_layout.error_first) {
3009 members.appendAssumeCapacity(operand_id);
3010 members.appendAssumeCapacity(payload_id);
3011 // TODO: ABI padding?
3012 } else {
3013 members.appendAssumeCapacity(payload_id);
3014 members.appendAssumeCapacity(operand_id);
3015 // TODO: ABI padding?
3247
3248 var members: [2]IdRef = undefined;
3249 members[eu_layout.errorFieldIndex()] = operand_id;
3250 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_ref);
3251
3252 const err_union_ty_ref = try self.resolveType(err_union_ty, .direct);
3253 return try self.constructStruct(err_union_ty_ref, &members);
3254 }
3255
3256 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3257 if (self.liveness.isUnused(inst)) return null;
3258
3259 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3260 const err_union_ty = self.typeOfIndex(inst);
3261 const operand_id = try self.resolve(ty_op.operand);
3262 const payload_ty = self.typeOf(ty_op.operand);
3263 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
3264 const eu_layout = self.errorUnionLayout(payload_ty);
3265
3266 if (!eu_layout.payload_has_bits) {
3267 return try self.constInt(err_ty_ref, 0);
30163268 }
30173269
3270 var members: [2]IdRef = undefined;
3271 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);
3272 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);
3273
30183274 const err_union_ty_ref = try self.resolveType(err_union_ty, .direct);
3019 return try self.constructStruct(err_union_ty_ref, members.slice());
3275 return try self.constructStruct(err_union_ty_ref, &members);
30203276 }
30213277
30223278 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {
......@@ -3081,6 +3337,42 @@ pub const DeclGen = struct {
30813337 };
30823338 }
30833339
3340 fn airIsErr(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err }) !?IdRef {
3341 if (self.liveness.isUnused(inst)) return null;
3342
3343 const mod = self.module;
3344 const un_op = self.air.instructions.items(.data)[inst].un_op;
3345 const operand_id = try self.resolve(un_op);
3346 const err_union_ty = self.typeOf(un_op);
3347
3348 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
3349 return try self.constBool(pred == .is_non_err, .direct);
3350 }
3351
3352 const payload_ty = err_union_ty.errorUnionPayload(mod);
3353 const eu_layout = self.errorUnionLayout(payload_ty);
3354 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
3355 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
3356
3357 const error_id = if (!eu_layout.payload_has_bits)
3358 operand_id
3359 else
3360 try self.extractField(Type.anyerror, operand_id, eu_layout.errorFieldIndex());
3361
3362 const result_id = self.spv.allocId();
3363 const operands = .{
3364 .id_result_type = self.typeId(bool_ty_ref),
3365 .id_result = result_id,
3366 .operand_1 = error_id,
3367 .operand_2 = try self.constInt(err_ty_ref, 0),
3368 };
3369 switch (pred) {
3370 .is_err => try self.func.body.emit(self.spv.gpa, .OpINotEqual, operands),
3371 .is_non_err => try self.func.body.emit(self.spv.gpa, .OpIEqual, operands),
3372 }
3373 return result_id;
3374 }
3375
30843376 fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
30853377 if (self.liveness.isUnused(inst)) return null;
30863378
......@@ -3238,6 +3530,40 @@ pub const DeclGen = struct {
32383530 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});
32393531 }
32403532
3533 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
3534 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
3535 const src_fname_id = try self.spv.resolveSourceFileName(
3536 self.module,
3537 self.module.declPtr(self.decl_index),
3538 );
3539 const base_line = self.base_line_stack.getLast();
3540 try self.func.body.emit(self.spv.gpa, .OpLine, .{
3541 .file = src_fname_id,
3542 .line = base_line + dbg_stmt.line + 1,
3543 .column = dbg_stmt.column + 1,
3544 });
3545 }
3546
3547 fn airDbgInlineBegin(self: *DeclGen, inst: Air.Inst.Index) !void {
3548 const mod = self.module;
3549 const fn_ty = self.air.instructions.items(.data)[inst].ty_fn;
3550 const decl_index = mod.funcInfo(fn_ty.func).owner_decl;
3551 const decl = mod.declPtr(decl_index);
3552 try self.base_line_stack.append(self.gpa, decl.src_line);
3553 }
3554
3555 fn airDbgInlineEnd(self: *DeclGen, inst: Air.Inst.Index) !void {
3556 _ = inst;
3557 _ = self.base_line_stack.pop();
3558 }
3559
3560 fn airDbgVar(self: *DeclGen, inst: Air.Inst.Index) !void {
3561 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3562 const target_id = try self.resolve(pl_op.operand);
3563 const name = self.air.nullTerminatedString(pl_op.payload);
3564 try self.spv.debugName(target_id, name);
3565 }
3566
32413567 fn airAssembly(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
32423568 const mod = self.module;
32433569 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
src/codegen/spirv/Cache.zig+6-6
......@@ -462,11 +462,11 @@ fn emit(
462462 switch (key) {
463463 .void_type => {
464464 try section.emit(spv.gpa, .OpTypeVoid, .{ .id_result = result_id });
465 try spv.debugName(result_id, "void", .{});
465 try spv.debugName(result_id, "void");
466466 },
467467 .bool_type => {
468468 try section.emit(spv.gpa, .OpTypeBool, .{ .id_result = result_id });
469 try spv.debugName(result_id, "bool", .{});
469 try spv.debugName(result_id, "bool");
470470 },
471471 .int_type => |int| {
472472 try section.emit(spv.gpa, .OpTypeInt, .{
......@@ -481,14 +481,14 @@ fn emit(
481481 .unsigned => "u",
482482 .signed => "i",
483483 };
484 try spv.debugName(result_id, "{s}{}", .{ ui, int.bits });
484 try spv.debugNameFmt(result_id, "{s}{}", .{ ui, int.bits });
485485 },
486486 .float_type => |float| {
487487 try section.emit(spv.gpa, .OpTypeFloat, .{
488488 .id_result = result_id,
489489 .width = float.bits,
490490 });
491 try spv.debugName(result_id, "f{}", .{float.bits});
491 try spv.debugNameFmt(result_id, "f{}", .{float.bits});
492492 },
493493 .vector_type => |vector| {
494494 try section.emit(spv.gpa, .OpTypeVector, .{
......@@ -530,11 +530,11 @@ fn emit(
530530 section.writeOperand(IdResult, self.resultId(member_type));
531531 }
532532 if (self.getString(struct_type.name)) |name| {
533 try spv.debugName(result_id, "{s}", .{name});
533 try spv.debugName(result_id, name);
534534 }
535535 for (struct_type.memberNames(), 0..) |member_name, i| {
536536 if (self.getString(member_name)) |name| {
537 try spv.memberDebugName(result_id, @as(u32, @intCast(i)), "{s}", .{name});
537 try spv.memberDebugName(result_id, @as(u32, @intCast(i)), name);
538538 }
539539 }
540540 // TODO: Decorations?
src/codegen/spirv/Module.zig+101-20
......@@ -94,6 +94,8 @@ pub const Global = struct {
9494 begin_inst: u32,
9595 /// The past-end offset into `self.flobals.section`.
9696 end_inst: u32,
97 /// The result-id of the function that initializes this value.
98 initializer_id: IdRef,
9799};
98100
99101/// This models a kernel entry point.
......@@ -284,6 +286,10 @@ fn addEntryPointDeps(
284286 const decl = self.declPtr(decl_index);
285287 const deps = self.decl_deps.items[decl.begin_dep..decl.end_dep];
286288
289 if (seen.isSet(@intFromEnum(decl_index))) {
290 return;
291 }
292
287293 seen.set(@intFromEnum(decl_index));
288294
289295 if (self.globalPtr(decl_index)) |global| {
......@@ -291,9 +297,7 @@ fn addEntryPointDeps(
291297 }
292298
293299 for (deps) |dep| {
294 if (!seen.isSet(@intFromEnum(dep))) {
295 try self.addEntryPointDeps(dep, seen, interface);
296 }
300 try self.addEntryPointDeps(dep, seen, interface);
297301 }
298302}
299303
......@@ -325,20 +329,76 @@ fn entryPoints(self: *Module) !Section {
325329 return entry_points;
326330}
327331
332/// Generate a function that calls all initialization functions,
333/// in unspecified order (an order should not be required here).
334/// It generated as follows:
335/// %init = OpFunction %void None
336/// foreach %initializer:
337/// OpFunctionCall %initializer
338/// OpReturn
339/// OpFunctionEnd
340fn initializer(self: *Module, entry_points: *Section) !Section {
341 var section = Section{};
342 errdefer section.deinit(self.gpa);
343
344 // const void_ty_ref = try self.resolveType(Type.void, .direct);
345 const void_ty_ref = try self.resolve(.void_type);
346 const void_ty_id = self.resultId(void_ty_ref);
347 const init_proto_ty_ref = try self.resolve(.{ .function_type = .{
348 .return_type = void_ty_ref,
349 .parameters = &.{},
350 } });
351
352 const init_id = self.allocId();
353 try section.emit(self.gpa, .OpFunction, .{
354 .id_result_type = void_ty_id,
355 .id_result = init_id,
356 .function_control = .{},
357 .function_type = self.resultId(init_proto_ty_ref),
358 });
359 try section.emit(self.gpa, .OpLabel, .{
360 .id_result = self.allocId(),
361 });
362
363 var seen = try std.DynamicBitSetUnmanaged.initEmpty(self.gpa, self.decls.items.len);
364 defer seen.deinit(self.gpa);
365
366 var interface = std.ArrayList(IdRef).init(self.gpa);
367 defer interface.deinit();
368
369 for (self.globals.globals.keys(), self.globals.globals.values()) |decl_index, global| {
370 try self.addEntryPointDeps(decl_index, &seen, &interface);
371 try section.emit(self.gpa, .OpFunctionCall, .{
372 .id_result_type = void_ty_id,
373 .id_result = self.allocId(),
374 .function = global.initializer_id,
375 });
376 }
377
378 try section.emit(self.gpa, .OpReturn, {});
379 try section.emit(self.gpa, .OpFunctionEnd, {});
380
381 try entry_points.emit(self.gpa, .OpEntryPoint, .{
382 // TODO: Rusticl does not support this because its poorly defined.
383 // Do we need to generate a workaround here?
384 .execution_model = .Kernel,
385 .entry_point = init_id,
386 .name = "zig global initializer",
387 .interface = interface.items,
388 });
389
390 try self.sections.execution_modes.emit(self.gpa, .OpExecutionMode, .{
391 .entry_point = init_id,
392 .mode = .Initializer,
393 });
394
395 return section;
396}
397
328398/// Emit this module as a spir-v binary.
329399pub fn flush(self: *Module, file: std.fs.File) !void {
330400 // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction"
331401
332 const header = [_]Word{
333 spec.magic_number,
334 // TODO: From cpu features
335 // Emit SPIR-V 1.4 for now. This is the highest version that Intel's CPU OpenCL supports.
336 (1 << 16) | (4 << 8),
337 0, // TODO: Register Zig compiler magic number.
338 self.idBound(),
339 0, // Schema (currently reserved for future use)
340 };
341
342402 // TODO: Perform topological sort on the globals.
343403 var globals = try self.orderGlobals();
344404 defer globals.deinit(self.gpa);
......@@ -349,6 +409,19 @@ pub fn flush(self: *Module, file: std.fs.File) !void {
349409 var types_constants = try self.cache.materialize(self);
350410 defer types_constants.deinit(self.gpa);
351411
412 var init_func = try self.initializer(&entry_points);
413 defer init_func.deinit(self.gpa);
414
415 const header = [_]Word{
416 spec.magic_number,
417 // TODO: From cpu features
418 // Emit SPIR-V 1.4 for now. This is the highest version that Intel's CPU OpenCL supports.
419 (1 << 16) | (4 << 8),
420 0, // TODO: Register Zig compiler magic number.
421 self.idBound(),
422 0, // Schema (currently reserved for future use)
423 };
424
352425 // Note: needs to be kept in order according to section 2.3!
353426 const buffers = &[_][]const Word{
354427 &header,
......@@ -363,6 +436,7 @@ pub fn flush(self: *Module, file: std.fs.File) !void {
363436 self.sections.types_globals_constants.toWords(),
364437 globals.toWords(),
365438 self.sections.functions.toWords(),
439 init_func.toWords(),
366440 };
367441
368442 var iovc_buffers: [buffers.len]std.os.iovec_const = undefined;
......@@ -524,6 +598,7 @@ pub fn allocDecl(self: *Module, kind: DeclKind) !Decl.Index {
524598 .result_id = undefined,
525599 .begin_inst = undefined,
526600 .end_inst = undefined,
601 .initializer_id = undefined,
527602 }),
528603 }
529604
......@@ -553,10 +628,14 @@ pub fn beginGlobal(self: *Module) u32 {
553628 return @as(u32, @intCast(self.globals.section.instructions.items.len));
554629}
555630
556pub fn endGlobal(self: *Module, global_index: Decl.Index, begin_inst: u32) void {
631pub fn endGlobal(self: *Module, global_index: Decl.Index, begin_inst: u32, result_id: IdRef, initializer_id: IdRef) void {
557632 const global = self.globalPtr(global_index).?;
558 global.begin_inst = begin_inst;
559 global.end_inst = @as(u32, @intCast(self.globals.section.instructions.items.len));
633 global.* = .{
634 .result_id = result_id,
635 .begin_inst = begin_inst,
636 .end_inst = @intCast(self.globals.section.instructions.items.len),
637 .initializer_id = initializer_id,
638 };
560639}
561640
562641pub fn declareEntryPoint(self: *Module, decl_index: Decl.Index, name: []const u8) !void {
......@@ -566,18 +645,20 @@ pub fn declareEntryPoint(self: *Module, decl_index: Decl.Index, name: []const u8
566645 });
567646}
568647
569pub fn debugName(self: *Module, target: IdResult, comptime fmt: []const u8, args: anytype) !void {
570 const name = try std.fmt.allocPrint(self.gpa, fmt, args);
571 defer self.gpa.free(name);
648pub fn debugName(self: *Module, target: IdResult, name: []const u8) !void {
572649 try self.sections.debug_names.emit(self.gpa, .OpName, .{
573650 .target = target,
574651 .name = name,
575652 });
576653}
577654
578pub fn memberDebugName(self: *Module, target: IdResult, member: u32, comptime fmt: []const u8, args: anytype) !void {
655pub fn debugNameFmt(self: *Module, target: IdResult, comptime fmt: []const u8, args: anytype) !void {
579656 const name = try std.fmt.allocPrint(self.gpa, fmt, args);
580657 defer self.gpa.free(name);
658 try self.debugName(target, name);
659}
660
661pub fn memberDebugName(self: *Module, target: IdResult, member: u32, name: []const u8) !void {
581662 try self.sections.debug_names.emit(self.gpa, .OpMemberName, .{
582663 .type = target,
583664 .member = member,
src/link/SpirV.zig+6-1
......@@ -110,6 +110,8 @@ pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, a
110110 }
111111
112112 const func = module.funcInfo(func_index);
113 const decl = module.declPtr(func.owner_decl);
114 log.debug("lowering function {s}", .{module.intern_pool.stringToSlice(decl.name)});
113115
114116 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
115117 defer decl_gen.deinit();
......@@ -124,6 +126,9 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index)
124126 @panic("Attempted to compile for architecture that was disabled by build configuration");
125127 }
126128
129 const decl = module.declPtr(decl_index);
130 log.debug("lowering declaration {s}", .{module.intern_pool.stringToSlice(decl.name)});
131
127132 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
128133 defer decl_gen.deinit();
129134
......@@ -212,7 +217,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
212217fn writeCapabilities(spv: *SpvModule, target: std.Target) !void {
213218 // TODO: Integrate with a hypothetical feature system
214219 const caps: []const spec.Capability = switch (target.os.tag) {
215 .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .GenericPointer },
220 .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .GenericPointer },
216221 .glsl450 => &.{.Shader},
217222 .vulkan => &.{.Shader},
218223 else => unreachable, // TODO
test/behavior/array.zig+2-21
......@@ -21,7 +21,6 @@ test "arrays" {
2121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2524
2625 var array: [5]u32 = undefined;
2726
......@@ -49,7 +48,6 @@ fn getArrayLen(a: []const u32) usize {
4948test "array concat with undefined" {
5049 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5351
5452 const S = struct {
5553 fn doTheTest() !void {
......@@ -89,7 +87,6 @@ test "array concat with tuple" {
8987
9088test "array init with concat" {
9189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
92 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
9390
9491 const a = 'a';
9592 var i: [4]u8 = [2]u8{ a, 'b' } ++ [2]u8{ 'c', 'd' };
......@@ -99,7 +96,6 @@ test "array init with concat" {
9996test "array init with mult" {
10097 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10198 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10399
104100 const a = 'a';
105101 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
......@@ -141,7 +137,6 @@ test "array literal with specified size" {
141137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
142138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
143139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
145140
146141 var array = [2]u8{ 1, 2 };
147142 try expect(array[0] == 1);
......@@ -163,7 +158,6 @@ test "array len field" {
163158test "array with sentinels" {
164159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
165160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
167161
168162 const S = struct {
169163 fn doTheTest(is_ct: bool) !void {
......@@ -201,7 +195,6 @@ test "nested arrays of strings" {
201195 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
202196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
203197 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
205198
206199 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
207200 for (array_of_strings, 0..) |s, i| {
......@@ -231,7 +224,6 @@ test "nested arrays of integers" {
231224test "implicit comptime in array type size" {
232225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
233226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
235227
236228 var arr: [plusOne(10)]bool = undefined;
237229 try expect(arr.len == 11);
......@@ -244,7 +236,6 @@ fn plusOne(x: u32) u32 {
244236test "single-item pointer to array indexing and slicing" {
245237 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
246238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
248239
249240 try testSingleItemPtrArrayIndexSlice();
250241 try comptime testSingleItemPtrArrayIndexSlice();
......@@ -288,7 +279,6 @@ test "anonymous list literal syntax" {
288279 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
289280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
290281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
291 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
292282
293283 const S = struct {
294284 fn doTheTest() !void {
......@@ -326,7 +316,6 @@ test "read/write through global variable array of struct fields initialized via
326316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
327317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
328318 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
330319
331320 const S = struct {
332321 fn doTheTest() !void {
......@@ -366,7 +355,6 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {
366355test "comptime evaluating function that takes array by value" {
367356 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
368357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
370358
371359 const arr = [_]u8{ 1, 2 };
372360 const x = comptime testArrayByValAtComptime(arr);
......@@ -378,7 +366,6 @@ test "comptime evaluating function that takes array by value" {
378366test "runtime initialize array elem and then implicit cast to slice" {
379367 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380368 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
382369
383370 var two: i32 = 2;
384371 const x: []const i32 = &[_]i32{two};
......@@ -388,7 +375,6 @@ test "runtime initialize array elem and then implicit cast to slice" {
388375test "array literal as argument to function" {
389376 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
390377 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
391 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
392378
393379 const S = struct {
394380 fn entry(two: i32) !void {
......@@ -417,7 +403,6 @@ test "double nested array to const slice cast in array literal" {
417403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
418404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
419405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
420 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
421406
422407 const S = struct {
423408 fn entry(two: i32) !void {
......@@ -479,7 +464,6 @@ test "anonymous literal in array" {
479464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
480465 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
481466 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
482 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
483467
484468 const S = struct {
485469 const Foo = struct {
......@@ -504,7 +488,6 @@ test "anonymous literal in array" {
504488test "access the null element of a null terminated array" {
505489 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
506490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
508491
509492 const S = struct {
510493 fn doTheTest() !void {
......@@ -522,7 +505,6 @@ test "type deduction for array subscript expression" {
522505 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
523506 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
524507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
526508
527509 const S = struct {
528510 fn doTheTest() !void {
......@@ -620,7 +602,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {
620602 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
621603 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
622604 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
623 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
624605
625606 const S = struct {
626607 const U = union {
......@@ -659,7 +640,6 @@ test "tuple to array handles sentinel" {
659640 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
660641 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
661642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
662 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
663643
664644 const S = struct {
665645 const a = .{ 1, 2, 3 };
......@@ -703,7 +683,6 @@ test "array of array agregate init" {
703683 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
704684 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
705685 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
707686
708687 var a = [1]u32{11} ** 10;
709688 var b = [1][10]u32{a} ** 2;
......@@ -777,6 +756,8 @@ test "array init with no result pointer sets field result types" {
777756}
778757
779758test "runtime side-effects in comptime-known array init" {
759 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
760
780761 var side_effects: u4 = 0;
781762 const init = [4]u4{
782763 blk: {
test/behavior/basic.zig+1-8
......@@ -330,7 +330,6 @@ const FnPtrWrapper = struct {
330330
331331test "const ptr from var variable" {
332332 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
333 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
334333
335334 var x: u64 = undefined;
336335 var y: u64 = undefined;
......@@ -581,7 +580,7 @@ test "comptime cast fn to ptr" {
581580}
582581
583582test "equality compare fn ptrs" {
584 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // Test passes but should not
583 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
585584
586585 var a = &emptyFn;
587586 try expect(a == a);
......@@ -607,7 +606,6 @@ test "self reference through fn ptr field" {
607606
608607test "global variable initialized to global variable array element" {
609608 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
610 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
611609
612610 try expect(global_ptr == &gdt[0]);
613611}
......@@ -639,7 +637,6 @@ test "global constant is loaded with a runtime-known index" {
639637
640638test "multiline string literal is null terminated" {
641639 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
642 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
643640
644641 const s1 =
645642 \\one
......@@ -711,7 +708,6 @@ test "comptime manyptr concatenation" {
711708 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
712709 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
713710 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
714 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
715711
716712 const s = "epic";
717713 const actual = manyptrConcat(s);
......@@ -1027,7 +1023,6 @@ comptime {
10271023
10281024test "switch inside @as gets correct type" {
10291025 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1030 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10311026
10321027 var a: u32 = 0;
10331028 var b: [2]u32 = undefined;
......@@ -1136,8 +1131,6 @@ test "orelse coercion as function argument" {
11361131}
11371132
11381133test "runtime-known globals initialized with undefined" {
1139 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1140
11411134 const S = struct {
11421135 var array: [10]u32 = [_]u32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
11431136 var vp: [*]u32 = undefined;
test/behavior/bitcast.zig+4
......@@ -271,6 +271,8 @@ test "comptime bitcast used in expression has the correct type" {
271271}
272272
273273test "bitcast passed as tuple element" {
274 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
275
274276 const S = struct {
275277 fn foo(args: anytype) !void {
276278 try comptime expect(@TypeOf(args[0]) == f32);
......@@ -281,6 +283,8 @@ test "bitcast passed as tuple element" {
281283}
282284
283285test "triple level result location with bitcast sandwich passed as tuple element" {
286 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
287
284288 const S = struct {
285289 fn foo(args: anytype) !void {
286290 try comptime expect(@TypeOf(args[0]) == f64);
test/behavior/bugs/10138.zig-1
......@@ -5,7 +5,6 @@ test "registers get overwritten when ignoring return" {
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
77 if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .linux) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
98
109 const fd = open();
1110 _ = write(fd, "a", 1);
test/behavior/bugs/10970.zig-1
......@@ -7,7 +7,6 @@ test "breaking from a loop in an if statement" {
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1110
1211 var cond = true;
1312 const opt = while (cond) {
test/behavior/bugs/11100.zig-2
......@@ -9,7 +9,5 @@ pub fn do() bool {
99}
1010
1111test "bug" {
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13
1412 try std.testing.expect(!do());
1513}
test/behavior/bugs/11165.zig-2
......@@ -2,7 +2,6 @@ const builtin = @import("builtin");
22
33test "bytes" {
44 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
65
76 const S = struct {
87 a: u32,
......@@ -24,7 +23,6 @@ test "bytes" {
2423
2524test "aggregate" {
2625 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2826
2927 const S = struct {
3028 a: u32,
test/behavior/bugs/11816.zig-1
......@@ -4,7 +4,6 @@ const builtin = @import("builtin");
44test {
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
87
98 var x: u32 = 3;
109 const val: usize = while (true) switch (x) {
test/behavior/bugs/12025.zig-2
......@@ -1,8 +1,6 @@
11const builtin = @import("builtin");
22
33test {
4 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5
64 comptime var st = .{
75 .foo = &1,
86 .bar = &2,
test/behavior/bugs/12033.zig-2
......@@ -2,8 +2,6 @@ const std = @import("std");
22const builtin = @import("builtin");
33
44test {
5 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6
75 const string = "Hello!\x00World!";
86 try std.testing.expect(@TypeOf(string) == *const [13:0]u8);
97
test/behavior/bugs/12043.zig-2
......@@ -7,8 +7,6 @@ fn foo(x: anytype) void {
77 ok = x;
88}
99test {
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11
1210 const x = &foo;
1311 x(true);
1412 try expect(ok);
test/behavior/bugs/12119.zig-1
......@@ -9,7 +9,6 @@ test {
99 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1312
1413 const zerox32: u8x32 = [_]u8{0} ** 32;
1514 const bigsum: u32x8 = @as(u32x8, @bitCast(zerox32));
test/behavior/bugs/12891.zig-8
......@@ -7,29 +7,21 @@ test "issue12891" {
77 try std.testing.expect(i < f);
88}
99test "nan" {
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11
1210 const f = comptime std.math.nan(f64);
1311 var i: usize = 0;
1412 try std.testing.expect(!(f < i));
1513}
1614test "inf" {
17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
18
1915 const f = comptime std.math.inf(f64);
2016 var i: usize = 0;
2117 try std.testing.expect(f > i);
2218}
2319test "-inf < 0" {
24 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
25
2620 const f = comptime -std.math.inf(f64);
2721 var i: usize = 0;
2822 try std.testing.expect(f < i);
2923}
3024test "inf >= 1" {
31 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
32
3325 const f = comptime std.math.inf(f64);
3426 var i: usize = 1;
3527 try std.testing.expect(f >= i);
test/behavior/bugs/12928.zig-4
......@@ -11,8 +11,6 @@ const B = extern struct {
1111};
1212
1313test {
14 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15
1614 var a: *A = undefined;
1715 try expect(@TypeOf(&a.value.a) == *volatile u32);
1816 try expect(@TypeOf(&a.value.b) == *volatile i32);
......@@ -26,8 +24,6 @@ const D = extern union {
2624 b: i32,
2725};
2826test {
29 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
30
3127 var c: *C = undefined;
3228 try expect(@TypeOf(&c.value.a) == *volatile u32);
3329 try expect(@TypeOf(&c.value.b) == *volatile i32);
test/behavior/bugs/12984.zig-1
......@@ -14,7 +14,6 @@ pub const CustomDraw = DeleagateWithContext(fn (?OnConfirm) void);
1414test "simple test" {
1515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1616 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1817
1918 var c: CustomDraw = undefined;
2019 _ = c;
test/behavior/bugs/13113.zig-1
......@@ -10,7 +10,6 @@ test {
1010 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1212 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1413
1514 const foo = Foo{
1615 .a = 1,
test/behavior/bugs/13159.zig-1
......@@ -11,7 +11,6 @@ const Bar = packed struct {
1111
1212test {
1313 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1514
1615 var foo = Bar.Baz.fizz;
1716 try expect(foo == .fizz);
test/behavior/bugs/13285.zig-1
......@@ -6,7 +6,6 @@ const Crasher = struct {
66
77test {
88 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
109
1110 var a: Crasher = undefined;
1211 var crasher_ptr = &a;
test/behavior/bugs/14854.zig-2
......@@ -2,8 +2,6 @@ const testing = @import("std").testing;
22const builtin = @import("builtin");
33
44test {
5 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6
75 try testing.expect(getGeneric(u8, getU8) == 123);
86}
97
test/behavior/bugs/1500.zig-2
......@@ -6,8 +6,6 @@ const A = struct {
66const B = *const fn (A) void;
77
88test "allow these dependencies" {
9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10
119 var a: A = undefined;
1210 var b: B = undefined;
1311 if (false) {
test/behavior/bugs/15778.zig-2
......@@ -6,7 +6,6 @@ test {
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
109 const a = @Vector(0, i32){};
1110 const b = @Vector(0, i32){};
1211 _ = a + b;
......@@ -18,7 +17,6 @@ test {
1817 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
2019 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2220 const a = @Vector(0, f32){};
2321 const b = @Vector(0, f32){};
2422 _ = a - b;
test/behavior/bugs/2622.zig-1
......@@ -7,7 +7,6 @@ test "reslice of undefined global var slice" {
77 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1110
1211 var mem: [100]u8 = [_]u8{0} ** 100;
1312 buf = &mem;
test/behavior/bugs/3779.zig-2
......@@ -8,7 +8,6 @@ const ptr_tag_name: [*:0]const u8 = tag_name;
88test "@tagName() returns a string literal" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1211
1312 try std.testing.expect(*const [13:0]u8 == @TypeOf(tag_name));
1413 try std.testing.expect(std.mem.eql(u8, "TestEnumValue", tag_name));
......@@ -22,7 +21,6 @@ const ptr_error_name: [*:0]const u8 = error_name;
2221test "@errorName() returns a string literal" {
2322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2423 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2624
2725 try std.testing.expect(*const [13:0]u8 == @TypeOf(error_name));
2826 try std.testing.expect(std.mem.eql(u8, "TestErrorCode", error_name));
test/behavior/bugs/4954.zig-1
......@@ -8,7 +8,6 @@ test "crash" {
88 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1211
1312 var buf: [4096]u8 = undefined;
1413 f(&buf);
test/behavior/bugs/5398.zig-1
......@@ -22,7 +22,6 @@ test "assignment of field with padding" {
2222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2424 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2625
2726 renderable = Renderable{
2827 .mesh = Mesh{ .id = 0 },
test/behavior/bugs/5487.zig+1
......@@ -13,5 +13,6 @@ test "crash" {
1313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1617 _ = io.multiWriter(.{writer()});
1718}
test/behavior/bugs/6456.zig-1
......@@ -13,7 +13,6 @@ const text =
1313test "issue 6456" {
1414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1716
1817 comptime {
1918 var fields: []const StructField = &[0]StructField{};
test/behavior/bugs/656.zig-1
......@@ -14,7 +14,6 @@ test "optional if after an if in a switch prong of a switch with 2 prongs in an
1414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1616 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1817
1918 try foo(false, true);
2019}
test/behavior/bugs/7047.zig-2
......@@ -15,8 +15,6 @@ fn S(comptime query: U) type {
1515}
1616
1717test "compiler doesn't consider equal unions with different 'type' payload" {
18 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
19
2018 const s1 = S(U{ .T = u32 }).tag();
2119 try std.testing.expectEqual(u32, s1);
2220
test/behavior/bugs/7187.zig-2
......@@ -3,8 +3,6 @@ const builtin = @import("builtin");
33const expect = std.testing.expect;
44
55test "miscompilation with bool return type" {
6 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
7
86 var x: usize = 1;
97 var y: bool = getFalse();
108 _ = y;
test/behavior/bugs/8277.zig-2
......@@ -2,8 +2,6 @@ const std = @import("std");
22const builtin = @import("builtin");
33
44test "@sizeOf reified union zero-size payload fields" {
5 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6
75 comptime {
86 try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union {}))));
97 try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void }))));
test/behavior/bugs/828.zig-1
......@@ -31,7 +31,6 @@ fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
3131
3232test "comptime struct return should not return the same instance" {
3333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3534
3635 //the first parameter must be passed by reference to trigger the bug
3736 //a second parameter is required to trigger the bug
test/behavior/byval_arg_var.zig-1
......@@ -5,7 +5,6 @@ var result: []const u8 = "wrong";
55
66test "pass string literal byvalue to a generic var param" {
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
98
109 start();
1110 blowUpStack(10);
test/behavior/call.zig-1
......@@ -334,7 +334,6 @@ test "inline call preserves tail call" {
334334test "inline call doesn't re-evaluate non generic struct" {
335335 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
336336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
338337
339338 const S = struct {
340339 fn foo(f: struct { a: u8, b: u8 }) !void {
test/behavior/call_tail.zig+1
......@@ -46,6 +46,7 @@ test "arguments pointed to on stack into tailcall" {
4646 }
4747 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
4848 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
4950
5051 var data = [_]u64{ 1, 6, 2, 7, 1, 9, 3 };
5152 base = @intFromPtr(&data);
test/behavior/cast.zig+2-35
......@@ -403,7 +403,6 @@ test "peer type unsigned int to signed" {
403403test "expected [*c]const u8, found [*:0]const u8" {
404404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
405405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
407406
408407 var a: [*:0]const u8 = "hello";
409408 var b: [*c]const u8 = a;
......@@ -445,7 +444,6 @@ test "implicitly cast from T to anyerror!?T" {
445444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
446445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
447446 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
449447
450448 try castToOptionalTypeError(1);
451449 try comptime castToOptionalTypeError(1);
......@@ -521,7 +519,6 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
521519test "implicit cast from *const [N]T to []const T" {
522520 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
523521 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
525522
526523 try testCastConstArrayRefToConstSlice();
527524 try comptime testCastConstArrayRefToConstSlice();
......@@ -547,7 +544,6 @@ fn testCastConstArrayRefToConstSlice() !void {
547544test "peer type resolution: error and [N]T" {
548545 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
549546 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
551547
552548 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
553549 try comptime expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
......@@ -709,7 +705,6 @@ test "peer type resolution: error set supersets" {
709705 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
710706 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
711707 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
712 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
713708
714709 const a: error{ One, Two } = undefined;
715710 const b: error{One} = undefined;
......@@ -739,7 +734,6 @@ test "peer type resolution: disjoint error sets" {
739734 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
740735 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
741736 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
742 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
743737
744738 const a: error{ One, Two } = undefined;
745739 const b: error{Three} = undefined;
......@@ -769,7 +763,6 @@ test "peer type resolution: error union and error set" {
769763 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
770764 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
771765 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
772 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
773766
774767 const a: error{Three} = undefined;
775768 const b: error{ One, Two }!u32 = undefined;
......@@ -803,7 +796,6 @@ test "peer type resolution: error union after non-error" {
803796 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
804797 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
805798 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
806 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
807799
808800 const a: u32 = undefined;
809801 const b: error{ One, Two }!u32 = undefined;
......@@ -863,7 +855,6 @@ test "peer cast *[0]T to []const T" {
863855
864856test "peer cast *[N]T to [*]T" {
865857 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
866 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
867858
868859 var array = [4:99]i32{ 1, 2, 3, 4 };
869860 var dest: [*]i32 = undefined;
......@@ -930,7 +921,6 @@ test "peer cast [N:x]T to [N]T" {
930921test "peer cast *[N:x]T to *[N]T" {
931922 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
932923 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
933 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
934924
935925 const S = struct {
936926 fn doTheTest() !void {
......@@ -946,7 +936,6 @@ test "peer cast *[N:x]T to *[N]T" {
946936test "peer cast [*:x]T to [*]T" {
947937 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
948938 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
949 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
950939
951940 const S = struct {
952941 fn doTheTest() !void {
......@@ -967,7 +956,6 @@ test "peer cast [:x]T to [*:x]T" {
967956 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
968957 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
969958 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
970 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
971959
972960 const S = struct {
973961 fn doTheTest() !void {
......@@ -988,7 +976,6 @@ test "peer cast [:x]T to [*:x]T" {
988976test "peer type resolution implicit cast to return type" {
989977 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
990978 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
991 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
992979
993980 const S = struct {
994981 fn doTheTest() !void {
......@@ -1009,7 +996,6 @@ test "peer type resolution implicit cast to return type" {
1009996test "peer type resolution implicit cast to variable type" {
1010997 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1011998 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1012 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1013999
10141000 const S = struct {
10151001 fn doTheTest() !void {
......@@ -1034,7 +1020,6 @@ test "variable initialization uses result locations properly with regards to the
10341020test "cast between C pointer with different but compatible types" {
10351021 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10361022 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1037 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10381023
10391024 const S = struct {
10401025 fn foo(arg: [*]c_ushort) u16 {
......@@ -1052,7 +1037,6 @@ test "cast between C pointer with different but compatible types" {
10521037test "peer type resolve string lit with sentinel-terminated mutable slice" {
10531038 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10541039 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1055 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10561040
10571041 var array: [4:0]u8 = undefined;
10581042 array[4] = 0; // TODO remove this when #4372 is solved
......@@ -1062,8 +1046,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" {
10621046}
10631047
10641048test "peer type resolve array pointers, one of them const" {
1065 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1066
10671049 var array1: [4]u8 = undefined;
10681050 const array2: [5]u8 = undefined;
10691051 try comptime expect(@TypeOf(&array1, &array2) == []const u8);
......@@ -1071,8 +1053,6 @@ test "peer type resolve array pointers, one of them const" {
10711053}
10721054
10731055test "peer type resolve array pointer and unknown pointer" {
1074 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1075
10761056 const const_array: [4]u8 = undefined;
10771057 var array: [4]u8 = undefined;
10781058 var const_ptr: [*]const u8 = undefined;
......@@ -1092,8 +1072,6 @@ test "peer type resolve array pointer and unknown pointer" {
10921072}
10931073
10941074test "comptime float casts" {
1095 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1096
10971075 const a = @as(comptime_float, @floatFromInt(1));
10981076 try expect(a == 1);
10991077 try expect(@TypeOf(a) == comptime_float);
......@@ -1140,8 +1118,6 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void {
11401118}
11411119
11421120test "compile time int to ptr of function" {
1143 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1144
11451121 try foobar(FUNCTION_CONSTANT);
11461122}
11471123
......@@ -1156,6 +1132,7 @@ fn foobar(func: PFN_void) !void {
11561132
11571133test "cast function with an opaque parameter" {
11581134 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1135 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11591136
11601137 if (builtin.zig_backend == .stage2_c) {
11611138 // https://github.com/ziglang/zig/issues/16845
......@@ -1340,8 +1317,6 @@ test "*const [N]null u8 to ?[]const u8" {
13401317}
13411318
13421319test "cast between [*c]T and ?[*:0]T on fn parameter" {
1343 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1344
13451320 const S = struct {
13461321 const Handler = ?fn ([*c]const u8) callconv(.C) void;
13471322 fn addCallback(comptime handler: Handler) void {
......@@ -1381,7 +1356,6 @@ test "cast between *[N]void and []void" {
13811356test "peer resolve arrays of different size to const slice" {
13821357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
13831358 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1384 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13851359
13861360 try expect(mem.eql(u8, boolToStr(true), "true"));
13871361 try expect(mem.eql(u8, boolToStr(false), "false"));
......@@ -1485,7 +1459,6 @@ test "cast compatible optional types" {
14851459test "coerce undefined single-item pointer of array to error union of slice" {
14861460 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14871461 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1488 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14891462
14901463 const a = @as([*]u8, undefined)[0..0];
14911464 var b: error{a}![]const u8 = a;
......@@ -1495,7 +1468,6 @@ test "coerce undefined single-item pointer of array to error union of slice" {
14951468
14961469test "pointer to empty struct literal to mutable slice" {
14971470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1498 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14991471
15001472 var x: []i32 = &.{};
15011473 try expect(x.len == 0);
......@@ -1584,7 +1556,6 @@ test "bitcast packed struct with u0" {
15841556
15851557test "optional pointer coerced to optional allowzero pointer" {
15861558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1587 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15881559
15891560 var p: ?*u32 = undefined;
15901561 var q: ?*allowzero u32 = undefined;
......@@ -1594,8 +1565,6 @@ test "optional pointer coerced to optional allowzero pointer" {
15941565}
15951566
15961567test "single item pointer to pointer to array to slice" {
1597 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1598
15991568 var x: i32 = 1234;
16001569 try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
16011570 const z1 = @as([]const i32, @as(*[1]i32, &x));
......@@ -1631,8 +1600,6 @@ test "@volatileCast without a result location" {
16311600}
16321601
16331602test "coercion from single-item pointer to @as to slice" {
1634 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1635
16361603 var x: u32 = 1;
16371604
16381605 // Why the following line gets a compile error?
......@@ -2294,7 +2261,6 @@ test "cast builtins can wrap result in error union" {
22942261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
22952262 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
22962263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2297 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
22982264
22992265 const S = struct {
23002266 const MyEnum = enum(u32) { _ };
......@@ -2501,6 +2467,7 @@ test "@intFromBool on vector" {
25012467test "numeric coercions with undefined" {
25022468 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
25032469 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2470 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
25042471
25052472 const from: i32 = undefined;
25062473 var to: f32 = from;
test/behavior/cast_int.zig-1
......@@ -19,7 +19,6 @@ test "coerce i8 to i32 and @intCast back" {
1919 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2020 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2121 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2322
2423 var x: i8 = -5;
2524 var y: i32 = -5;
test/behavior/comptime_memory.zig+2
......@@ -425,6 +425,8 @@ test "mutate entire slice at comptime" {
425425}
426426
427427test "dereference undefined pointer to zero-bit type" {
428 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
429
428430 const p0: *void = undefined;
429431 try testing.expectEqual({}, p0.*);
430432
test/behavior/defer.zig-2
......@@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual;
55const expectError = std.testing.expectError;
66
77test "break and continue inside loop inside defer expression" {
8 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
9
108 testBreakContInDefer(10);
119 comptime testBreakContInDefer(10);
1210}
test/behavior/empty_union.zig-3
......@@ -9,8 +9,6 @@ test "switch on empty enum" {
99}
1010
1111test "switch on empty enum with a specified tag type" {
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13
1412 const E = enum(u8) {};
1513 var e: E = undefined;
1614 switch (e) {}
......@@ -18,7 +16,6 @@ test "switch on empty enum with a specified tag type" {
1816
1917test "switch on empty auto numbered tagged union" {
2018 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2219
2320 const U = union(enum(u8)) {};
2421 var u: U = undefined;
test/behavior/enum.zig-4
......@@ -935,7 +935,6 @@ const Bar = enum { A, B, C, D };
935935test "enum literal casting to error union with payload enum" {
936936 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
937937 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
938 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
939938
940939 var bar: error{B}!Bar = undefined;
941940 bar = .B; // should never cast to the error set
......@@ -947,7 +946,6 @@ test "constant enum initialization with differing sizes" {
947946 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
948947 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
949948 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
951949
952950 try test3_1(test3_foo);
953951 try test3_2(test3_bar);
......@@ -1054,7 +1052,6 @@ test "enum literal casting to optional" {
10541052 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10551053 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10561054 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1057 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10581055
10591056 var bar: ?Bar = undefined;
10601057 bar = .B;
......@@ -1141,7 +1138,6 @@ test "tag name functions are unique" {
11411138test "size of enum with only one tag which has explicit integer tag type" {
11421139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11431140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1144 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11451141
11461142 const E = enum(u8) { nope = 10 };
11471143 const S0 = struct { e: E };
test/behavior/error.zig+1-15
......@@ -30,7 +30,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
3030
3131test "error binary operator" {
3232 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3433
3534 const a = errBinaryOperatorG(true) catch 3;
3635 const b = errBinaryOperatorG(false) catch 3;
......@@ -62,14 +61,12 @@ pub fn baz() anyerror!i32 {
6261
6362test "error wrapping" {
6463 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6664
6765 try expect((baz() catch unreachable) == 15);
6866}
6967
7068test "unwrap simple value from error" {
7169 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
7370
7471 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
7572 try expect(i == 13);
......@@ -80,7 +77,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
8077
8178test "error return in assignment" {
8279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
8480
8581 doErrReturnInAssignment() catch unreachable;
8682}
......@@ -103,7 +99,6 @@ test "syntax: optional operator in front of error union operator" {
10399test "widen cast integer payload of error union function call" {
104100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
105101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
106 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
107102
108103 const S = struct {
109104 fn errorable() !u64 {
......@@ -150,7 +145,6 @@ test "implicit cast to optional to error union to return result loc" {
150145}
151146
152147test "fn returning empty error set can be passed as fn returning any error" {
153 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
154148 entry();
155149 comptime entry();
156150}
......@@ -243,7 +237,6 @@ fn testExplicitErrorSetCast(set1: Set1) !void {
243237
244238test "comptime test error for empty error set" {
245239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
246 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
247240
248241 try testComptimeTestErrorEmptySet(1234);
249242 try comptime testComptimeTestErrorEmptySet(1234);
......@@ -279,7 +272,6 @@ test "inferred empty error set comptime catch" {
279272}
280273
281274test "error inference with an empty set" {
282 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
283275 const S = struct {
284276 const Struct = struct {
285277 pub fn func() (error{})!usize {
......@@ -334,7 +326,6 @@ fn quux_1() !i32 {
334326
335327test "error: Zero sized error set returned with value payload crash" {
336328 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
338329
339330 _ = try foo3(0);
340331 _ = try comptime foo3(0);
......@@ -434,7 +425,6 @@ test "nested error union function call in optional unwrap" {
434425test "return function call to error set from error union function" {
435426 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
436427 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
437 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
438428
439429 const S = struct {
440430 fn errorable() anyerror!i32 {
......@@ -670,7 +660,6 @@ test "peer type resolution of two different error unions" {
670660}
671661
672662test "coerce error set to the current inferred error set" {
673 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
674663 const S = struct {
675664 fn foo() !void {
676665 var a = false;
......@@ -833,7 +822,6 @@ test "alignment of wrapping an error union payload" {
833822
834823test "compare error union and error set" {
835824 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
836 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
837825
838826 var a: anyerror = error.Foo;
839827 var b: anyerror!u32 = error.Bar;
......@@ -862,8 +850,6 @@ fn non_errorable() void {
862850}
863851
864852test "catch within a function that calls no errorable functions" {
865 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
866
867853 non_errorable();
868854}
869855
......@@ -895,7 +881,6 @@ test "field access of anyerror results in smaller error set" {
895881test "optional error union return type" {
896882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
897883 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
899884
900885 const S = struct {
901886 fn foo() ?anyerror!u32 {
......@@ -942,6 +927,7 @@ test "returning an error union containing a type with no runtime bits" {
942927test "try used in recursive function with inferred error set" {
943928 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
944929 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
930 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
945931
946932 const Value = union(enum) {
947933 values: []const @This(),
test/behavior/eval.zig+1-35
......@@ -5,8 +5,6 @@ const expect = std.testing.expect;
55const expectEqual = std.testing.expectEqual;
66
77test "compile time recursion" {
8 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
9
108 try expect(some_data.len == 21);
119}
1210var some_data: [@as(usize, @intCast(fibonacci(7)))]u8 = undefined;
......@@ -74,7 +72,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
7472test "constant expressions" {
7573 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7674 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
7875
7976 var array: [array_size]u8 = undefined;
8077 try expect(@sizeOf(@TypeOf(array)) == 20);
......@@ -143,7 +140,6 @@ test "pointer to type" {
143140test "a type constructed in a global expression" {
144141 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
145142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
147143
148144 var l: List = undefined;
149145 l.array[0] = 10;
......@@ -202,8 +198,6 @@ test "@setEvalBranchQuota" {
202198}
203199
204200test "constant struct with negation" {
205 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
206
207201 try expect(vertices[0].x == @as(f32, -0.6));
208202}
209203const Vertex = struct {
......@@ -308,8 +302,6 @@ fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
308302}
309303
310304test "comptime iterate over fn ptr list" {
311 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
312
313305 try expect(performFn('t', 1) == 6);
314306 try expect(performFn('o', 0) == 1);
315307 try expect(performFn('w', 99) == 99);
......@@ -348,7 +340,6 @@ fn doesAlotT(comptime T: type, value: usize) T {
348340test "@setEvalBranchQuota at same scope as generic function call" {
349341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
350342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
352343
353344 try expect(doesAlotT(u32, 2) == 2);
354345}
......@@ -385,8 +376,6 @@ test "zero extend from u0 to u1" {
385376}
386377
387378test "return 0 from function that has u0 return type" {
388 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
389
390379 const S = struct {
391380 fn foo_zero() u0 {
392381 return 0;
......@@ -417,8 +406,6 @@ var st_init_str_foo = StInitStrFoo{
417406};
418407
419408test "inline for with same type but different values" {
420 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
421
422409 var res: usize = 0;
423410 inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
424411 var a: T = undefined;
......@@ -544,7 +531,6 @@ test "runtime 128 bit integer division" {
544531test "@tagName of @typeInfo" {
545532 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
546533 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
547 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
548534
549535 const str = @tagName(@typeInfo(u8));
550536 try expect(std.mem.eql(u8, str, "Int"));
......@@ -554,7 +540,6 @@ test "static eval list init" {
554540 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
555541 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
556542 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
557 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
558543
559544 try expect(static_vec3.data[2] == 1.0);
560545 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
......@@ -586,7 +571,6 @@ test "inlined loop has array literal with elided runtime scope on first iteratio
586571test "ptr to local array argument at comptime" {
587572 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
588573 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
589 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
590574
591575 comptime {
592576 var bytes: [10]u8 = undefined;
......@@ -623,7 +607,6 @@ const hi1 = "hi";
623607const hi2 = hi1;
624608test "const global shares pointer with other same one" {
625609 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
626 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
627610
628611 try assertEqualPtrs(&hi1[0], &hi2[0]);
629612 try comptime expect(&hi1[0] == &hi2[0]);
......@@ -659,8 +642,6 @@ pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
659642}
660643
661644test "comptime function with mutable pointer is not memoized" {
662 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
663
664645 comptime {
665646 var x: i32 = 1;
666647 const ptr = &x;
......@@ -729,6 +710,7 @@ fn loopNTimes(comptime n: usize) void {
729710}
730711
731712test "variable inside inline loop that has different types on different iterations" {
713 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
732714 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
733715}
734716
......@@ -752,7 +734,6 @@ test "array concatenation of function calls" {
752734 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
753735 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
754736 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
755 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
756737
757738 var a = oneItem(3) ++ oneItem(4);
758739 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
......@@ -762,7 +743,6 @@ test "array multiplication of function calls" {
762743 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
763744 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
764745 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
765 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
766746
767747 var a = oneItem(3) ** scalar(2);
768748 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
......@@ -851,7 +831,6 @@ test "array multiplication sets the sentinel - value" {
851831 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
852832 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
853833 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
854 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
855834
856835 var a = [2:7]u3{ 1, 6 };
857836 var b = a ** 2;
......@@ -868,7 +847,6 @@ test "array multiplication sets the sentinel - pointer" {
868847 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
869848 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
870849 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
871 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
872850
873851 var a = [2:7]u3{ 1, 6 };
874852 var b = &a ** 2;
......@@ -1003,7 +981,6 @@ test "closure capture type of runtime-known var" {
1003981
1004982test "comptime break passing through runtime condition converted to runtime break" {
1005983 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1006 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1007984
1008985 const S = struct {
1009986 fn doTheTest() !void {
......@@ -1037,7 +1014,6 @@ test "comptime break to outer loop passing through runtime condition converted t
10371014 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10381015 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10391016 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1040 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10411017
10421018 const S = struct {
10431019 fn doTheTest() !void {
......@@ -1109,7 +1085,6 @@ test "comptime break operand passing through runtime switch converted to runtime
11091085test "no dependency loop for alignment of self struct" {
11101086 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11111087 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11131088
11141089 const S = struct {
11151090 fn doTheTest() !void {
......@@ -1147,7 +1122,6 @@ test "no dependency loop for alignment of self struct" {
11471122test "no dependency loop for alignment of self bare union" {
11481123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11491124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1150 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11511125
11521126 const S = struct {
11531127 fn doTheTest() !void {
......@@ -1185,7 +1159,6 @@ test "no dependency loop for alignment of self bare union" {
11851159test "no dependency loop for alignment of self tagged union" {
11861160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11871161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1188 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11891162
11901163 const S = struct {
11911164 fn doTheTest() !void {
......@@ -1376,7 +1349,6 @@ test "lazy value is resolved as slice operand" {
13761349 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13771350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13781351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1379 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13801352
13811353 const A = struct { a: u32 };
13821354 var a: [512]u64 = undefined;
......@@ -1434,7 +1406,6 @@ test "inline for inside a runtime condition" {
14341406
14351407test "continue in inline for inside a comptime switch" {
14361408 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1437 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14381409
14391410 const arr = .{ 1, 2, 3 };
14401411 var count: u8 = 0;
......@@ -1500,7 +1471,6 @@ test "continue nested inline for loop in named block expr" {
15001471
15011472test "x and false is comptime-known false" {
15021473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1503 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15041474
15051475 const T = struct {
15061476 var x: u32 = 0;
......@@ -1528,7 +1498,6 @@ test "x and false is comptime-known false" {
15281498
15291499test "x or true is comptime-known true" {
15301500 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1531 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15321501
15331502 const T = struct {
15341503 var x: u32 = 0;
......@@ -1558,7 +1527,6 @@ test "non-optional and optional array elements concatenated" {
15581527 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15591528 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15601529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1561 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15621530
15631531 const array = [1]u8{'A'} ++ [1]?u8{null};
15641532 var index: usize = 0;
......@@ -1647,8 +1615,6 @@ test "result of nested switch assigned to variable" {
16471615}
16481616
16491617test "inline for loop of functions returning error unions" {
1650 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1651
16521618 const T1 = struct {
16531619 fn v() error{}!usize {
16541620 return 1;
test/behavior/floatop.zig-3
......@@ -736,7 +736,6 @@ test "@ceil" {
736736 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
737737 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
738738 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
739 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
740739
741740 try comptime testCeil();
742741 try testCeil();
......@@ -1053,7 +1052,6 @@ test "negation f128" {
10531052test "eval @setFloatMode at compile-time" {
10541053 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10551054 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1056 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10571055
10581056 const result = comptime fnWithFloatMode();
10591057 try expect(result == 1234.0);
......@@ -1089,7 +1087,6 @@ test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
10891087 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10901088 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10911089 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1092 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10931090
10941091 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
10951092 const pos = @as(F, 1) / @as(F, 0);
test/behavior/fn.zig+2-12
......@@ -20,8 +20,6 @@ fn testLocVars(b: i32) void {
2020}
2121
2222test "mutable local variables" {
23 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
24
2523 var zero: i32 = 0;
2624 try expect(zero == 0);
2725
......@@ -53,8 +51,6 @@ test "weird function name" {
5351}
5452
5553test "assign inline fn to const variable" {
56 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
57
5854 const a = inlineFn;
5955 a();
6056}
......@@ -190,7 +186,6 @@ test "function with complex callconv and return type expressions" {
190186
191187test "pass by non-copying value" {
192188 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
193 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
194189
195190 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
196191}
......@@ -218,7 +213,6 @@ fn addPointCoordsVar(pt: anytype) !i32 {
218213
219214test "pass by non-copying value as method" {
220215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
222216
223217 var pt = Point2{ .x = 1, .y = 2 };
224218 try expect(pt.addPointCoords() == 3);
......@@ -235,7 +229,6 @@ const Point2 = struct {
235229
236230test "pass by non-copying value as method, which is generic" {
237231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
238 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
239232
240233 var pt = Point3{ .x = 1, .y = 2 };
241234 try expect(pt.addPointCoords(i32) == 3);
......@@ -253,7 +246,6 @@ const Point3 = struct {
253246
254247test "pass by non-copying value as method, at comptime" {
255248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
257249
258250 comptime {
259251 var pt = Point2{ .x = 1, .y = 2 };
......@@ -396,8 +388,6 @@ test "function call with anon list literal - 2D" {
396388}
397389
398390test "ability to give comptime types and non comptime types to same parameter" {
399 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
400
401391 const S = struct {
402392 fn doTheTest() !void {
403393 var x: i32 = 1;
......@@ -415,8 +405,6 @@ test "ability to give comptime types and non comptime types to same parameter" {
415405}
416406
417407test "function with inferred error set but returning no error" {
418 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
419
420408 const S = struct {
421409 fn foo() !void {}
422410 };
......@@ -583,6 +571,8 @@ test "lazy values passed to anytype parameter" {
583571}
584572
585573test "pass and return comptime-only types" {
574 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
575
586576 const S = struct {
587577 fn returnNull(comptime x: @Type(.Null)) @Type(.Null) {
588578 return x;
test/behavior/for.zig-4
......@@ -257,7 +257,6 @@ test "for loop with else branch" {
257257test "count over fixed range" {
258258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
259259 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261260
262261 var sum: usize = 0;
263262 for (0..6) |i| {
......@@ -270,7 +269,6 @@ test "count over fixed range" {
270269test "two counters" {
271270 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
272271 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
273 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
274272
275273 var sum: usize = 0;
276274 for (0..10, 10..20) |i, j| {
......@@ -318,7 +316,6 @@ test "slice and two counters, one is offset and one is runtime" {
318316 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
319317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
320318 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
322319
323320 const slice: []const u8 = "blah";
324321 var start: usize = 0;
......@@ -406,7 +403,6 @@ test "inline for with slice as the comptime-known" {
406403 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
407404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
408405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
409 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
410406
411407 const comptime_slice = "hello";
412408 var runtime_i: usize = 3;
test/behavior/generics.zig+1-14
......@@ -55,7 +55,6 @@ test "fn with comptime args" {
5555 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
5757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5958
6059 try expect(gimmeTheBigOne(1234, 5678) == 5678);
6160 try expect(shouldCallSameInstance(34, 12) == 34);
......@@ -66,7 +65,6 @@ test "anytype params" {
6665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6766 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
7068
7169 try expect(max_i32(12, 34) == 34);
7270 try expect(max_f64(1.2, 3.4) == 3.4);
......@@ -91,7 +89,6 @@ fn max_f64(a: f64, b: f64) f64 {
9189test "type constructed by comptime function call" {
9290 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9391 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
9592
9693 var l: SimpleList(10) = undefined;
9794 l.array[0] = 10;
......@@ -115,7 +112,6 @@ test "function with return type type" {
115112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
116113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
117114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
118 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
119115
120116 var list: List(i32) = undefined;
121117 var list2: List(i32) = undefined;
......@@ -147,8 +143,6 @@ fn GenericDataThing(comptime count: isize) type {
147143}
148144
149145test "use generic param in generic param" {
150 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
151
152146 try expect(aGenericFn(i32, 3, 4) == 7);
153147}
154148fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
......@@ -178,7 +172,6 @@ test "generic fn keeps non-generic parameter types" {
178172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
179173 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
180174 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
182175
183176 const A = 128;
184177
......@@ -254,7 +247,6 @@ test "generic function instantiation turns into comptime call" {
254247 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
255248 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
256249 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
257 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
258250
259251 const S = struct {
260252 fn doTheTest() !void {
......@@ -288,6 +280,7 @@ test "generic function instantiation turns into comptime call" {
288280
289281test "generic function with void and comptime parameter" {
290282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
283 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
291284
292285 const S = struct { x: i32 };
293286 const namespace = struct {
......@@ -304,7 +297,6 @@ test "generic function with void and comptime parameter" {
304297test "anonymous struct return type referencing comptime parameter" {
305298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
306299 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
307 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
308300
309301 const S = struct {
310302 pub fn extraData(comptime T: type, index: usize) struct { data: T, end: usize } {
......@@ -405,8 +397,6 @@ test "generic struct as parameter type" {
405397}
406398
407399test "slice as parameter type" {
408 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
409
410400 const S = struct {
411401 fn internComptimeString(comptime str: []const u8) *const []const u8 {
412402 return &struct {
......@@ -421,8 +411,6 @@ test "slice as parameter type" {
421411}
422412
423413test "null sentinel pointer passed as generic argument" {
424 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
425
426414 const S = struct {
427415 fn doTheTest(a: anytype) !void {
428416 try std.testing.expect(@intFromPtr(a) == 8);
......@@ -433,7 +421,6 @@ test "null sentinel pointer passed as generic argument" {
433421
434422test "generic function passed as comptime argument" {
435423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
437424
438425 const S = struct {
439426 fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {
test/behavior/inline_switch.zig-3
......@@ -47,7 +47,6 @@ test "inline switch unions" {
4747 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4848 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
4949 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5150
5251 var x: U = .a;
5352 switch (x) {
......@@ -141,8 +140,6 @@ test "inline else int all values" {
141140}
142141
143142test "inline switch capture is set when switch operand is comptime known" {
144 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
145
146143 const U2 = union(enum) {
147144 a: u32,
148145 };
test/behavior/math.zig+2-3
......@@ -1020,7 +1020,6 @@ test "@subWithOverflow" {
10201020 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10211021 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10221022 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1023 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10241023
10251024 {
10261025 var a: u8 = 1;
......@@ -1146,8 +1145,6 @@ test "overflow arithmetic with u0 values" {
11461145}
11471146
11481147test "allow signed integer division/remainder when values are comptime-known and positive or exact" {
1149 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1150
11511148 try expect(5 / 3 == 1);
11521149 try expect(-5 / -3 == 1);
11531150 try expect(-6 / 3 == -2);
......@@ -1289,6 +1286,8 @@ fn testShrExact(x: u8) !void {
12891286}
12901287
12911288test "shift left/right on u0 operand" {
1289 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1290
12921291 const S = struct {
12931292 fn doTheTest() !void {
12941293 var x: u0 = 0;
test/behavior/maximum_minimum.zig-2
......@@ -200,7 +200,6 @@ test "@min/@max on comptime_int" {
200200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
201201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
204203
205204 const min = @min(1, 2, -2, -1);
206205 const max = @max(1, 2, -2, -1);
......@@ -257,7 +256,6 @@ test "@min/@max notices bounds from types when comptime-known value is undef" {
257256 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
258257 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
259258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261259
262260 var x: u32 = 1_000_000;
263261 const y: u16 = undefined;
test/behavior/optional.zig+2
......@@ -500,6 +500,8 @@ test "cast slice to const slice nested in error union and optional" {
500500}
501501
502502test "variable of optional of noreturn" {
503 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
504
503505 var null_opv: ?noreturn = null;
504506 try std.testing.expectEqual(@as(?noreturn, null), null_opv);
505507}
test/behavior/pointers.zig-9
......@@ -125,7 +125,6 @@ fn testDerefPtrOneVal() !void {
125125}
126126
127127test "peer type resolution with C pointers" {
128 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
129128 var ptr_one: *u8 = undefined;
130129 var ptr_many: [*]u8 = undefined;
131130 var ptr_c: [*c]u8 = undefined;
......@@ -141,7 +140,6 @@ test "peer type resolution with C pointers" {
141140}
142141
143142test "peer type resolution with C pointer and const pointer" {
144 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
145143 var ptr_c: [*c]u8 = undefined;
146144 const ptr_const: u8 = undefined;
147145 try expect(@TypeOf(ptr_c, &ptr_const) == [*c]const u8);
......@@ -314,7 +312,6 @@ test "allow any sentinel" {
314312test "pointer sentinel with enums" {
315313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
316314 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
318315
319316 const S = struct {
320317 const Number = enum {
......@@ -336,7 +333,6 @@ test "pointer sentinel with optional element" {
336333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337334 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
338335 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
340336
341337 const S = struct {
342338 fn doTheTest() !void {
......@@ -353,7 +349,6 @@ test "pointer sentinel with +inf" {
353349 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
354350 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
355351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
356 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
357352
358353 const S = struct {
359354 fn doTheTest() !void {
......@@ -374,7 +369,6 @@ test "pointer to array at fixed address" {
374369}
375370
376371test "pointer arithmetic affects the alignment" {
377 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
378372 {
379373 var ptr: [*]align(8) u32 = undefined;
380374 var x: usize = 1;
......@@ -430,7 +424,6 @@ test "indexing array with sentinel returns correct type" {
430424test "element pointer to slice" {
431425 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
432426 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
434427
435428 const S = struct {
436429 fn doTheTest() !void {
......@@ -453,7 +446,6 @@ test "element pointer to slice" {
453446test "element pointer arithmetic to slice" {
454447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
455448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
456 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
457449
458450 const S = struct {
459451 fn doTheTest() !void {
......@@ -478,7 +470,6 @@ test "element pointer arithmetic to slice" {
478470
479471test "array slicing to slice" {
480472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
481 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
482473
483474 const S = struct {
484475 fn doTheTest() !void {
test/behavior/slice.zig-11
......@@ -29,7 +29,6 @@ comptime {
2929
3030test "slicing" {
3131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3332
3433 var array: [20]i32 = undefined;
3534
......@@ -122,7 +121,6 @@ test "slice of type" {
122121
123122test "generic malloc free" {
124123 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
126124
127125 const a = memAlloc(u8, 10) catch unreachable;
128126 memFree(u8, a);
......@@ -303,7 +301,6 @@ test "slice type with custom alignment" {
303301
304302test "obtaining a null terminated slice" {
305303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
307304
308305 // here we have a normal array
309306 var buf: [50]u8 = undefined;
......@@ -346,7 +343,6 @@ test "empty array to slice" {
346343test "@ptrCast slice to pointer" {
347344 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
348345 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
350346
351347 const S = struct {
352348 fn doTheTest() !void {
......@@ -572,7 +568,6 @@ test "slice syntax resulting in pointer-to-array" {
572568test "slice pointer-to-array null terminated" {
573569 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
574570 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
576571
577572 comptime {
578573 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
......@@ -626,7 +621,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {
626621 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
627622 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
628623 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
629 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
630624
631625 const S = struct {
632626 const U = union {
......@@ -714,7 +708,6 @@ test "slice sentinel access at comptime" {
714708test "slicing array with sentinel as end index" {
715709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
716710 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
717 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
718711
719712 const S = struct {
720713 fn do() !void {
......@@ -733,7 +726,6 @@ test "slicing array with sentinel as end index" {
733726test "slicing slice with sentinel as end index" {
734727 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
735728 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
736 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
737729
738730 const S = struct {
739731 fn do() !void {
......@@ -762,8 +754,6 @@ test "slice len modification at comptime" {
762754}
763755
764756test "slice field ptr const" {
765 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
766
767757 const const_slice: []const u8 = "string";
768758
769759 const const_ptr_const_slice = &const_slice;
......@@ -777,7 +767,6 @@ test "slice field ptr const" {
777767
778768test "slice field ptr var" {
779769 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
780 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
781770
782771 var var_slice: []const u8 = "string";
783772
test/behavior/struct.zig+11-14
......@@ -109,7 +109,6 @@ fn testMutation(foo: *StructFoo) void {
109109
110110test "struct byval assign" {
111111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
113112
114113 var foo1: StructFoo = undefined;
115114 var foo2: StructFoo = undefined;
......@@ -129,14 +128,14 @@ test "call struct static method" {
129128const should_be_11 = StructWithNoFields.add(5, 6);
130129
131130test "invoke static method in global scope" {
132 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
133
134131 try expect(should_be_11 == 11);
135132}
136133
137134const empty_global_instance = StructWithNoFields{};
138135
139136test "return empty struct instance" {
137 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
138
140139 _ = returnEmptyStructInstance();
141140}
142141fn returnEmptyStructInstance() StructWithNoFields {
......@@ -253,7 +252,6 @@ test "usingnamespace within struct scope" {
253252test "struct field init with catch" {
254253 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
255254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
257255
258256 const S = struct {
259257 fn doTheTest() !void {
......@@ -331,6 +329,7 @@ const VoidStructFieldsFoo = struct {
331329
332330test "return empty struct from fn" {
333331 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
334333
335334 _ = testReturnEmptyStructFromFn();
336335}
......@@ -364,8 +363,6 @@ test "self-referencing struct via array member" {
364363}
365364
366365test "empty struct method call" {
367 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
368
369366 const es = EmptyStruct{};
370367 try expect(es.method() == 1234);
371368}
......@@ -550,7 +547,6 @@ test "implicit cast packed struct field to const ptr" {
550547
551548test "zero-bit field in packed struct" {
552549 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
553 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
554550
555551 const S = packed struct {
556552 x: u10,
......@@ -893,6 +889,8 @@ test "anonymous struct literal syntax" {
893889}
894890
895891test "fully anonymous struct" {
892 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
893
896894 const S = struct {
897895 fn doTheTest() !void {
898896 try dump(.{
......@@ -915,6 +913,8 @@ test "fully anonymous struct" {
915913}
916914
917915test "fully anonymous list literal" {
916 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
917
918918 const S = struct {
919919 fn doTheTest() !void {
920920 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
......@@ -942,8 +942,6 @@ test "tuple assigned to variable" {
942942}
943943
944944test "comptime struct field" {
945 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
946
947945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
948946 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
949947
......@@ -981,7 +979,6 @@ test "struct with union field" {
981979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
982980 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
983981 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
984 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
985982
986983 const Value = struct {
987984 ref: u32 = 2,
......@@ -1432,8 +1429,6 @@ test "struct field has a pointer to an aligned version of itself" {
14321429}
14331430
14341431test "struct has only one reference" {
1435 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1436
14371432 const S = struct {
14381433 fn optionalStructParam(_: ?struct { x: u8 }) void {}
14391434 fn errorUnionStructParam(_: error{}!struct { x: u8 }) void {}
......@@ -1503,7 +1498,6 @@ test "discarded struct initialization works as expected" {
15031498
15041499test "function pointer in struct returns the struct" {
15051500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1506 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15071501
15081502 const A = struct {
15091503 const A = @This();
......@@ -1553,7 +1547,6 @@ test "optional field init with tuple" {
15531547
15541548test "if inside struct init inside if" {
15551549 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1556 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15571550
15581551 const MyStruct = struct { x: u32 };
15591552 const b: u32 = 5;
......@@ -1715,6 +1708,8 @@ test "extern struct field pointer has correct alignment" {
17151708}
17161709
17171710test "packed struct field in anonymous struct" {
1711 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1712
17181713 const T = packed struct {
17191714 f1: bool = false,
17201715 };
......@@ -1740,6 +1735,8 @@ test "struct init with no result pointer sets field result types" {
17401735}
17411736
17421737test "runtime side-effects in comptime-known struct init" {
1738 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1739
17431740 var side_effects: u4 = 0;
17441741 const S = struct { a: u4, b: u4, c: u4, d: u4 };
17451742 const init = S{
test/behavior/switch.zig+2-10
......@@ -232,7 +232,6 @@ test "switch prong with variable" {
232232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
233233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
234234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
236235
237236 try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
238237 try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
......@@ -257,7 +256,6 @@ test "switch on enum using pointer capture" {
257256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
258257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
259258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261259
262260 try testSwitchEnumPtrCapture();
263261 try comptime testSwitchEnumPtrCapture();
......@@ -318,7 +316,6 @@ test "switch on union with some prongs capturing" {
318316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
319317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
320318 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
322319
323320 const X = union(enum) {
324321 a,
......@@ -355,7 +352,6 @@ test "switch on const enum with var" {
355352test "anon enum literal used in switch on union enum" {
356353 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
357354 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
359355
360356 const Foo = union(enum) {
361357 a: i32,
......@@ -394,7 +390,6 @@ fn switchWithUnreachable(x: i32) i32 {
394390
395391test "capture value of switch with all unreachable prongs" {
396392 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
398393
399394 const x = return_a_number() catch |err| switch (err) {
400395 else => unreachable,
......@@ -408,7 +403,6 @@ fn return_a_number() anyerror!i32 {
408403
409404test "switch on integer with else capturing expr" {
410405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
411 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
412406
413407 const S = struct {
414408 fn doTheTest() !void {
......@@ -498,7 +492,6 @@ test "switch prongs with error set cases make a new error set type for capture v
498492
499493test "return result loc and then switch with range implicit casted to error union" {
500494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
502495
503496 const S = struct {
504497 fn doTheTest() !void {
......@@ -539,7 +532,6 @@ test "switch prongs with cases with identical payload types" {
539532 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
540533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
541534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
542 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
543535
544536 const Union = union(enum) {
545537 A: usize,
......@@ -706,8 +698,6 @@ test "switch item sizeof" {
706698}
707699
708700test "comptime inline switch" {
709 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
710
711701 const U = union(enum) { a: type, b: type };
712702 const value = comptime blk: {
713703 var u: U = .{ .a = u32 };
......@@ -799,6 +789,8 @@ test "inline switch range that includes the maximum value of the switched type"
799789}
800790
801791test "nested break ignores switch conditions and breaks instead" {
792 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
793
802794 const S = struct {
803795 fn register_to_address(ident: []const u8) !u8 {
804796 const reg: u8 = if (std.mem.eql(u8, ident, "zero")) 0x00 else blk: {
test/behavior/this.zig-1
......@@ -27,7 +27,6 @@ test "this refer to module call private fn" {
2727test "this refer to container" {
2828 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2929 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3130
3231 var pt: Point(i32) = undefined;
3332 pt.x = 12;
test/behavior/translate_c_macros.zig+2
......@@ -233,6 +233,8 @@ test "@typeInfo on @cImport result" {
233233}
234234
235235test "Macro that uses Long type concatenation casting" {
236 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
237
236238 try expect((@TypeOf(h.X)) == c_long);
237239 try expectEqual(h.X, @as(c_long, 10));
238240}
test/behavior/try.zig-2
......@@ -24,8 +24,6 @@ fn returnsTen() anyerror!i32 {
2424}
2525
2626test "try without vars" {
27 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
28
2927 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
3028 try expect(result1 == 2);
3129
test/behavior/tuple.zig-3
......@@ -289,7 +289,6 @@ test "coerce tuple to tuple" {
289289 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
290290 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
291291 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
292 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
293292
294293 const T = std.meta.Tuple(&.{u8});
295294 const S = struct {
......@@ -304,7 +303,6 @@ test "tuple type with void field" {
304303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
305304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
306305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
307 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
308306
309307 const T = std.meta.Tuple(&[_]type{void});
310308 const x = T{{}};
......@@ -343,7 +341,6 @@ test "zero sized struct in tuple handled correctly" {
343341test "tuple type with void field and a runtime field" {
344342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
345343 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
347344
348345 const T = std.meta.Tuple(&[_]type{ usize, void });
349346 var t: T = .{ 5, {} };
test/behavior/type_info.zig-5
......@@ -160,7 +160,6 @@ test "type info: error set, error union info, anyerror" {
160160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
161161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
162162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
164163
165164 try testErrorSet();
166165 try comptime testErrorSet();
......@@ -192,7 +191,6 @@ test "type info: error set single value" {
192191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
193192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
194193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
196194
197195 const TestSet = error.One;
198196
......@@ -206,7 +204,6 @@ test "type info: error set merged" {
206204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
207205 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
208206 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
209 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
210207
211208 const TestSet = error{ One, Two } || error{Three};
212209
......@@ -222,7 +219,6 @@ test "type info: enum info" {
222219 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
223220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
224221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
225 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
226222
227223 try testEnum();
228224 try comptime testEnum();
......@@ -533,7 +529,6 @@ test "Struct.is_tuple for anon list literal" {
533529
534530test "Struct.is_tuple for anon struct literal" {
535531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
536 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
537532
538533 const info = @typeInfo(@TypeOf(.{ .a = 0 }));
539534 try expect(!info.Struct.is_tuple);
test/behavior/type_info_only_pub_decls.zig+3
......@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
12const std = @import("std");
23const other = struct {
34 const std = @import("std");
......@@ -14,6 +15,8 @@ const other = struct {
1415};
1516
1617test {
18 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
19
1720 const ti = @typeInfo(other);
1821 const decls = ti.Struct.decls;
1922
test/behavior/undefined.zig-2
......@@ -48,7 +48,6 @@ test "assign undefined to struct" {
4848 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
4949 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
5050 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5251
5352 comptime {
5453 var foo: Foo = undefined;
......@@ -66,7 +65,6 @@ test "assign undefined to struct with method" {
6665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6766 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
7068
7169 comptime {
7270 var foo: Foo = undefined;
test/behavior/underscore.zig-1
......@@ -8,7 +8,6 @@ test "ignore lval with underscore" {
88
99test "ignore lval with underscore (while loop)" {
1010 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1211
1312 while (optionalReturnError()) |_| {
1413 while (optionalReturnError()) |_| {
test/behavior/union.zig+2-28
......@@ -14,7 +14,6 @@ test "basic unions with floats" {
1414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1515 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1616 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1817
1918 var foo = FooWithFloats{ .int = 1 };
2019 try expect(foo.int == 1);
......@@ -30,7 +29,6 @@ test "init union with runtime value - floats" {
3029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3130 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3432
3533 var foo: FooWithFloats = undefined;
3634
......@@ -42,7 +40,6 @@ test "basic unions" {
4240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
4341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
4442 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
4643
4744 var foo = Foo{ .int = 1 };
4845 try expect(foo.int == 1);
......@@ -61,7 +58,6 @@ test "init union with runtime value" {
6158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
64 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6561
6662 var foo: Foo = undefined;
6763
......@@ -172,7 +168,6 @@ test "constant tagged union with payload" {
172168 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
173169 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
174170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
175 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
176171
177172 var empty = TaggedUnionWithPayload{ .Empty = {} };
178173 var full = TaggedUnionWithPayload{ .Full = 13 };
......@@ -342,7 +337,6 @@ test "constant packed union" {
342337 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
343338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
344339 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
346340
347341 try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }});
348342}
......@@ -453,7 +447,6 @@ test "global union with single field is correctly initialized" {
453447 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
454448 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
455449 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
456 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
457450
458451 glbl = Foo1{
459452 .f = @typeInfo(Foo1).Union.fields[0].type{ .x = 123 },
......@@ -500,7 +493,6 @@ test "union initializer generates padding only if needed" {
500493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
501494 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
502495 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
504496
505497 const U = union(enum) {
506498 A: u24,
......@@ -513,7 +505,6 @@ test "union initializer generates padding only if needed" {
513505test "runtime tag name with single field" {
514506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
515507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
517508
518509 const U = union(enum) {
519510 A: i32,
......@@ -590,7 +581,6 @@ test "tagged union as return value" {
590581 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
591582 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
592583 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
593 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
594584
595585 switch (returnAnInt(13)) {
596586 TaggedFoo.One => |value| try expect(value == 13),
......@@ -635,7 +625,6 @@ test "union(enum(u32)) with specified and unspecified tag values" {
635625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
636626 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
637627 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
638 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
639628
640629 try comptime expect(Tag(Tag(MultipleChoice2)) == u32);
641630 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
......@@ -673,7 +662,6 @@ test "switch on union with only 1 field" {
673662 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
674663 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
675664 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
676 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
677665
678666 var r: PartialInst = undefined;
679667 r = PartialInst.Compiled;
......@@ -702,7 +690,6 @@ const PartialInstWithPayload = union(enum) {
702690
703691test "union with only 1 field casted to its enum type which has enum value specified" {
704692 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
705 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
706693
707694 const Literal = union(enum) {
708695 Number: f64,
......@@ -787,7 +774,6 @@ test "return union init with void payload" {
787774 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
788775 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
789776 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
790 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
791777
792778 const S = struct {
793779 fn entry() !void {
......@@ -841,7 +827,6 @@ test "@unionInit can modify a union type" {
841827 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
842828 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
843829 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
844 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
845830
846831 const UnionInitEnum = union(enum) {
847832 Boolean: bool,
......@@ -865,7 +850,6 @@ test "@unionInit can modify a pointer value" {
865850 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
866851 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
867852 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
868 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
869853
870854 const UnionInitEnum = union(enum) {
871855 Boolean: bool,
......@@ -922,7 +906,6 @@ test "anonymous union literal syntax" {
922906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
923907 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
924908 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
925 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
926909
927910 const S = struct {
928911 const Number = union {
......@@ -1014,7 +997,6 @@ test "cast from pointer to anonymous struct to pointer to union" {
1014997 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1015998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1016999 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1017 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10181000
10191001 const S = struct {
10201002 const U = union(enum) {
......@@ -1046,7 +1028,6 @@ test "switching on non exhaustive union" {
10461028 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10471029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10481030 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1049 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10501031
10511032 const S = struct {
10521033 const E = enum(u8) {
......@@ -1179,7 +1160,6 @@ test "union with no result loc initiated with a runtime value" {
11791160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11801161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11811162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1182 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11831163
11841164 const U = union {
11851165 a: u32,
......@@ -1196,7 +1176,6 @@ test "union with a large struct field" {
11961176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11971177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11981178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1199 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12001179
12011180 const S = struct {
12021181 a: [8]usize,
......@@ -1230,7 +1209,6 @@ test "union tag is set when initiated as a temporary value at runtime" {
12301209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12311210 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12321211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1233 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12341212
12351213 const U = union(enum) {
12361214 a,
......@@ -1268,7 +1246,6 @@ test "return an extern union from C calling convention" {
12681246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12691247 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12701248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1271 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12721249
12731250 const namespace = struct {
12741251 const S = extern struct {
......@@ -1299,7 +1276,6 @@ test "noreturn field in union" {
12991276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13001277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13011278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1302 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13031279
13041280 const U = union(enum) {
13051281 a: u32,
......@@ -1351,7 +1327,6 @@ test "@unionInit uses tag value instead of field index" {
13511327 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13521328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13531329 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1354 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13551330
13561331 const E = enum(u8) {
13571332 b = 255,
......@@ -1480,7 +1455,6 @@ test "no dependency loop when function pointer in union returns the union" {
14801455test "union reassignment can use previous value" {
14811456 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14821457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1483 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14841458
14851459 const U = union {
14861460 a: u32,
......@@ -1532,7 +1506,6 @@ test "reinterpreting enum value inside packed union" {
15321506
15331507test "access the tag of a global tagged union" {
15341508 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1535 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15361509
15371510 const U = union(enum) {
15381511 a,
......@@ -1544,7 +1517,6 @@ test "access the tag of a global tagged union" {
15441517
15451518test "coerce enum literal to union in result loc" {
15461519 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1547 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15481520
15491521 const U = union(enum) {
15501522 a,
......@@ -1669,6 +1641,8 @@ test "packed union field pointer has correct alignment" {
16691641}
16701642
16711643test "union with 128 bit integer" {
1644 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1645
16721646 const ValueTag = enum { int, other };
16731647
16741648 const Value3 = union(ValueTag) {
test/behavior/var_args.zig+9
......@@ -14,6 +14,8 @@ fn add(args: anytype) i32 {
1414}
1515
1616test "add arbitrary args" {
17 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
18
1719 try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
1820 try expect(add(.{@as(i32, 1234)}) == 1234);
1921 try expect(add(.{}) == 0);
......@@ -24,12 +26,15 @@ fn readFirstVarArg(args: anytype) void {
2426}
2527
2628test "send void arg to var args" {
29 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
30
2731 readFirstVarArg(.{{}});
2832}
2933
3034test "pass args directly" {
3135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3236 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3338
3439 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
3540 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
......@@ -82,11 +87,15 @@ fn foo2(args: anytype) bool {
8287}
8388
8489test "array of var args functions" {
90 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
91
8592 try expect(foos[0](.{}));
8693 try expect(!foos[1](.{}));
8794}
8895
8996test "pass zero length array to var args param" {
97 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
98
9099 doNothingWithFirstArg(.{""});
91100}
92101
test/behavior/vector.zig-2
......@@ -240,7 +240,6 @@ test "peer type resolution with coercible element types" {
240240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
241241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
243 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
244243
245244 const S = struct {
246245 fn doTheTest() !void {
......@@ -1469,7 +1468,6 @@ test "boolean vector with 2 or more booleans" {
14691468 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14701469 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14711470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1472 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14731471
14741472 // TODO: try removing this after <https://github.com/ziglang/zig/issues/13782>:
14751473 if (!(builtin.os.tag == .linux and builtin.cpu.arch == .x86_64)) return;
test/behavior/while.zig-15
......@@ -50,8 +50,6 @@ test "while with continue expression" {
5050}
5151
5252test "while with else" {
53 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
54
5553 var sum: i32 = 0;
5654 var i: i32 = 0;
5755 var got_else: i32 = 0;
......@@ -79,8 +77,6 @@ fn getNumberOrNull() ?i32 {
7977}
8078
8179test "continue outer while loop" {
82 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
83
8480 testContinueOuter();
8581 comptime testContinueOuter();
8682}
......@@ -127,7 +123,6 @@ test "while copies its payload" {
127123
128124test "continue and break" {
129125 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
130 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
131126
132127 try runContinueAndBreakTest();
133128 try expect(continue_and_break_counter == 8);
......@@ -149,7 +144,6 @@ fn runContinueAndBreakTest() !void {
149144test "while with optional as condition" {
150145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
151146 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
152 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
153147
154148 numbers_left = 10;
155149 var sum: i32 = 0;
......@@ -162,7 +156,6 @@ test "while with optional as condition" {
162156test "while with optional as condition with else" {
163157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
164158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
166159
167160 numbers_left = 10;
168161 var sum: i32 = 0;
......@@ -223,7 +216,6 @@ test "while on optional with else result follow break prong" {
223216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
224217 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
225218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
227219
228220 const result = while (returnOptional(10)) |value| {
229221 break value;
......@@ -251,8 +243,6 @@ fn returnTrue() bool {
251243}
252244
253245test "return with implicit cast from while loop" {
254 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
255
256246 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
257247}
258248fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
......@@ -263,7 +253,6 @@ fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
263253
264254test "while on error union with else result follow else prong" {
265255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
267256
268257 const result = while (returnError()) |value| {
269258 break value;
......@@ -273,7 +262,6 @@ test "while on error union with else result follow else prong" {
273262
274263test "while on error union with else result follow break prong" {
275264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
277265
278266 const result = while (returnSuccess(10)) |value| {
279267 break value;
......@@ -319,7 +307,6 @@ test "while error 2 break statements and an else" {
319307 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
320308 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
321309 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
322 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
323310
324311 const S = struct {
325312 fn entry(opt_t: anyerror!bool, f: bool) !void {
......@@ -345,8 +332,6 @@ test "continue inline while loop" {
345332}
346333
347334test "else continue outer while" {
348 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
349
350335 var i: usize = 0;
351336 while (true) {
352337 i += 1;