authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-06-16 16:42:57+03:30
committergravatar for alichraghi@noreply.codeberg.orgAli Cheraghi <alichraghi@noreply.codeberg.org> 2026-06-18 13:38:58+02:00
log4653794852923e08cceab69620b7d0bb5d11e42d
tree233b20624ff8fc8da7ff0e297a336efd02f6ba86
parenta5fbbb83050f2dad0a9ebc0bd995a5a8f58d0a49

spirv: implement switch with ranges and loop_switch_br switch_dispatch


34 files changed, 679 insertions(+), 544 deletions(-)

src/codegen/spirv/CodeGen.zig+671-369
...@@ -45,104 +45,67 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {...@@ -45,104 +45,67 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
4545
46pub const zig_call_abi_ver = 3;46pub const zig_call_abi_ver = 3;
4747
48const ControlFlow = union(enum) {48const LoopSwitch = struct { cond_var: Id, continue_label: Id };
49 const Structured = struct {49
50 /// This type indicates the way that a block is terminated. The50/// This type indicates the way that a block is terminated. The
51 /// state of a particular block is used to track how a jump from51/// state of a particular block is used to track how a jump from
52 /// inside the block must reach the outside.52/// inside the block must reach the outside.
53 const Block = union(enum) {53const Block = union(enum) {
54 const Incoming = struct {54 const Incoming = struct {
55 src_label: Id,55 src_label: Id,
56 /// Instruction that returns an u32 value of the56 /// Instruction that returns an u32 value of the
57 /// `Air.Inst.Index` that control flow should jump to.57 /// `Air.Inst.Index` that control flow should jump to.
58 next_block: Id,58 next_block: Id,
59 };
60
61 const SelectionMerge = struct {
62 /// Incoming block from the `then` label.
63 /// Note that hte incoming block from the `else` label is
64 /// either given by the next element in the stack.
65 incoming: Incoming,
66 /// The label id of the cond_br's merge block.
67 /// For the top-most element in the stack, this
68 /// value is undefined.
69 merge_block: Id,
70 };
71
72 /// For a `selection` type block, we cannot use early exits, and we
73 /// must generate a 'merge ladder' of OpSelection instructions. To that end,
74 /// we keep a stack of the merges that still must be closed at the end of
75 /// a block.
76 ///
77 /// This entire structure basically just resembles a tree like
78 /// a x
79 /// \ /
80 /// b o merge
81 /// \ /
82 /// c o merge
83 /// \ /
84 /// o merge
85 /// /
86 /// o jump to next block
87 selection: struct {
88 /// In order to know which merges we still need to do, we need to keep
89 /// a stack of those.
90 merge_stack: std.ArrayList(SelectionMerge) = .empty,
91 },
92 /// For a `loop` type block, we can early-exit the block by
93 /// jumping to the loop exit node, and we don't need to generate
94 /// an entire stack of merges.
95 loop: struct {
96 /// The next block to jump to can be determined from any number
97 /// of conditions that jump to the loop exit.
98 merges: std.ArrayList(Incoming) = .empty,
99 /// The label id of the loop's merge block.
100 merge_block: Id,
101 },
102
103 fn deinit(block: *Structured.Block, gpa: Allocator) void {
104 switch (block.*) {
105 .selection => |*merge| merge.merge_stack.deinit(gpa),
106 .loop => |*merge| merge.merges.deinit(gpa),
107 }
108 block.* = undefined;
109 }
110 };
111 /// This determines how exits from the current block must be handled.
112 block_stack: std.ArrayList(*Structured.Block) = .empty,
113 block_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
114 };59 };
11560
116 const Unstructured = struct {61 const SelectionMerge = struct {
117 const Incoming = struct {62 /// Incoming block from the `then` label.
118 src_label: Id,63 /// Note that the incoming block from the `else` label is
119 break_value_id: Id,64 /// either given by the next element in the stack.
120 };65 incoming: Incoming,
12166 /// The label id of the cond_br's merge block.
122 const Block = struct {67 /// For the top-most element in the stack, this
123 label: ?Id = null,68 /// value is undefined.
124 incoming_blocks: std.ArrayList(Incoming) = .empty,69 merge_block: Id,
125 };
126
127 /// We need to keep track of result ids for block labels, as well as the 'incoming'
128 /// blocks for a block.
129 blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *Block) = .empty,
130 };70 };
13171
132 structured: Structured,72 /// For a `selection` type block, we cannot use early exits, and we
133 unstructured: Unstructured,73 /// must generate a 'merge ladder' of OpSelection instructions. To that end,
74 /// we keep a stack of the merges that still must be closed at the end of
75 /// a block.
76 ///
77 /// This entire structure basically just resembles a tree like
78 /// a x
79 /// \ /
80 /// b o merge
81 /// \ /
82 /// c o merge
83 /// \ /
84 /// o merge
85 /// /
86 /// o jump to next block
87 selection: struct {
88 /// In order to know which merges we still need to do, we need to keep
89 /// a stack of those.
90 merge_stack: std.ArrayList(SelectionMerge) = .empty,
91 },
92 /// For a `loop` type block, we can early-exit the block by
93 /// jumping to the loop exit node, and we don't need to generate
94 /// an entire stack of merges.
95 loop: struct {
96 /// The next block to jump to can be determined from any number
97 /// of conditions that jump to the loop exit.
98 merges: std.ArrayList(Incoming) = .empty,
99 /// The label id of the loop's merge block.
100 merge_block: Id,
101 },
134102
135 pub fn deinit(cg: *ControlFlow, gpa: Allocator) void {103 fn deinit(block: *Block, gpa: Allocator) void {
136 switch (cg.*) {104 switch (block.*) {
137 .structured => |*cf| {105 .selection => |*merge| merge.merge_stack.deinit(gpa),
138 cf.block_stack.deinit(gpa);106 .loop => |*merge| merge.merges.deinit(gpa),
139 cf.block_results.deinit(gpa);
140 },
141 .unstructured => |*cf| {
142 cf.blocks.deinit(gpa);
143 },
144 }107 }
145 cg.* = undefined;108 block.* = undefined;
146 }109 }
147};110};
148111
...@@ -151,23 +114,27 @@ air: Air,...@@ -151,23 +114,27 @@ air: Air,
151liveness: Air.Liveness,114liveness: Air.Liveness,
152owner_nav: InternPool.Nav.Index,115owner_nav: InternPool.Nav.Index,
153module: *Module,116module: *Module,
154control_flow: ControlFlow,117block_stack: std.ArrayList(*Block) = .empty,
118block_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
155base_line: u32,119base_line: u32,
156block_label: Id = .none,120block_label: Id = .none,
157next_arg_index: u32 = 0,121next_arg_index: u32 = 0,
158args: std.ArrayList(Id) = .empty,122args: std.ArrayList(Id) = .empty,
159virtual_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty,123virtual_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty,
160inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,124inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
125loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, LoopSwitch) = .empty,
161id_scratch: std.ArrayList(Id) = .empty,126id_scratch: std.ArrayList(Id) = .empty,
162prologue: Section = .{},127prologue: Section = .{},
163body: Section = .{},128body: Section = .{},
164129
165pub fn deinit(cg: *CodeGen) void {130pub fn deinit(cg: *CodeGen) void {
166 const gpa = cg.module.gpa;131 const gpa = cg.module.gpa;
167 cg.control_flow.deinit(gpa);132 cg.block_stack.deinit(gpa);
133 cg.block_results.deinit(gpa);
168 cg.args.deinit(gpa);134 cg.args.deinit(gpa);
169 cg.virtual_allocas.deinit(gpa);135 cg.virtual_allocas.deinit(gpa);
170 cg.inst_results.deinit(gpa);136 cg.inst_results.deinit(gpa);
137 cg.loop_switches.deinit(gpa);
171 cg.id_scratch.deinit(gpa);138 cg.id_scratch.deinit(gpa);
172 cg.prologue.deinit(gpa);139 cg.prologue.deinit(gpa);
173 cg.body.deinit(gpa);140 cg.body.deinit(gpa);
...@@ -183,7 +150,6 @@ pub fn generate(...@@ -183,7 +150,6 @@ pub fn generate(
183 const zcu = pt.zcu;150 const zcu = pt.zcu;
184 const gpa = zcu.gpa;151 const gpa = zcu.gpa;
185 const nav = zcu.funcInfo(func_index).owner_nav;152 const nav = zcu.funcInfo(func_index).owner_nav;
186 const structured_cfg = zcu.navFileScope(nav).mod.?.structured_cfg;
187153
188 var arena = std.heap.ArenaAllocator.init(gpa);154 var arena = std.heap.ArenaAllocator.init(gpa);
189 defer arena.deinit();155 defer arena.deinit();
...@@ -200,10 +166,6 @@ pub fn generate(...@@ -200,10 +166,6 @@ pub fn generate(
200 .liveness = liveness.*.?,166 .liveness = liveness.*.?,
201 .owner_nav = nav,167 .owner_nav = nav,
202 .module = &module,168 .module = &module,
203 .control_flow = switch (structured_cfg) {
204 true => .{ .structured = .{} },
205 false => .{ .unstructured = .{} },
206 },
207 .base_line = zcu.navSrcLine(nav),169 .base_line = zcu.navSrcLine(nav),
208 };170 };
209 defer cg.deinit();171 defer cg.deinit();
...@@ -222,7 +184,6 @@ pub fn generateNav(...@@ -222,7 +184,6 @@ pub fn generateNav(
222) codegen.Error!Mir {184) codegen.Error!Mir {
223 const zcu = pt.zcu;185 const zcu = pt.zcu;
224 const gpa = zcu.gpa;186 const gpa = zcu.gpa;
225 const structured_cfg = zcu.navFileScope(nav_index).mod.?.structured_cfg;
226187
227 var arena = std.heap.ArenaAllocator.init(gpa);188 var arena = std.heap.ArenaAllocator.init(gpa);
228 defer arena.deinit();189 defer arena.deinit();
...@@ -239,10 +200,6 @@ pub fn generateNav(...@@ -239,10 +200,6 @@ pub fn generateNav(
239 .liveness = undefined,200 .liveness = undefined,
240 .owner_nav = nav_index,201 .owner_nav = nav_index,
241 .module = &module,202 .module = &module,
242 .control_flow = switch (structured_cfg) {
243 true => .{ .structured = .{} },
244 false => .{ .unstructured = .{} },
245 },
246 .base_line = zcu.navSrcLine(nav_index),203 .base_line = zcu.navSrcLine(nav_index),
247 };204 };
248 defer cg.deinit();205 defer cg.deinit();
...@@ -433,17 +390,10 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {...@@ -433,17 +390,10 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
433 cg.block_label = root_block_id;390 cg.block_label = root_block_id;
434391
435 const main_body = cg.air.getMainBody();392 const main_body = cg.air.getMainBody();
436 switch (cg.control_flow) {393 _ = try cg.genStructuredBody(.selection, main_body);
437 .structured => {394 // We always expect paths to here to end, but we still need the block
438 _ = try cg.genStructuredBody(.selection, main_body);395 // to act as a dummy merge block.
439 // We always expect paths to here to end, but we still need the block396 try cg.body.emit(gpa, .OpUnreachable, {});
440 // to act as a dummy merge block.
441 try cg.body.emit(gpa, .OpUnreachable, {});
442 },
443 .unstructured => {
444 try cg.genBody(main_body);
445 },
446 }
447 try cg.body.emit(gpa, .OpFunctionEnd, {});397 try cg.body.emit(gpa, .OpFunctionEnd, {});
448 // Append the actual code into the functions section.398 // Append the actual code into the functions section.
449 try cg.module.sections.functions.append(gpa, cg.prologue);399 try cg.module.sections.functions.append(gpa, cg.prologue);
...@@ -1052,8 +1002,34 @@ fn constIntBig(cg: *CodeGen, ty: Type, val: Value) !Id {...@@ -1052,8 +1002,34 @@ fn constIntBig(cg: *CodeGen, ty: Type, val: Value) !Id {
1052 return cg.constructComposite(result_ty_id, constituents);1002 return cg.constructComposite(result_ty_id, constituents);
1053}1003}
10541004
1005/// Construct a composite value from its constituents.
1006/// In logical addressing mode (Vulkan/OpenGL), OpCompositeConstruct cannot accept
1007/// pointer operands, so for struct types we use alloc, store for each field and load instead.
1055pub fn constructComposite(cg: *CodeGen, result_ty_id: Id, constituents: []const Id) !Id {1008pub fn constructComposite(cg: *CodeGen, result_ty_id: Id, constituents: []const Id) !Id {
1056 const gpa = cg.module.gpa;1009 const gpa = cg.module.gpa;
1010
1011 if (cg.module.structFields(result_ty_id)) |fields| {
1012 assert(fields.len == constituents.len);
1013 const u32_ty_id = try cg.module.intType(.unsigned, 32);
1014 const var_id = try cg.alloc(result_ty_id, null);
1015 for (fields, constituents, 0..) |field_ty_id, constituent, i| {
1016 const field_ptr_ty_id = try cg.module.ptrType(field_ty_id, .function);
1017 const index_id = try cg.module.constant(u32_ty_id, .{ .uint32 = @intCast(i) });
1018 const field_ptr = try cg.accessChainId(field_ptr_ty_id, var_id, &.{index_id});
1019 try cg.body.emit(gpa, .OpStore, .{
1020 .pointer = field_ptr,
1021 .object = constituent,
1022 });
1023 }
1024 const result_id = cg.module.allocId();
1025 try cg.body.emit(gpa, .OpLoad, .{
1026 .id_result_type = result_ty_id,
1027 .id_result = result_id,
1028 .pointer = var_id,
1029 });
1030 return result_id;
1031 }
1032
1057 const result_id = cg.module.allocId();1033 const result_id = cg.module.allocId();
1058 try cg.body.emit(gpa, .OpCompositeConstruct, .{1034 try cg.body.emit(gpa, .OpCompositeConstruct, .{
1059 .id_result_type = result_ty_id,1035 .id_result_type = result_ty_id,
...@@ -3896,19 +3872,21 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {...@@ -3896,19 +3872,21 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
3896 .load => try cg.airLoad(inst),3872 .load => try cg.airLoad(inst),
3897 .store, .store_safe => return cg.airStore(inst),3873 .store, .store_safe => return cg.airStore(inst),
38983874
3899 .br => return cg.airBr(inst),3875 .br => return cg.airBr(inst),
3900 // For now just ignore this instruction. This effectively falls back on the old implementation,3876 // For now just ignore this instruction. This effectively falls back on the old implementation,
3901 // this doesn't change anything for us.3877 // this doesn't change anything for us.
3902 .repeat => return,3878 .repeat => return,
3903 .breakpoint => return,3879 .breakpoint => return,
3904 .cond_br => return cg.airCondBr(inst),3880 .cond_br => return cg.airCondBr(inst),
3905 .loop => return cg.airLoop(inst),3881 .loop => return cg.airLoop(inst),
3906 .ret => return cg.airRet(inst),3882 .ret => return cg.airRet(inst),
3907 .ret_safe => return cg.airRet(inst), // TODO3883 .ret_safe => return cg.airRet(inst), // TODO
3908 .ret_load => return cg.airRetLoad(inst),3884 .ret_load => return cg.airRetLoad(inst),
3909 .@"try" => try cg.airTry(inst),3885 .@"try" => try cg.airTry(inst),
3910 .switch_br => return cg.airSwitchBr(inst),3886 .switch_br => return cg.airSwitchBr(inst),
3911 .unreach, .trap => return cg.airUnreach(),3887 .loop_switch_br => return cg.airLoopSwitchBr(inst),
3888 .switch_dispatch => return cg.airSwitchDispatch(inst),
3889 .unreach, .trap => return cg.airUnreach(),
39123890
3913 .dbg_empty_stmt => return,3891 .dbg_empty_stmt => return,
3914 .dbg_stmt => return cg.airDbgStmt(inst),3892 .dbg_stmt => return cg.airDbgStmt(inst),
...@@ -6426,7 +6404,27 @@ fn structFieldPtr(...@@ -6426,7 +6404,27 @@ fn structFieldPtr(
6426 return cg.accessChain(result_ty_id, object_ptr, &.{field_index});6404 return cg.accessChain(result_ty_id, object_ptr, &.{field_index});
6427 },6405 },
6428 .@"struct" => switch (object_ty.containerLayout(zcu)) {6406 .@"struct" => switch (object_ty.containerLayout(zcu)) {
6429 .@"packed" => return cg.todo("implement field access for packed structs", .{}),6407 .@"packed" => {
6408 const byte_offset = codegen.fieldOffset(object_ptr_ty, result_ptr_ty, field_index, zcu);
6409 if (byte_offset == 0) return object_ptr;
6410 const usize_ty_id = try cg.resolveType(.usize, .direct);
6411 const base_int = cg.module.allocId();
6412 try cg.body.emit(cg.module.gpa, .OpConvertPtrToU, .{
6413 .id_result_type = usize_ty_id,
6414 .id_result = base_int,
6415 .pointer = object_ptr,
6416 });
6417 const offset_id = try cg.constInt(.usize, byte_offset);
6418 const adjusted = try cg.buildBinary(.OpIAdd, .{ .ty = .usize, .value = .{ .singleton = base_int } }, .{ .ty = .usize, .value = .{ .singleton = offset_id } });
6419 const adjusted_id = try adjusted.materialize(cg);
6420 const result_id = cg.module.allocId();
6421 try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{
6422 .id_result_type = result_ty_id,
6423 .id_result = result_id,
6424 .integer_value = adjusted_id,
6425 });
6426 return result_id;
6427 },
6430 .auto, .@"extern" => {6428 .auto, .@"extern" => {
6431 return try cg.accessChain(result_ty_id, object_ptr, &.{field_index});6429 return try cg.accessChain(result_ty_id, object_ptr, &.{field_index});
6432 },6430 },
...@@ -6532,9 +6530,7 @@ fn airArg(cg: *CodeGen) Id {...@@ -6532,9 +6530,7 @@ fn airArg(cg: *CodeGen) Id {
6532/// block to jump to. This function emits instructions, so it should be emitted6530/// block to jump to. This function emits instructions, so it should be emitted
6533/// inside the merge block of the block.6531/// inside the merge block of the block.
6534/// This function should only be called with structured control flow generation.6532/// This function should only be called with structured control flow generation.
6535fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Block.Incoming) !Id {6533fn structuredNextBlock(cg: *CodeGen, incoming: []const Block.Incoming) !Id {
6536 assert(cg.control_flow == .structured);
6537
6538 const result_id = cg.module.allocId();6534 const result_id = cg.module.allocId();
6539 const block_id_ty_id = try cg.resolveType(.u32, .direct);6535 const block_id_ty_id = try cg.resolveType(.u32, .direct);
6540 try cg.body.emitRaw(cg.module.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent...6536 try cg.body.emitRaw(cg.module.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent...
...@@ -6552,10 +6548,8 @@ fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Bl...@@ -6552,10 +6548,8 @@ fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Bl
6552/// terminating a body, there should be no instructions after it.6548/// terminating a body, there should be no instructions after it.
6553/// This function should only be called with structured control flow generation.6549/// This function should only be called with structured control flow generation.
6554fn structuredBreak(cg: *CodeGen, target_block: Id) !void {6550fn structuredBreak(cg: *CodeGen, target_block: Id) !void {
6555 assert(cg.control_flow == .structured);
6556
6557 const gpa = cg.module.gpa;6551 const gpa = cg.module.gpa;
6558 const sblock = cg.control_flow.structured.block_stack.getLast().?;6552 const sblock = cg.block_stack.getLast().?;
6559 const merge_block = switch (sblock.*) {6553 const merge_block = switch (sblock.*) {
6560 .selection => |*merge| blk: {6554 .selection => |*merge| blk: {
6561 const merge_label = cg.module.allocId();6555 const merge_label = cg.module.allocId();
...@@ -6598,11 +6592,9 @@ fn genStructuredBody(...@@ -6598,11 +6592,9 @@ fn genStructuredBody(
6598 },6592 },
6599 body: []const Air.Inst.Index,6593 body: []const Air.Inst.Index,
6600) !Id {6594) !Id {
6601 assert(cg.control_flow == .structured);
6602
6603 const gpa = cg.module.gpa;6595 const gpa = cg.module.gpa;
66046596
6605 var sblock: ControlFlow.Structured.Block = switch (block_merge_type) {6597 var sblock: Block = switch (block_merge_type) {
6606 .loop => |merge| .{ .loop = .{6598 .loop => |merge| .{ .loop = .{
6607 .merge_block = merge.merge_label,6599 .merge_block = merge.merge_label,
6608 } },6600 } },
...@@ -6611,8 +6603,8 @@ fn genStructuredBody(...@@ -6611,8 +6603,8 @@ fn genStructuredBody(
6611 defer sblock.deinit(gpa);6603 defer sblock.deinit(gpa);
66126604
6613 {6605 {
6614 try cg.control_flow.structured.block_stack.append(gpa, &sblock);6606 try cg.block_stack.append(gpa, &sblock);
6615 defer _ = cg.control_flow.structured.block_stack.pop();6607 defer _ = cg.block_stack.pop();
66166608
6617 try cg.genBody(body);6609 try cg.genBody(body);
6618 }6610 }
...@@ -6650,7 +6642,7 @@ fn genStructuredBody(...@@ -6650,7 +6642,7 @@ fn genStructuredBody(
6650 try cg.beginSpvBlock(merge_stack[merge_stack.len - 1].merge_block);6642 try cg.beginSpvBlock(merge_stack[merge_stack.len - 1].merge_block);
66516643
6652 // Now generate a merge ladder for the remaining merges in the stack.6644 // Now generate a merge ladder for the remaining merges in the stack.
6653 var incoming: ControlFlow.Structured.Block.Incoming = .{6645 var incoming: Block.Incoming = .{
6654 .src_label = cg.block_label,6646 .src_label = cg.block_label,
6655 .next_block = merge_stack[merge_stack.len - 1].incoming.next_block,6647 .next_block = merge_stack[merge_stack.len - 1].incoming.next_block,
6656 };6648 };
...@@ -6699,65 +6691,19 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -6699,65 +6691,19 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
6699 const ty = cg.typeOfIndex(inst);6691 const ty = cg.typeOfIndex(inst);
6700 const have_block_result = ty.hasRuntimeBits(zcu);6692 const have_block_result = ty.hasRuntimeBits(zcu);
67016693
6702 const cf = switch (cg.control_flow) {
6703 .structured => |*cf| cf,
6704 .unstructured => |*cf| {
6705 var block: ControlFlow.Unstructured.Block = .{};
6706 defer block.incoming_blocks.deinit(gpa);
6707
6708 // 4 chosen as arbitrary initial capacity.
6709 try block.incoming_blocks.ensureUnusedCapacity(gpa, 4);
6710
6711 try cf.blocks.putNoClobber(gpa, inst, &block);
6712 defer assert(cf.blocks.remove(inst));
6713
6714 try cg.genBody(body);
6715
6716 // Only begin a new block if there were actually any breaks towards it.
6717 if (block.label) |label| {
6718 try cg.beginSpvBlock(label);
6719 }
6720
6721 if (!have_block_result)
6722 return null;
6723
6724 assert(block.label != null);
6725 const result_id = cg.module.allocId();
6726 const result_type_id = try cg.resolveType(ty, .direct);
6727
6728 try cg.body.emitRaw(
6729 gpa,
6730 .OpPhi,
6731 // result type + result + variable/parent...
6732 2 + @as(u16, @intCast(block.incoming_blocks.items.len * 2)),
6733 );
6734 cg.body.writeOperand(Id, result_type_id);
6735 cg.body.writeOperand(Id, result_id);
6736
6737 for (block.incoming_blocks.items) |incoming| {
6738 cg.body.writeOperand(
6739 spec.PairIdRefIdRef,
6740 .{ incoming.break_value_id, incoming.src_label },
6741 );
6742 }
6743
6744 return result_id;
6745 },
6746 };
6747
6748 const maybe_block_result_var_id = if (have_block_result) blk: {6694 const maybe_block_result_var_id = if (have_block_result) blk: {
6749 const ty_id = try cg.resolveType(ty, .indirect);6695 const ty_id = try cg.resolveType(ty, .indirect);
6750 const block_result_var_id = try cg.alloc(ty_id, null);6696 const block_result_var_id = try cg.alloc(ty_id, null);
6751 try cf.block_results.putNoClobber(gpa, inst, block_result_var_id);6697 try cg.block_results.putNoClobber(gpa, inst, block_result_var_id);
6752 break :blk block_result_var_id;6698 break :blk block_result_var_id;
6753 } else null;6699 } else null;
6754 defer if (have_block_result) assert(cf.block_results.remove(inst));6700 defer if (have_block_result) assert(cg.block_results.remove(inst));
67556701
6756 const next_block = try cg.genStructuredBody(.selection, body);6702 const next_block = try cg.genStructuredBody(.selection, body);
67576703
6758 // When encountering a block instruction, we are always at least in the function's scope,6704 // When encountering a block instruction, we are always at least in the function's scope,
6759 // so there always has to be another entry.6705 // so there always has to be another entry.
6760 assert(cf.block_stack.items.len > 0);6706 assert(cg.block_stack.items.len > 0);
67616707
6762 // Check if the target of the branch was this current block.6708 // Check if the target of the branch was this current block.
6763 const this_block = try cg.constInt(.u32, @intFromEnum(inst));6709 const this_block = try cg.constInt(.u32, @intFromEnum(inst));
...@@ -6770,7 +6716,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -6770,7 +6716,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
6770 .operand_2 = this_block,6716 .operand_2 = this_block,
6771 });6717 });
67726718
6773 const sblock = cf.block_stack.getLast().?;6719 const sblock = cg.block_stack.getLast().?;
67746720
6775 if (ty.isNoReturn(zcu)) {6721 if (ty.isNoReturn(zcu)) {
6776 // If this block is noreturn, this instruction is the last of a block,6722 // If this block is noreturn, this instruction is the last of a block,
...@@ -6828,41 +6774,18 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -6828,41 +6774,18 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
6828}6774}
68296775
6830fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void {6776fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
6831 const gpa = cg.module.gpa;
6832 const zcu = cg.module.zcu;6777 const zcu = cg.module.zcu;
6833 const br = cg.air.instructions.items(.data)[@intFromEnum(inst)].br;6778 const br = cg.air.instructions.items(.data)[@intFromEnum(inst)].br;
6834 const operand_ty = cg.typeOf(br.operand);6779 const operand_ty = cg.typeOf(br.operand);
68356780
6836 switch (cg.control_flow) {6781 if (operand_ty.hasRuntimeBits(zcu)) {
6837 .structured => |*cf| {6782 const operand_id = try cg.resolve(br.operand);
6838 if (operand_ty.hasRuntimeBits(zcu)) {6783 const block_result_var_id = cg.block_results.get(br.block_inst).?;
6839 const operand_id = try cg.resolve(br.operand);6784 try cg.store(operand_ty, block_result_var_id, operand_id, .{});
6840 const block_result_var_id = cf.block_results.get(br.block_inst).?;
6841 try cg.store(operand_ty, block_result_var_id, operand_id, .{});
6842 }
6843
6844 const next_block = try cg.constInt(.u32, @intFromEnum(br.block_inst));
6845 try cg.structuredBreak(next_block);
6846 },
6847 .unstructured => |cf| {
6848 const block = cf.blocks.get(br.block_inst).?;
6849 if (operand_ty.hasRuntimeBits(zcu)) {
6850 const operand_id = try cg.resolve(br.operand);
6851 // block_label should not be undefined here, lest there
6852 // is a br or br_void in the function's body.
6853 try block.incoming_blocks.append(gpa, .{
6854 .src_label = cg.block_label,
6855 .break_value_id = operand_id,
6856 });
6857 }
6858
6859 if (block.label == null) {
6860 block.label = cg.module.allocId();
6861 }
6862
6863 try cg.body.emit(gpa, .OpBranch, .{ .target_label = block.label.? });
6864 },
6865 }6785 }
6786
6787 const next_block = try cg.constInt(.u32, @intFromEnum(br.block_inst));
6788 try cg.structuredBreak(next_block);
6866}6789}
68676790
6868fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void {6791fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
...@@ -6875,56 +6798,40 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void {...@@ -6875,56 +6798,40 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
6875 const then_label = cg.module.allocId();6798 const then_label = cg.module.allocId();
6876 const else_label = cg.module.allocId();6799 const else_label = cg.module.allocId();
68776800
6878 switch (cg.control_flow) {6801 const merge_label = cg.module.allocId();
6879 .structured => {
6880 const merge_label = cg.module.allocId();
6881
6882 try cg.body.emit(gpa, .OpSelectionMerge, .{
6883 .merge_block = merge_label,
6884 .selection_control = .{},
6885 });
6886 try cg.body.emit(gpa, .OpBranchConditional, .{
6887 .condition = condition_id,
6888 .true_label = then_label,
6889 .false_label = else_label,
6890 });
68916802
6892 try cg.beginSpvBlock(then_label);6803 try cg.body.emit(gpa, .OpSelectionMerge, .{
6893 const then_next = try cg.genStructuredBody(.selection, then_body);6804 .merge_block = merge_label,
6894 const then_incoming: ControlFlow.Structured.Block.Incoming = .{6805 .selection_control = .{},
6895 .src_label = cg.block_label,6806 });
6896 .next_block = then_next,6807 try cg.body.emit(gpa, .OpBranchConditional, .{
6897 };6808 .condition = condition_id,
6809 .true_label = then_label,
6810 .false_label = else_label,
6811 });
68986812
6899 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });6813 try cg.beginSpvBlock(then_label);
6814 const then_next = try cg.genStructuredBody(.selection, then_body);
6815 const then_incoming: Block.Incoming = .{
6816 .src_label = cg.block_label,
6817 .next_block = then_next,
6818 };
69006819
6901 try cg.beginSpvBlock(else_label);6820 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
6902 const else_next = try cg.genStructuredBody(.selection, else_body);
6903 const else_incoming: ControlFlow.Structured.Block.Incoming = .{
6904 .src_label = cg.block_label,
6905 .next_block = else_next,
6906 };
69076821
6908 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });6822 try cg.beginSpvBlock(else_label);
6823 const else_next = try cg.genStructuredBody(.selection, else_body);
6824 const else_incoming: Block.Incoming = .{
6825 .src_label = cg.block_label,
6826 .next_block = else_next,
6827 };
69096828
6910 try cg.beginSpvBlock(merge_label);6829 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
6911 const next_block = try cg.structuredNextBlock(&.{ then_incoming, else_incoming });
69126830
6913 try cg.structuredBreak(next_block);6831 try cg.beginSpvBlock(merge_label);
6914 },6832 const next_block = try cg.structuredNextBlock(&.{ then_incoming, else_incoming });
6915 .unstructured => {
6916 try cg.body.emit(gpa, .OpBranchConditional, .{
6917 .condition = condition_id,
6918 .true_label = then_label,
6919 .false_label = else_label,
6920 });
69216833
6922 try cg.beginSpvBlock(then_label);6834 try cg.structuredBreak(next_block);
6923 try cg.genBody(then_body);
6924 try cg.beginSpvBlock(else_label);
6925 try cg.genBody(else_body);
6926 },
6927 }
6928}6835}
69296836
6930fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void {6837fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void {
...@@ -6933,67 +6840,85 @@ fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void {...@@ -6933,67 +6840,85 @@ fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void {
69336840
6934 const body_label = cg.module.allocId();6841 const body_label = cg.module.allocId();
69356842
6936 switch (cg.control_flow) {6843 const header_label = cg.module.allocId();
6937 .structured => {6844 const merge_label = cg.module.allocId();
6938 const header_label = cg.module.allocId();6845 const continue_label = cg.module.allocId();
6939 const merge_label = cg.module.allocId();
6940 const continue_label = cg.module.allocId();
6941
6942 // The back-edge must point to the loop header, so generate a separate block for the
6943 // loop header so that we don't accidentally include some instructions from there
6944 // in the loop.
69456846
6946 try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });6847 // The back-edge must point to the loop header, so generate a separate block for the
6947 try cg.beginSpvBlock(header_label);6848 // loop header so that we don't accidentally include some instructions from there
6849 // in the loop.
69486850
6949 // Emit loop header and jump to loop body6851 try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
6950 try cg.body.emit(gpa, .OpLoopMerge, .{6852 try cg.beginSpvBlock(header_label);
6951 .merge_block = merge_label,
6952 .continue_target = continue_label,
6953 .loop_control = .{},
6954 });
69556853
6956 try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });6854 // Emit loop header and jump to loop body
6855 try cg.body.emit(gpa, .OpLoopMerge, .{
6856 .merge_block = merge_label,
6857 .continue_target = continue_label,
6858 .loop_control = .{},
6859 });
69576860
6958 try cg.beginSpvBlock(body_label);6861 try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
69596862
6960 const next_block = try cg.genStructuredBody(.{ .loop = .{6863 try cg.beginSpvBlock(body_label);
6961 .merge_label = merge_label,
6962 .continue_label = continue_label,
6963 } }, block.body);
6964 try cg.structuredBreak(next_block);
69656864
6966 try cg.beginSpvBlock(continue_label);6865 const next_block = try cg.genStructuredBody(.{ .loop = .{
6866 .merge_label = merge_label,
6867 .continue_label = continue_label,
6868 } }, block.body);
6869 try cg.structuredBreak(next_block);
69676870
6968 try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });6871 try cg.beginSpvBlock(continue_label);
6969 },
6970 .unstructured => {
6971 try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
6972 try cg.beginSpvBlock(body_label);
6973 try cg.genBody(block.body);
69746872
6975 try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });6873 try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
6976 },
6977 }
6978}6874}
69796875
6980fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) !?Id {6876fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
6981 const zcu = cg.module.zcu;6877 const zcu = cg.module.zcu;
6878 const pt = cg.pt;
6982 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6879 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6983 const ptr_ty = cg.typeOf(ty_op.operand);6880 const ptr_ty = cg.typeOf(ty_op.operand);
6881 const ptr_info = ptr_ty.ptrInfo(zcu);
6984 const elem_ty = cg.typeOfIndex(inst);6882 const elem_ty = cg.typeOfIndex(inst);
6985 const operand = try cg.resolve(ty_op.operand);6883 const operand = try cg.resolve(ty_op.operand);
6986 if (!ptr_ty.isVolatilePtr(zcu) and cg.liveness.isUnused(inst)) return null;6884 if (!ptr_ty.isVolatilePtr(zcu) and cg.liveness.isUnused(inst)) return null;
69876885
6988 if (cg.virtual_allocas.get(operand)) |stored| return stored.?;6886 if (cg.virtual_allocas.get(operand)) |stored| return stored.?;
69896887
6888 if (ptr_info.packed_offset.host_size != 0 and
6889 ptr_info.flags.vector_index == .none)
6890 {
6891 const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
6892 const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu));
6893 const host_int_ty = try pt.intType(.unsigned, host_bits);
6894 const host_val = try cg.load(host_int_ty, operand, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
6895 const signedness: Signedness = if (elem_ty.isInt(zcu)) elem_ty.intInfo(zcu).signedness else .unsigned;
6896 const field_int_ty = try pt.intType(signedness, elem_bit_size);
6897 const narrowed = if (ptr_info.packed_offset.bit_offset > 0) blk: {
6898 const bit_offset_id = try cg.constInt(host_int_ty, ptr_info.packed_offset.bit_offset);
6899 const shifted = try cg.buildBinary(.OpShiftRightLogical, .{ .ty = host_int_ty, .value = .{ .singleton = host_val } }, .{ .ty = host_int_ty, .value = .{ .singleton = bit_offset_id } });
6900 break :blk try shifted.materialize(cg);
6901 } else host_val;
6902 const result_id = blk: {
6903 if (cg.module.backingIntBits(elem_bit_size).@"0" == cg.module.backingIntBits(host_bits).@"0")
6904 break :blk try cg.bitCast(field_int_ty, host_int_ty, narrowed);
6905 const trunc = try cg.buildConvert(field_int_ty, .{ .ty = host_int_ty, .value = .{ .singleton = narrowed } });
6906 break :blk try trunc.materialize(cg);
6907 };
6908 if (elem_ty.ip_index == .bool_type) return try cg.convertToDirect(.bool, result_id);
6909 if (elem_ty.isInt(zcu)) return result_id;
6910 return try cg.bitCast(elem_ty, field_int_ty, result_id);
6911 }
6912
6990 return try cg.load(elem_ty, operand, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });6913 return try cg.load(elem_ty, operand, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
6991}6914}
69926915
6993fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void {6916fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void {
6994 const zcu = cg.module.zcu;6917 const zcu = cg.module.zcu;
6918 const pt = cg.pt;
6995 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;6919 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
6996 const ptr_ty = cg.typeOf(bin_op.lhs);6920 const ptr_ty = cg.typeOf(bin_op.lhs);
6921 const ptr_info = ptr_ty.ptrInfo(zcu);
6997 const elem_ty = ptr_ty.childType(zcu);6922 const elem_ty = ptr_ty.childType(zcu);
6998 const ptr = try cg.resolve(bin_op.lhs);6923 const ptr = try cg.resolve(bin_op.lhs);
6999 const value = try cg.resolve(bin_op.rhs);6924 const value = try cg.resolve(bin_op.rhs);
...@@ -7003,6 +6928,48 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7003,6 +6928,48 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void {
7003 return;6928 return;
7004 }6929 }
70056930
6931 if (ptr_info.packed_offset.host_size != 0 and
6932 ptr_info.flags.vector_index == .none)
6933 {
6934 const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
6935 const host_int_ty = try pt.intType(.unsigned, host_bits);
6936 const host_val = try cg.load(host_int_ty, ptr, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
6937 const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu));
6938 const signedness: Signedness = if (elem_ty.isInt(zcu)) elem_ty.intInfo(zcu).signedness else .unsigned;
6939 const field_int_ty = try pt.intType(signedness, elem_bit_size);
6940
6941 var value_as_int: Id = undefined;
6942 if (elem_ty.ip_index == .bool_type) {
6943 value_as_int = try cg.convertToIndirect(.bool, value);
6944 value_as_int = try cg.bitCast(field_int_ty, .u1, value_as_int);
6945 } else if (elem_ty.isInt(zcu)) {
6946 value_as_int = value;
6947 } else {
6948 value_as_int = try cg.bitCast(field_int_ty, elem_ty, value);
6949 }
6950
6951 const extended = blk: {
6952 if (cg.module.backingIntBits(elem_bit_size).@"0" == cg.module.backingIntBits(host_bits).@"0")
6953 break :blk try cg.bitCast(host_int_ty, field_int_ty, value_as_int);
6954 const conv = try cg.buildConvert(host_int_ty, .{ .ty = field_int_ty, .value = .{ .singleton = value_as_int } });
6955 break :blk try conv.materialize(cg);
6956 };
6957
6958 const bit_offset = ptr_info.packed_offset.bit_offset;
6959 const field_mask = (@as(u64, 1) << @as(u6, @intCast(elem_bit_size))) - 1;
6960 const host_mask = if (host_bits == 64) @as(u64, std.math.maxInt(u64)) else (@as(u64, 1) << @as(u6, @intCast(host_bits))) - 1;
6961 const clear_mask = ~(field_mask << @as(u6, @intCast(bit_offset))) & host_mask;
6962 const clear_mask_id = try cg.constInt(host_int_ty, clear_mask);
6963 const cleared = try cg.buildBinary(.OpBitwiseAnd, .{ .ty = host_int_ty, .value = .{ .singleton = host_val } }, .{ .ty = host_int_ty, .value = .{ .singleton = clear_mask_id } });
6964 const bit_offset_id = try cg.constInt(host_int_ty, bit_offset);
6965 const shifted_val = try cg.buildBinary(.OpShiftLeftLogical, .{ .ty = host_int_ty, .value = .{ .singleton = extended } }, .{ .ty = host_int_ty, .value = .{ .singleton = bit_offset_id } });
6966 const combined = try cg.buildBinary(.OpBitwiseOr, cleared, shifted_val);
6967 const combined_id = try combined.materialize(cg);
6968
6969 try cg.store(host_int_ty, ptr, combined_id, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
6970 return;
6971 }
6972
7006 try cg.store(elem_ty, ptr, value, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });6973 try cg.store(elem_ty, ptr, value, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
7007}6974}
70086975
...@@ -7091,19 +7058,13 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id {...@@ -7091,19 +7058,13 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
7091 const err_block = cg.module.allocId();7058 const err_block = cg.module.allocId();
7092 const ok_block = cg.module.allocId();7059 const ok_block = cg.module.allocId();
70937060
7094 switch (cg.control_flow) {7061 // According to AIR documentation, this block is guaranteed
7095 .structured => {7062 // to not break and end in a return instruction. Thus,
7096 // According to AIR documentation, this block is guaranteed7063 // we can just naively use the ok block as the merge block here.
7097 // to not break and end in a return instruction. Thus,7064 try cg.body.emit(gpa, .OpSelectionMerge, .{
7098 // for structured control flow, we can just naively use7065 .merge_block = ok_block,
7099 // the ok block as the merge block here.7066 .selection_control = .{},
7100 try cg.body.emit(gpa, .OpSelectionMerge, .{7067 });
7101 .merge_block = ok_block,
7102 .selection_control = .{},
7103 });
7104 },
7105 .unstructured => {},
7106 }
71077068
7108 try cg.body.emit(gpa, .OpBranchConditional, .{7069 try cg.body.emit(gpa, .OpBranchConditional, .{
7109 .condition = is_err_id,7070 .condition = is_err_id,
...@@ -7419,45 +7380,44 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7419,45 +7380,44 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
74197380
7420 const num_cases = switch_br.cases_len;7381 const num_cases = switch_br.cases_len;
74217382
7422 // Compute the total number of arms that we need.7383 // compute the total number of scalar arms and find the last range case
7423 // Zig switches are grouped by condition, so we need to loop through all of them7384 var num_conditions: u32 = 0;
7424 const num_conditions = blk: {7385 var last_range_case: ?u32 = null;
7425 var num_conditions: u32 = 0;7386 {
7426 var it = switch_br.iterateCases();7387 var it = switch_br.iterateCases();
7427 while (it.next()) |case| {7388 while (it.next()) |case| {
7428 if (case.ranges.len > 0) return cg.todo("switch with ranges", .{});7389 if (case.ranges.len > 0) {
7429 num_conditions += @intCast(case.items.len);7390 last_range_case = case.idx;
7391 } else {
7392 num_conditions += @intCast(case.items.len);
7393 }
7430 }7394 }
7431 break :blk num_conditions;7395 }
7432 };
74337396
7434 // First, pre-allocate the labels for the cases.7397 // First, pre-allocate the labels for the cases.
7435 const case_labels = cg.module.allocIds(num_cases);7398 const case_labels = cg.module.allocIds(num_cases);
7436 // We always need the default case - if zig has none, we will generate unreachable there.7399 // We always need the default case - if zig has none, we will generate unreachable there.
7437 const default = cg.module.allocId();7400 const default_label = cg.module.allocId();
7401 const switch_default = if (last_range_case != null) cg.module.allocId() else default_label;
74387402
7439 const merge_label = switch (cg.control_flow) {7403 const merge_label = cg.module.allocId();
7440 .structured => cg.module.allocId(),
7441 .unstructured => null,
7442 };
74437404
7444 if (cg.control_flow == .structured) {7405 try cg.body.emit(gpa, .OpSelectionMerge, .{
7445 try cg.body.emit(gpa, .OpSelectionMerge, .{7406 .merge_block = merge_label,
7446 .merge_block = merge_label.?,7407 .selection_control = .{},
7447 .selection_control = .{},7408 });
7448 });
7449 }
74507409
7451 // Emit the instruction before generating the blocks.7410 // Emit the instruction before generating the blocks.
7452 try cg.body.emitRaw(gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions);7411 try cg.body.emitRaw(gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions);
7453 cg.body.writeOperand(Id, cond_indirect);7412 cg.body.writeOperand(Id, cond_indirect);
7454 cg.body.writeOperand(Id, default);7413 cg.body.writeOperand(Id, switch_default);
74557414
7456 // Emit each of the cases7415 // Emit the non-range cases into the OpSwitch.
7416 // Cases with ranges are handled by the conditional chain below.
7457 {7417 {
7458 var it = switch_br.iterateCases();7418 var it = switch_br.iterateCases();
7459 while (it.next()) |case| {7419 while (it.next()) |case| {
7460 // SPIR-V needs a literal here, which' width depends on the case condition.7420 if (case.ranges.len > 0) continue;
7461 const label = case_labels.at(case.idx);7421 const label = case_labels.at(case.idx);
74627422
7463 for (case.items) |item| {7423 for (case.items) |item| {
...@@ -7480,62 +7440,394 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7480,62 +7440,394 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
7480 }7440 }
7481 }7441 }
74827442
7483 var incoming_structured_blocks: std.ArrayList(ControlFlow.Structured.Block.Incoming) = .empty;7443 var incoming_structured_blocks: std.ArrayList(Block.Incoming) = .empty;
7484 defer incoming_structured_blocks.deinit(gpa);7444 defer incoming_structured_blocks.deinit(gpa);
7445 try incoming_structured_blocks.ensureUnusedCapacity(gpa, num_cases + 1);
7446
7447 // emit the range-checking chain as nested if-else inside the switch's default branch.
7448 // each range case becomes:
7449 // - check condition,
7450 // - if true emit case body and branch to merge,
7451 // - else continue to next check or default
7452 if (last_range_case != null) {
7453 const cond_tmp: Temporary = .init(cond_ty, cond);
7454 const bool_ty_id = try cg.resolveType(.bool, .direct);
7455
7456 try cg.beginSpvBlock(switch_default);
7457
7458 var it_range = switch_br.iterateCases();
7459 while (it_range.next()) |case| {
7460 if (case.ranges.len == 0) continue;
7461
7462 var case_cond: ?Id = null;
7463
7464 for (case.items) |item| {
7465 const item_tmp: Temporary = try cg.temporary(item);
7466 const eq = try (try cg.cmp(.eq, cond_tmp, item_tmp)).materialize(cg);
7467 case_cond = if (case_cond) |prev| blk: {
7468 const combined = cg.module.allocId();
7469 try cg.body.emitRaw(gpa, .OpLogicalOr, 4);
7470 cg.body.writeOperand(Id, bool_ty_id);
7471 cg.body.writeOperand(Id, combined);
7472 cg.body.writeOperand(Id, prev);
7473 cg.body.writeOperand(Id, eq);
7474 break :blk combined;
7475 } else eq;
7476 }
7477
7478 for (case.ranges) |range| {
7479 const lo_tmp: Temporary = try cg.temporary(range[0]);
7480 const hi_tmp: Temporary = try cg.temporary(range[1]);
7481 const ge = try (try cg.cmp(.gte, cond_tmp, lo_tmp)).materialize(cg);
7482 const le = try (try cg.cmp(.lte, cond_tmp, hi_tmp)).materialize(cg);
7483 const in_range = cg.module.allocId();
7484 try cg.body.emitRaw(gpa, .OpLogicalAnd, 4);
7485 cg.body.writeOperand(Id, bool_ty_id);
7486 cg.body.writeOperand(Id, in_range);
7487 cg.body.writeOperand(Id, ge);
7488 cg.body.writeOperand(Id, le);
7489 case_cond = if (case_cond) |prev| blk: {
7490 const combined = cg.module.allocId();
7491 try cg.body.emitRaw(gpa, .OpLogicalOr, 4);
7492 cg.body.writeOperand(Id, bool_ty_id);
7493 cg.body.writeOperand(Id, combined);
7494 cg.body.writeOperand(Id, prev);
7495 cg.body.writeOperand(Id, in_range);
7496 break :blk combined;
7497 } else in_range;
7498 }
74857499
7486 if (cg.control_flow == .structured) {7500 const case_label = case_labels.at(case.idx);
7487 try incoming_structured_blocks.ensureUnusedCapacity(gpa, num_cases + 1);7501 const is_last = case.idx == last_range_case.?;
7502 const next_check = if (is_last) default_label else cg.module.allocId();
7503
7504 try cg.body.emit(gpa, .OpSelectionMerge, .{
7505 .merge_block = next_check,
7506 .selection_control = .{},
7507 });
7508
7509 try cg.body.emit(gpa, .OpBranchConditional, .{
7510 .condition = case_cond.?,
7511 .true_label = case_label,
7512 .false_label = next_check,
7513 });
7514
7515 if (!is_last) {
7516 try cg.beginSpvBlock(next_check);
7517 }
7518 }
7488 }7519 }
74897520
7490 // Now, finally, we can start emitting each of the cases.7521 // emit bodies
7491 var it = switch_br.iterateCases();7522 var it = switch_br.iterateCases();
7492 while (it.next()) |case| {7523 while (it.next()) |case| {
7493 const label = case_labels.at(case.idx);7524 const label = case_labels.at(case.idx);
74947525
7495 try cg.beginSpvBlock(label);7526 try cg.beginSpvBlock(label);
74967527
7497 switch (cg.control_flow) {7528 const next_block = try cg.genStructuredBody(.selection, case.body);
7498 .structured => {7529 incoming_structured_blocks.appendAssumeCapacity(.{
7499 const next_block = try cg.genStructuredBody(.selection, case.body);7530 .src_label = cg.block_label,
7500 incoming_structured_blocks.appendAssumeCapacity(.{7531 .next_block = next_block,
7501 .src_label = cg.block_label,7532 });
7502 .next_block = next_block,
7503 });
75047533
7505 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label.? });7534 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
7506 },
7507 .unstructured => {
7508 try cg.genBody(case.body);
7509 },
7510 }
7511 }7535 }
75127536
7513 const else_body = it.elseBody();7537 const else_body = blk: {
7514 try cg.beginSpvBlock(default);7538 var it_else = switch_br.iterateCases();
7539 while (it_else.next()) |_| {}
7540 break :blk it_else.elseBody();
7541 };
7542 try cg.beginSpvBlock(default_label);
7515 if (else_body.len != 0) {7543 if (else_body.len != 0) {
7516 switch (cg.control_flow) {7544 const next_block = try cg.genStructuredBody(.selection, else_body);
7517 .structured => {7545 incoming_structured_blocks.appendAssumeCapacity(.{
7518 const next_block = try cg.genStructuredBody(.selection, else_body);7546 .src_label = cg.block_label,
7519 incoming_structured_blocks.appendAssumeCapacity(.{7547 .next_block = next_block,
7520 .src_label = cg.block_label,7548 });
7521 .next_block = next_block,
7522 });
75237549
7524 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label.? });7550 try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
7525 },
7526 .unstructured => {
7527 try cg.genBody(else_body);
7528 },
7529 }
7530 } else {7551 } else {
7531 try cg.body.emit(gpa, .OpUnreachable, {});7552 try cg.body.emit(gpa, .OpUnreachable, {});
7532 }7553 }
75337554
7534 if (cg.control_flow == .structured) {7555 try cg.beginSpvBlock(merge_label);
7535 try cg.beginSpvBlock(merge_label.?);7556 const next_block = try cg.structuredNextBlock(incoming_structured_blocks.items);
7536 const next_block = try cg.structuredNextBlock(incoming_structured_blocks.items);7557 try cg.structuredBreak(next_block);
7537 try cg.structuredBreak(next_block);7558}
7559
7560fn airLoopSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
7561 const gpa = cg.module.gpa;
7562 const zcu = cg.module.zcu;
7563 const target = cg.module.zcu.getTarget();
7564 const switch_br = cg.air.unwrapSwitch(inst);
7565 const cond_ty = cg.typeOf(switch_br.operand);
7566 const initial_cond = try cg.resolve(switch_br.operand);
7567 var initial_cond_indirect = try cg.convertToIndirect(cond_ty, initial_cond);
7568
7569 const cond_words: u32 = switch (cond_ty.zigTypeTag(zcu)) {
7570 .bool, .error_set => 1,
7571 .int => blk: {
7572 const bits = cond_ty.intInfo(zcu).bits;
7573 const backing_bits, const big_int = cg.module.backingIntBits(bits);
7574 if (big_int) return cg.todo("implement composite int loop switch", .{});
7575 break :blk if (backing_bits <= 32) 1 else 2;
7576 },
7577 .@"enum" => blk: {
7578 const int_ty = cond_ty.intTagType(zcu);
7579 const int_info = int_ty.intInfo(zcu);
7580 const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits);
7581 if (big_int) return cg.todo("implement composite int loop switch", .{});
7582 break :blk if (backing_bits <= 32) 1 else 2;
7583 },
7584 .pointer => blk: {
7585 initial_cond_indirect = try cg.intFromPtr(initial_cond_indirect);
7586 break :blk target.ptrBitWidth() / 32;
7587 },
7588 else => return cg.todo("implement loop switch for type {s}", .{@tagName(cond_ty.zigTypeTag(zcu))}),
7589 };
7590
7591 const cond_ty_id = try cg.resolveType(cond_ty, .indirect);
7592 const cond_var = try cg.alloc(cond_ty_id, null);
7593 try cg.store(cond_ty, cond_var, initial_cond_indirect, .{});
7594
7595 const num_cases = switch_br.cases_len;
7596
7597 var num_conditions: u32 = 0;
7598 var last_range_case: ?u32 = null;
7599 {
7600 var it = switch_br.iterateCases();
7601 while (it.next()) |case| {
7602 if (case.ranges.len > 0) {
7603 last_range_case = case.idx;
7604 } else {
7605 num_conditions += @intCast(case.items.len);
7606 }
7607 }
7538 }7608 }
7609
7610 const case_labels = cg.module.allocIds(num_cases);
7611 const default_label = cg.module.allocId();
7612 const switch_default = if (last_range_case != null) cg.module.allocId() else default_label;
7613
7614 const header_label = cg.module.allocId();
7615 const loop_merge = cg.module.allocId();
7616 const continue_label = cg.module.allocId();
7617 const switch_merge = cg.module.allocId();
7618 const body_label = cg.module.allocId();
7619
7620 // switch_dispatch signals "continue the loop" by using this sentinel as the
7621 // next_block in structuredBreak. at switch_merge, a phi + comparison distinguishes
7622 // dispatch (continue) from break (exit)
7623 const dispatch_sentinel = try cg.constInt(.u32, @intFromEnum(inst));
7624
7625 try cg.loop_switches.putNoClobber(gpa, inst, .{
7626 .cond_var = cond_var,
7627 .continue_label = dispatch_sentinel,
7628 });
7629 defer assert(cg.loop_switches.remove(inst));
7630
7631 try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
7632 try cg.beginSpvBlock(header_label);
7633
7634 try cg.body.emit(gpa, .OpLoopMerge, .{
7635 .merge_block = loop_merge,
7636 .continue_target = continue_label,
7637 .loop_control = .{},
7638 });
7639
7640 try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
7641 try cg.beginSpvBlock(body_label);
7642
7643 const cond = try cg.load(cond_ty, cond_var, .{});
7644 const cond_indirect = try cg.convertToIndirect(cond_ty, cond);
7645
7646 try cg.body.emit(gpa, .OpSelectionMerge, .{
7647 .merge_block = switch_merge,
7648 .selection_control = .{},
7649 });
7650
7651 try cg.body.emitRaw(gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions);
7652 cg.body.writeOperand(Id, cond_indirect);
7653 cg.body.writeOperand(Id, switch_default);
7654
7655 {
7656 var it = switch_br.iterateCases();
7657 while (it.next()) |case| {
7658 if (case.ranges.len > 0) continue;
7659 const label = case_labels.at(case.idx);
7660 for (case.items) |item| {
7661 const value: Value = .fromInterned(item.toInterned().?);
7662 const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) {
7663 .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu),
7664 .@"enum" => value.intFromEnum(zcu).toUnsignedInt(zcu),
7665 .error_set => value.getErrorInt(zcu),
7666 .pointer => value.toUnsignedInt(zcu),
7667 else => unreachable,
7668 };
7669 const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) {
7670 1 => .{ .uint32 = @intCast(int_val) },
7671 2 => .{ .uint64 = int_val },
7672 else => unreachable,
7673 };
7674 cg.body.writeOperand(spec.LiteralContextDependentNumber, int_lit);
7675 cg.body.writeOperand(Id, label);
7676 }
7677 }
7678 }
7679
7680 var incoming_structured_blocks: std.ArrayList(Block.Incoming) = .empty;
7681 defer incoming_structured_blocks.deinit(gpa);
7682 try incoming_structured_blocks.ensureUnusedCapacity(gpa, num_cases + 1);
7683
7684 if (last_range_case != null) {
7685 const cond_tmp: Temporary = .init(cond_ty, cond);
7686 const bool_ty_id = try cg.resolveType(.bool, .direct);
7687
7688 try cg.beginSpvBlock(switch_default);
7689
7690 var it_range = switch_br.iterateCases();
7691 while (it_range.next()) |case| {
7692 if (case.ranges.len == 0) continue;
7693
7694 var case_cond: ?Id = null;
7695
7696 for (case.items) |item| {
7697 const item_tmp: Temporary = try cg.temporary(item);
7698 const eq = try (try cg.cmp(.eq, cond_tmp, item_tmp)).materialize(cg);
7699 case_cond = if (case_cond) |prev| blk: {
7700 const combined = cg.module.allocId();
7701 try cg.body.emitRaw(gpa, .OpLogicalOr, 4);
7702 cg.body.writeOperand(Id, bool_ty_id);
7703 cg.body.writeOperand(Id, combined);
7704 cg.body.writeOperand(Id, prev);
7705 cg.body.writeOperand(Id, eq);
7706 break :blk combined;
7707 } else eq;
7708 }
7709
7710 for (case.ranges) |range| {
7711 const lo_tmp: Temporary = try cg.temporary(range[0]);
7712 const hi_tmp: Temporary = try cg.temporary(range[1]);
7713 const ge = try (try cg.cmp(.gte, cond_tmp, lo_tmp)).materialize(cg);
7714 const le = try (try cg.cmp(.lte, cond_tmp, hi_tmp)).materialize(cg);
7715 const in_range = cg.module.allocId();
7716 try cg.body.emitRaw(gpa, .OpLogicalAnd, 4);
7717 cg.body.writeOperand(Id, bool_ty_id);
7718 cg.body.writeOperand(Id, in_range);
7719 cg.body.writeOperand(Id, ge);
7720 cg.body.writeOperand(Id, le);
7721 case_cond = if (case_cond) |prev| blk: {
7722 const combined = cg.module.allocId();
7723 try cg.body.emitRaw(gpa, .OpLogicalOr, 4);
7724 cg.body.writeOperand(Id, bool_ty_id);
7725 cg.body.writeOperand(Id, combined);
7726 cg.body.writeOperand(Id, prev);
7727 cg.body.writeOperand(Id, in_range);
7728 break :blk combined;
7729 } else in_range;
7730 }
7731
7732 const case_label = case_labels.at(case.idx);
7733 const is_last = case.idx == last_range_case.?;
7734 const next_check = if (is_last) default_label else cg.module.allocId();
7735
7736 try cg.body.emit(gpa, .OpSelectionMerge, .{
7737 .merge_block = next_check,
7738 .selection_control = .{},
7739 });
7740
7741 try cg.body.emit(gpa, .OpBranchConditional, .{
7742 .condition = case_cond.?,
7743 .true_label = case_label,
7744 .false_label = next_check,
7745 });
7746
7747 if (!is_last) {
7748 try cg.beginSpvBlock(next_check);
7749 }
7750 }
7751 }
7752
7753 {
7754 var it = switch_br.iterateCases();
7755 while (it.next()) |case| {
7756 const label = case_labels.at(case.idx);
7757 try cg.beginSpvBlock(label);
7758
7759 const next_block = try cg.genStructuredBody(.selection, case.body);
7760 incoming_structured_blocks.appendAssumeCapacity(.{
7761 .src_label = cg.block_label,
7762 .next_block = next_block,
7763 });
7764 try cg.body.emit(gpa, .OpBranch, .{ .target_label = switch_merge });
7765 }
7766 }
7767
7768 const else_body = blk: {
7769 var it_else = switch_br.iterateCases();
7770 while (it_else.next()) |_| {}
7771 break :blk it_else.elseBody();
7772 };
7773 try cg.beginSpvBlock(default_label);
7774 if (else_body.len != 0) {
7775 const next_block = try cg.genStructuredBody(.selection, else_body);
7776 incoming_structured_blocks.appendAssumeCapacity(.{
7777 .src_label = cg.block_label,
7778 .next_block = next_block,
7779 });
7780 try cg.body.emit(gpa, .OpBranch, .{ .target_label = switch_merge });
7781 } else {
7782 try cg.body.emit(gpa, .OpUnreachable, {});
7783 }
7784
7785 try cg.beginSpvBlock(switch_merge);
7786 const next_block = try cg.structuredNextBlock(incoming_structured_blocks.items);
7787
7788 const is_dispatch = cg.module.allocId();
7789 const bool_ty_id = try cg.resolveType(.bool, .direct);
7790 try cg.body.emit(gpa, .OpIEqual, .{
7791 .id_result_type = bool_ty_id,
7792 .id_result = is_dispatch,
7793 .operand_1 = next_block,
7794 .operand_2 = dispatch_sentinel,
7795 });
7796
7797 const dispatch_check_merge = cg.module.allocId();
7798 try cg.body.emit(gpa, .OpSelectionMerge, .{
7799 .merge_block = dispatch_check_merge,
7800 .selection_control = .{},
7801 });
7802 const exit_block = cg.module.allocId();
7803 try cg.body.emit(gpa, .OpBranchConditional, .{
7804 .condition = is_dispatch,
7805 .true_label = dispatch_check_merge,
7806 .false_label = exit_block,
7807 });
7808
7809 try cg.beginSpvBlock(exit_block);
7810 try cg.body.emit(gpa, .OpBranch, .{ .target_label = loop_merge });
7811
7812 try cg.beginSpvBlock(dispatch_check_merge);
7813 try cg.body.emit(gpa, .OpBranch, .{ .target_label = continue_label });
7814
7815 try cg.beginSpvBlock(continue_label);
7816 try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
7817
7818 try cg.beginSpvBlock(loop_merge);
7819 try cg.structuredBreak(next_block);
7820}
7821
7822fn airSwitchDispatch(cg: *CodeGen, inst: Air.Inst.Index) !void {
7823 const br = cg.air.instructions.items(.data)[@intFromEnum(inst)].br;
7824 const loop_switch = cg.loop_switches.get(br.block_inst).?;
7825 const cond_ty = cg.typeOf(br.operand);
7826 const operand = try cg.resolve(br.operand);
7827 const operand_indirect = try cg.convertToIndirect(cond_ty, operand);
7828
7829 try cg.store(cond_ty, loop_switch.cond_var, operand_indirect, .{});
7830 try cg.structuredBreak(loop_switch.continue_label);
7539}7831}
75407832
7541fn airUnreach(cg: *CodeGen) !void {7833fn airUnreach(cg: *CodeGen) !void {
...@@ -7743,9 +8035,19 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)...@@ -7743,9 +8035,19 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
7743 // temporary params buffer.8035 // temporary params buffer.
7744 const arg_ty = cg.typeOf(arg);8036 const arg_ty = cg.typeOf(arg);
7745 if (!arg_ty.hasRuntimeBits(zcu)) continue;8037 if (!arg_ty.hasRuntimeBits(zcu)) continue;
7746 const arg_id = try cg.resolve(arg);
77478038
7748 params[n_params] = arg_id;8039 if (arg_ty.zigTypeTag(zcu) == .pointer and !arg_ty.isSlice(zcu) and
8040 !arg_ty.childType(zcu).hasRuntimeBits(zcu))
8041 {
8042 // in logical addressing, pointer arguments to function calls
8043 // must be memory object declarations (OpVariable). for pointers to
8044 // zero-sized types, the source value may not be a variable, so just
8045 // allocate a dummy one.
8046 const child_ty_id = try cg.resolveType(arg_ty.childType(zcu), .indirect);
8047 params[n_params] = try cg.alloc(child_ty_id, null);
8048 } else {
8049 params[n_params] = try cg.resolve(arg);
8050 }
7749 n_params += 1;8051 n_params += 1;
7750 }8052 }
77518053
src/codegen/spirv/Module.zig+7
...@@ -773,6 +773,13 @@ pub fn structType(...@@ -773,6 +773,13 @@ pub fn structType(
773 return result_id;773 return result_id;
774}774}
775775
776pub fn structFields(module: *const Module, struct_ty_id: Id) ?[]const Id {
777 for (module.cache.struct_types.keys(), module.cache.struct_types.values()) |key, val| {
778 if (val == struct_ty_id) return key.fields;
779 }
780 return null;
781}
782
776pub fn functionType(module: *Module, return_ty_id: Id, param_type_ids: []const Id) !Id {783pub fn functionType(module: *Module, return_ty_id: Id, param_type_ids: []const Id) !Id {
777 if (module.cache.fn_types.get(.{784 if (module.cache.fn_types.get(.{
778 .return_ty = return_ty_id,785 .return_ty = return_ty_id,
test/behavior/align.zig-6
...@@ -101,8 +101,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {...@@ -101,8 +101,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
101}101}
102102
103test "@alignCast pointers" {103test "@alignCast pointers" {
104 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
105
106 var x: u32 align(4) = 1;104 var x: u32 align(4) = 1;
107 expectsOnly1(&x);105 expectsOnly1(&x);
108 try expect(x == 2);106 try expect(x == 2);
...@@ -223,7 +221,6 @@ test "alignment and size of structs with 128-bit fields" {...@@ -223,7 +221,6 @@ test "alignment and size of structs with 128-bit fields" {
223test "implicitly decreasing slice alignment" {221test "implicitly decreasing slice alignment" {
224 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
225 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;223 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
226
227 const a: u32 align(4) = 3;224 const a: u32 align(4) = 3;
228 const b: u32 align(8) = 4;225 const b: u32 align(8) = 4;
229 try expect(addUnalignedSlice(@as(*const [1]u32, &a)[0..], @as(*const [1]u32, &b)[0..]) == 7);226 try expect(addUnalignedSlice(@as(*const [1]u32, &a)[0..], @as(*const [1]u32, &b)[0..]) == 7);
...@@ -265,8 +262,6 @@ test "return error union with 128-bit integer" {...@@ -265,8 +262,6 @@ test "return error union with 128-bit integer" {
265 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
268 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
269
270 try expect(3 == try give());265 try expect(3 == try give());
271}266}
272fn give() anyerror!u128 {267fn give() anyerror!u128 {
...@@ -278,7 +273,6 @@ test "page aligned array on stack" {...@@ -278,7 +273,6 @@ test "page aligned array on stack" {
278 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO274 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
280 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
281
282 // Large alignment value to make it hard to accidentally pass.276 // Large alignment value to make it hard to accidentally pass.
283 var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };277 var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
284 var number1: u8 align(16) = 42;278 var number1: u8 align(16) = 42;
test/behavior/array.zig-6
...@@ -22,8 +22,6 @@ test "array to slice" {...@@ -22,8 +22,6 @@ test "array to slice" {
22test "arrays" {22test "arrays" {
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
26
27 var array: [5]u32 = undefined;25 var array: [5]u32 = undefined;
2826
29 var i: u32 = 0;27 var i: u32 = 0;
...@@ -51,7 +49,6 @@ test "runtime array concat with comptime slice" {...@@ -51,7 +49,6 @@ test "runtime array concat with comptime slice" {
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
54
55 var a: [1]u8 = .{1};52 var a: [1]u8 = .{1};
56 const b = (comptime @as([]const u8, &.{0})) ++ &a;53 const b = (comptime @as([]const u8, &.{0})) ++ &a;
57 const c = &a ++ (comptime @as([]const u8, &.{0}));54 const c = &a ++ (comptime @as([]const u8, &.{0}));
...@@ -1072,8 +1069,6 @@ test "initialize many-pointer with reference to empty array initializer" {...@@ -1072,8 +1069,6 @@ test "initialize many-pointer with reference to empty array initializer" {
1072}1069}
10731070
1074test "initialize sentinel-terminated slice with reference to empty array initializer" {1071test "initialize sentinel-terminated slice with reference to empty array initializer" {
1075 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1076
1077 const a: [:0]const u8 = &.{};1072 const a: [:0]const u8 = &.{};
1078 comptime assert(a.len == 0);1073 comptime assert(a.len == 0);
1079 comptime assert(a[0] == 0);1074 comptime assert(a[0] == 0);
...@@ -1081,7 +1076,6 @@ test "initialize sentinel-terminated slice with reference to empty array initial...@@ -1081,7 +1076,6 @@ test "initialize sentinel-terminated slice with reference to empty array initial
10811076
1082test "initialize sentinel-terminated many-pointer with reference to empty array initializer" {1077test "initialize sentinel-terminated many-pointer with reference to empty array initializer" {
1083 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1078 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1084
1085 const a: [*:0]const u8 = &.{};1079 const a: [*:0]const u8 = &.{};
1086 comptime assert(a[0] == 0);1080 comptime assert(a[0] == 0);
1087}1081}
test/behavior/asm.zig-1
...@@ -82,7 +82,6 @@ test "sized integer/float in asm input" {...@@ -82,7 +82,6 @@ test "sized integer/float in asm input" {
82 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;85 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8786
88 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly87 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
test/behavior/basic.zig+1-1
...@@ -302,7 +302,7 @@ test "compile time global reinterpret" {...@@ -302,7 +302,7 @@ test "compile time global reinterpret" {
302}302}
303303
304test "cast undefined" {304test "cast undefined" {
305 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;305 // if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
307307
308 const array: [100]u8 = undefined;308 const array: [100]u8 = undefined;
test/behavior/bitcast.zig-6
...@@ -23,8 +23,6 @@ test "@bitCast iX -> uX (8, 16, 128)" {...@@ -23,8 +23,6 @@ test "@bitCast iX -> uX (8, 16, 128)" {
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;25 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
27
28 const bit_values = [_]usize{ 8, 16, 128 };26 const bit_values = [_]usize{ 8, 16, 128 };
2927
30 inline for (bit_values) |bits| {28 inline for (bit_values) |bits| {
...@@ -37,9 +35,6 @@ test "@bitCast iX -> uX exotic integers" {...@@ -37,9 +35,6 @@ test "@bitCast iX -> uX exotic integers" {
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
40 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
41 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
42
43 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };38 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };
4439
45 inline for (bit_values) |bits| {40 inline for (bit_values) |bits| {
...@@ -82,7 +77,6 @@ test "bitcast uX to bytes" {...@@ -82,7 +77,6 @@ test "bitcast uX to bytes" {
82 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;79 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8680
87 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };81 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };
88 inline for (bit_values) |bits| {82 inline for (bit_values) |bits| {
test/behavior/cast.zig-18
...@@ -103,11 +103,6 @@ test "comptime_int @floatFromInt" {...@@ -103,11 +103,6 @@ test "comptime_int @floatFromInt" {
103}103}
104104
105test "@floatFromInt" {105test "@floatFromInt" {
106 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
110
111 const S = struct {106 const S = struct {
112 fn doTheTest() !void {107 fn doTheTest() !void {
113 try testIntToFloat(-2);108 try testIntToFloat(-2);
...@@ -133,13 +128,9 @@ fn testIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -133,13 +128,9 @@ fn testIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {
133128
134test "@intFromFloat > 128 bits" {129test "@intFromFloat > 128 bits" {
135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;130 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;131 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
139132
140 try testIntFromFloat(f16, 1024, u140, 1024);
141 try testIntFromFloat(f16, -1024, i140, -1024);133 try testIntFromFloat(f16, -1024, i140, -1024);
142
143 try testIntFromFloat(f32, 1 << 24, u140, 1 << 24);134 try testIntFromFloat(f32, 1 << 24, u140, 1 << 24);
144 try testIntFromFloat(f32, -1 << 24, i140, -1 << 24);135 try testIntFromFloat(f32, -1 << 24, i140, -1 << 24);
145136
...@@ -161,13 +152,10 @@ test "@floatFromInt > 128 bits" {...@@ -161,13 +152,10 @@ test "@floatFromInt > 128 bits" {
161 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
163 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;154 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
165155
166 try testFloatFromInt(u140, 1024, f16, 1024);156 try testFloatFromInt(u140, 1024, f16, 1024);
167 try testFloatFromInt(i140, -1024, f16, -1024);
168157
169 try testFloatFromInt(u140, 1 << 24, f32, 1 << 24);158 try testFloatFromInt(u140, 1 << 24, f32, 1 << 24);
170 try testFloatFromInt(i140, -1 << 24, f32, -1 << 24);
171159
172 try testFloatFromInt(u200, 1 << 53, f64, 1 << 53);160 try testFloatFromInt(u200, 1 << 53, f64, 1 << 53);
173 try testFloatFromInt(i200, -1 << 53, f64, -1 << 53);161 try testFloatFromInt(i200, -1 << 53, f64, -1 << 53);
...@@ -282,8 +270,6 @@ test "type coercion from int to float" {...@@ -282,8 +270,6 @@ test "type coercion from int to float" {
282test "@intFromFloat" {270test "@intFromFloat" {
283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO271 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
286
287 try testIntFromFloats();273 try testIntFromFloats();
288 try comptime testIntFromFloats();274 try comptime testIntFromFloats();
289}275}
...@@ -347,7 +333,6 @@ fn expectTruncCast(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -347,7 +333,6 @@ fn expectTruncCast(comptime F: type, f: F, comptime I: type, i: I) !void {
347test "implicitly cast indirect pointer to maybe-indirect pointer" {333test "implicitly cast indirect pointer to maybe-indirect pointer" {
348 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO334 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;335 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
350
351 const S = struct {336 const S = struct {
352 const Self = @This();337 const Self = @This();
353 x: u8,338 x: u8,
...@@ -431,11 +416,9 @@ test "implicit cast from *[N]T to [*c]T" {...@@ -431,11 +416,9 @@ test "implicit cast from *[N]T to [*c]T" {
431 var y: [*c]u16 = &x;416 var y: [*c]u16 = &x;
432417
433 try expect(std.mem.eql(u16, x[0..4], y[0..4]));418 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
434 x[0] = 8;
435 y[3] = 6;419 y[3] = 6;
436 try expect(std.mem.eql(u16, x[0..4], y[0..4]));420 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
437}421}
438
439test "*usize to *void" {422test "*usize to *void" {
440 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;423 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
441424
...@@ -510,7 +493,6 @@ test "array coercion to undefined at runtime" {...@@ -510,7 +493,6 @@ test "array coercion to undefined at runtime" {
510493
511 var array = [4]u8{ 3, 4, 5, 6 };494 var array = [4]u8{ 3, 4, 5, 6 };
512 var undefined_val = [4]u8{ 0xAA, 0xAA, 0xAA, 0xAA };495 var undefined_val = [4]u8{ 0xAA, 0xAA, 0xAA, 0xAA };
513
514 try expect(std.mem.eql(u8, &array, &array));496 try expect(std.mem.eql(u8, &array, &array));
515 array = undefined;497 array = undefined;
516 try expect(std.mem.eql(u8, &array, &undefined_val));498 try expect(std.mem.eql(u8, &array, &undefined_val));
test/behavior/cast_int.zig-6
...@@ -8,9 +8,6 @@ const minInt = std.math.minInt;...@@ -8,9 +8,6 @@ const minInt = std.math.minInt;
8test "@intCast i32 to u7" {8test "@intCast i32 to u7" {
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13
14 var x: u128 = maxInt(u128);11 var x: u128 = maxInt(u128);
15 var y: i32 = 120;12 var y: i32 = 120;
16 _ = .{ &x, &y };13 _ = .{ &x, &y };
...@@ -145,9 +142,7 @@ fn testIntCast(comptime S: type, a: S, comptime D: type, expected: D) !void {...@@ -145,9 +142,7 @@ fn testIntCast(comptime S: type, a: S, comptime D: type, expected: D) !void {
145test "@intCast <= 64 bits" {142test "@intCast <= 64 bits" {
146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;143 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;144 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
148
149 try testIntCast(i32, minInt(i32), i64, minInt(i32));145 try testIntCast(i32, minInt(i32), i64, minInt(i32));
150 try testIntCast(i32, maxInt(i32), i64, maxInt(i32));
151 try testIntCast(u32, maxInt(u32), u64, maxInt(u32));146 try testIntCast(u32, maxInt(u32), u64, maxInt(u32));
152 try testIntCast(u32, maxInt(i32), i64, maxInt(i32));147 try testIntCast(u32, maxInt(i32), i64, maxInt(i32));
153 try testIntCast(u32, maxInt(u32), i64, maxInt(u32));148 try testIntCast(u32, maxInt(u32), i64, maxInt(u32));
...@@ -174,7 +169,6 @@ test "@intCast > 128 bits" {...@@ -174,7 +169,6 @@ test "@intCast > 128 bits" {
174 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;169 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
175170
176 try testIntCast(u8, 123, u140, 123);171 try testIntCast(u8, 123, u140, 123);
177 try testIntCast(u64, 1 << 63, u140, 1 << 63);
178 try testIntCast(u127, maxInt(u127), u140, maxInt(u127));172 try testIntCast(u127, maxInt(u127), u140, maxInt(u127));
179 try testIntCast(i8, -42, i140, -42);173 try testIntCast(i8, -42, i140, -42);
180 try testIntCast(i64, minInt(i64), i140, minInt(i64));174 try testIntCast(i64, minInt(i64), i140, minInt(i64));
test/behavior/comptime_memory.zig-3
...@@ -431,8 +431,6 @@ test "type pun @ptrFromInt" {...@@ -431,8 +431,6 @@ test "type pun @ptrFromInt" {
431}431}
432432
433test "type pun null pointer-like optional" {433test "type pun null pointer-like optional" {
434 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
435
436 const p: ?*u8 = null;434 const p: ?*u8 = null;
437 // note that expectEqual hides the bug435 // note that expectEqual hides the bug
438 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);436 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);
...@@ -518,7 +516,6 @@ fn fieldPtrTest() u32 {...@@ -518,7 +516,6 @@ fn fieldPtrTest() u32 {
518}516}
519test "pointer in aggregate field can mutate comptime state" {517test "pointer in aggregate field can mutate comptime state" {
520 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;518 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
521
522 try comptime std.testing.expect(fieldPtrTest() == 2);519 try comptime std.testing.expect(fieldPtrTest() == 2);
523}520}
524521
test/behavior/defer.zig-3
...@@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual;...@@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual;
5const expectError = std.testing.expectError;5const expectError = std.testing.expectError;
66
7test "break and continue inside loop inside defer expression" {7test "break and continue inside loop inside defer expression" {
8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
9
10 testBreakContInDefer(10);8 testBreakContInDefer(10);
11 comptime testBreakContInDefer(10);9 comptime testBreakContInDefer(10);
12}10}
...@@ -111,7 +109,6 @@ test "mixing normal and error defers" {...@@ -111,7 +109,6 @@ test "mixing normal and error defers" {
111test "simple else prong doesn't emit an error for unreachable else prong" {109test "simple else prong doesn't emit an error for unreachable else prong" {
112 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
113 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
114
115 const S = struct {112 const S = struct {
116 fn foo() error{Foo}!void {113 fn foo() error{Foo}!void {
117 return error.Foo;114 return error.Foo;
test/behavior/enum.zig-6
...@@ -931,9 +931,7 @@ test "constant enum initialization with differing sizes" {...@@ -931,9 +931,7 @@ test "constant enum initialization with differing sizes" {
931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
932 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;932 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
933 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;933 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
934
935 try test3_1(test3_foo);934 try test3_1(test3_foo);
936 try test3_2(test3_bar);
937}935}
938const Test3Foo = union(enum) {936const Test3Foo = union(enum) {
939 One: void,937 One: void,
...@@ -975,7 +973,6 @@ test "@tagName" {...@@ -975,7 +973,6 @@ test "@tagName" {
975 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO973 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
976 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;974 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
977975
978 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
979 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));976 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
980}977}
981978
...@@ -990,9 +987,7 @@ test "@tagName non-exhaustive enum" {...@@ -990,9 +987,7 @@ test "@tagName non-exhaustive enum" {
990 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;987 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
991 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO988 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
992 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;989 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
993 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
994990
995 try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
996 comptime assert(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));991 comptime assert(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
997}992}
998const NonExhaustive = enum(u8) { A, B, _ };993const NonExhaustive = enum(u8) { A, B, _ };
...@@ -1034,7 +1029,6 @@ test "@tagName on enum literals" {...@@ -1034,7 +1029,6 @@ test "@tagName on enum literals" {
1034 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1029 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10351030
1036 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));1031 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1037 comptime assert(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1038}1032}
10391033
1040test "tag name with signed enum values" {1034test "tag name with signed enum values" {
test/behavior/error.zig-13
...@@ -145,19 +145,12 @@ test "implicit cast to optional to error union to return result loc" {...@@ -145,19 +145,12 @@ test "implicit cast to optional to error union to return result loc" {
145}145}
146146
147test "fn returning empty error set can be passed as fn returning any error" {147test "fn returning empty error set can be passed as fn returning any error" {
148 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
149
150 entry();
151 comptime entry();
152}148}
153149
154test "fn returning empty error set can be passed as fn returning any error - pointer" {150test "fn returning empty error set can be passed as fn returning any error - pointer" {
155 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
156
157 entryPtr();152 entryPtr();
158 comptime entryPtr();
159}153}
160
161fn entry() void {154fn entry() void {
162 foo2(bar2);155 foo2(bar2);
163}156}
...@@ -369,10 +362,8 @@ test "error: Infer error set from literals" {...@@ -369,10 +362,8 @@ test "error: Infer error set from literals" {
369 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;362 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
370363
371 _ = nullLiteral("n") catch |err| handleErrors(err);364 _ = nullLiteral("n") catch |err| handleErrors(err);
372 _ = floatLiteral("n") catch |err| handleErrors(err);
373 _ = intLiteral("n") catch |err| handleErrors(err);365 _ = intLiteral("n") catch |err| handleErrors(err);
374 _ = comptime nullLiteral("n") catch |err| handleErrors(err);366 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
375 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
376 _ = comptime intLiteral("n") catch |err| handleErrors(err);367 _ = comptime intLiteral("n") catch |err| handleErrors(err);
377}368}
378369
...@@ -511,7 +502,6 @@ test "function pointer with return type that is error union with payload which i...@@ -511,7 +502,6 @@ test "function pointer with return type that is error union with payload which i
511 const Foo = struct {502 const Foo = struct {
512 fun: *const fn (a: i32) (anyerror!*Foo),503 fun: *const fn (a: i32) (anyerror!*Foo),
513 };504 };
514
515 const Err = error{UnspecifiedErr};505 const Err = error{UnspecifiedErr};
516506
517 fn bar(a: i32) anyerror!*Foo {507 fn bar(a: i32) anyerror!*Foo {
...@@ -699,8 +689,6 @@ test "coerce error set to the current inferred error set" {...@@ -699,8 +689,6 @@ test "coerce error set to the current inferred error set" {
699test "error union payload is properly aligned" {689test "error union payload is properly aligned" {
700 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO690 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
701 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO691 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
702 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
703 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
704692
705 const S = struct {693 const S = struct {
706 a: u128,694 a: u128,
...@@ -758,7 +746,6 @@ test "pointer to error union payload" {...@@ -758,7 +746,6 @@ test "pointer to error union payload" {
758 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO746 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
759 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO747 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
760 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;748 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
761 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
762749
763 var err_union: anyerror!u8 = 15;750 var err_union: anyerror!u8 = 15;
764751
test/behavior/floatop.zig-8
...@@ -134,9 +134,6 @@ test "cmp f32" {...@@ -134,9 +134,6 @@ test "cmp f32" {
134}134}
135135
136test "cmp f64" {136test "cmp f64" {
137 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
139
140 try testCmp(f64);137 try testCmp(f64);
141 try comptime testCmp(f64);138 try comptime testCmp(f64);
142}139}
...@@ -146,7 +143,6 @@ test "cmp f128" {...@@ -146,7 +143,6 @@ test "cmp f128" {
146 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;143 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;144 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
148145
149 try testCmp(f128);
150 try comptime testCmp(f128);146 try comptime testCmp(f128);
151}147}
152148
...@@ -154,10 +150,7 @@ test "cmp f80/c_longdouble" {...@@ -154,10 +150,7 @@ test "cmp f80/c_longdouble" {
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;151 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
156 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
158153
159 try testCmp(f80);
160 try comptime testCmp(f80);
161 try testCmp(c_longdouble);154 try testCmp(c_longdouble);
162 try comptime testCmp(c_longdouble);155 try comptime testCmp(c_longdouble);
163}156}
...@@ -232,7 +225,6 @@ test "vector cmp f32" {...@@ -232,7 +225,6 @@ test "vector cmp f32" {
232 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;225 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;227 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
236 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;228 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
237 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;229 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
238230
test/behavior/fn.zig-6
...@@ -292,9 +292,6 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void {...@@ -292,9 +292,6 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void {
292292
293test "call function with empty string" {293test "call function with empty string" {
294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
296
297 acceptsString("");
298}295}
299296
300fn acceptsString(foo: []u8) void {297fn acceptsString(foo: []u8) void {
...@@ -305,9 +302,7 @@ test "function pointers" {...@@ -305,9 +302,7 @@ test "function pointers" {
305 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
307 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;304 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
308
309 const fns = [_]*const @TypeOf(fn1){305 const fns = [_]*const @TypeOf(fn1){
310 &fn1,
311 &fn2,306 &fn2,
312 &fn3,307 &fn3,
313 &fn4,308 &fn4,
...@@ -445,7 +440,6 @@ test "method call with optional and error union first param" {...@@ -445,7 +440,6 @@ test "method call with optional and error union first param" {
445 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;440 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
446441
447 const S = struct {442 const S = struct {
448 x: i32 = 1234,
449443
450 fn opt(s: ?@This()) !void {444 fn opt(s: ?@This()) !void {
451 try expect(s.?.x == 1234);445 try expect(s.?.x == 1234);
test/behavior/generics.zig-4
...@@ -439,8 +439,6 @@ test "return type of generic function is function pointer" {...@@ -439,8 +439,6 @@ test "return type of generic function is function pointer" {
439}439}
440440
441test "coerced function body has inequal value with its uncoerced body" {441test "coerced function body has inequal value with its uncoerced body" {
442 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
443
444 const S = struct {442 const S = struct {
445 const A = B(i32, c);443 const A = B(i32, c);
446 fn c() !i32 {444 fn c() !i32 {
...@@ -488,8 +486,6 @@ test "union in struct captures argument" {...@@ -488,8 +486,6 @@ test "union in struct captures argument" {
488486
489test "function argument tuple used as struct field" {487test "function argument tuple used as struct field" {
490 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
492
493 const S = struct {489 const S = struct {
494 fn DeleagateWithContext(comptime Function: type) type {490 fn DeleagateWithContext(comptime Function: type) type {
495 const ArgArgs = std.meta.ArgsTuple(Function);491 const ArgArgs = std.meta.ArgsTuple(Function);
test/behavior/inline_switch.zig-6
...@@ -34,8 +34,6 @@ test "inline prong ranges" {...@@ -34,8 +34,6 @@ test "inline prong ranges" {
34const E = enum { a, b, c, d };34const E = enum { a, b, c, d };
35test "inline switch enums" {35test "inline switch enums" {
36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
38
39 var x: E = .a;37 var x: E = .a;
40 _ = &x;38 _ = &x;
41 switch (x) {39 switch (x) {
...@@ -49,7 +47,6 @@ test "inline switch unions" {...@@ -49,7 +47,6 @@ test "inline switch unions" {
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;49 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
52
53 var x: U = .a;50 var x: U = .a;
54 _ = &x;51 _ = &x;
55 switch (x) {52 switch (x) {
...@@ -74,8 +71,6 @@ test "inline switch unions" {...@@ -74,8 +71,6 @@ test "inline switch unions" {
7471
75test "inline else bool" {72test "inline else bool" {
76 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
78
79 var a = true;74 var a = true;
80 _ = &a;75 _ = &a;
81 switch (a) {76 switch (a) {
...@@ -87,7 +82,6 @@ test "inline else bool" {...@@ -87,7 +82,6 @@ test "inline else bool" {
87test "inline else error" {82test "inline else error" {
88 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
89 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;84 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
90
91 const Err = error{ a, b, c };85 const Err = error{ a, b, c };
92 var a = Err.a;86 var a = Err.a;
93 _ = &a;87 _ = &a;
test/behavior/maximum_minimum.zig-3
...@@ -304,8 +304,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known...@@ -304,8 +304,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known
304}304}
305305
306test "@min/@max of signed and unsigned runtime integers" {306test "@min/@max of signed and unsigned runtime integers" {
307 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
308
309 var x: i32 = -1;307 var x: i32 = -1;
310 var y: u31 = 1;308 var y: u31 = 1;
311 _ = .{ &x, &y };309 _ = .{ &x, &y };
...@@ -352,7 +350,6 @@ test "@min/@max with runtime signed and unsigned integers of same size" {...@@ -352,7 +350,6 @@ test "@min/@max with runtime signed and unsigned integers of same size" {
352350
353test "@min/@max with runtime vectors of signed and unsigned integers of same size" {351test "@min/@max with runtime vectors of signed and unsigned integers of same size" {
354 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO354 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;355 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/memcpy.zig-1
...@@ -168,7 +168,6 @@ test "@memcpy with sentinel" {...@@ -168,7 +168,6 @@ test "@memcpy with sentinel" {
168}168}
169169
170test "@memcpy no sentinel source into sentinel destination" {170test "@memcpy no sentinel source into sentinel destination" {
171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
172171
173 const S = struct {172 const S = struct {
174 fn doTheTest() void {173 fn doTheTest() void {
test/behavior/merge_error_sets.zig-1
...@@ -13,7 +13,6 @@ fn foo() C!void {...@@ -13,7 +13,6 @@ fn foo() C!void {
1313
14test "merge error sets" {14test "merge error sets" {
15 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1716
18 if (foo()) {17 if (foo()) {
19 @panic("unexpected");18 @panic("unexpected");
test/behavior/muladd.zig-3
...@@ -34,7 +34,6 @@ test "@mulAdd f16" {...@@ -34,7 +34,6 @@ test "@mulAdd f16" {
34 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3535
36 try comptime testMulAdd16();36 try comptime testMulAdd16();
37 try testMulAdd16();
38}37}
3938
40fn testMulAdd16() !void {39fn testMulAdd16() !void {
...@@ -49,9 +48,7 @@ test "@mulAdd f80" {...@@ -49,9 +48,7 @@ test "@mulAdd f80" {
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
54
55 try comptime testMulAdd80();52 try comptime testMulAdd80();
56 try testMulAdd80();53 try testMulAdd80();
57}54}
test/behavior/optional.zig-6
...@@ -338,8 +338,6 @@ test "coerce an anon struct literal to optional struct" {...@@ -338,8 +338,6 @@ test "coerce an anon struct literal to optional struct" {
338test "0-bit child type coerced to optional return ptr result location" {338test "0-bit child type coerced to optional return ptr result location" {
339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
341 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
342
343 const S = struct {341 const S = struct {
344 fn doTheTest() !void {342 fn doTheTest() !void {
345 var y = Foo{};343 var y = Foo{};
...@@ -365,7 +363,6 @@ test "0-bit child type coerced to optional" {...@@ -365,7 +363,6 @@ test "0-bit child type coerced to optional" {
365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;363 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO364 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
367 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;365 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
368
369 const S = struct {366 const S = struct {
370 fn doTheTest() !void {367 fn doTheTest() !void {
371 var it: Foo = .{368 var it: Foo = .{
...@@ -514,8 +511,6 @@ test "mutable optional of noreturn" {...@@ -514,8 +511,6 @@ test "mutable optional of noreturn" {
514}511}
515512
516test "orelse on C pointer" {513test "orelse on C pointer" {
517 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
518
519 // TODO https://github.com/ziglang/zig/issues/6597514 // TODO https://github.com/ziglang/zig/issues/6597
520 const foo: [*c]const u8 = "hey";515 const foo: [*c]const u8 = "hey";
521 const d = foo orelse @compileError("bad");516 const d = foo orelse @compileError("bad");
...@@ -527,7 +522,6 @@ test "alignment of wrapping an optional payload" {...@@ -527,7 +522,6 @@ test "alignment of wrapping an optional payload" {
527 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;522 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
528 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO523 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
529 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;524 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
530 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
531525
532 const S = struct {526 const S = struct {
533 const I = extern struct { x: i128 };527 const I = extern struct { x: i128 };
test/behavior/packed-struct.zig-6
...@@ -227,9 +227,6 @@ test "nested packed structs" {...@@ -227,9 +227,6 @@ test "nested packed structs" {
227test "regular in irregular packed struct" {227test "regular in irregular packed struct" {
228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
230 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
232
233 const Irregular = packed struct {230 const Irregular = packed struct {
234 bar: Regular = Regular{},231 bar: Regular = Regular{},
235 _: u24 = 0,232 _: u24 = 0,
...@@ -249,9 +246,7 @@ test "nested packed struct unaligned" {...@@ -249,9 +246,7 @@ test "nested packed struct unaligned" {
249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
252
253 const S1 = packed struct {249 const S1 = packed struct {
254 a: u4,
255 b: u4,250 b: u4,
256 c: u8,251 c: u8,
257 };252 };
...@@ -408,7 +403,6 @@ test "nested packed struct field pointers" {...@@ -408,7 +403,6 @@ test "nested packed struct field pointers" {
408 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
409 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access404 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
410 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO405 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
411
412 const S2 = packed struct {406 const S2 = packed struct {
413 base: u8,407 base: u8,
414 p0: packed struct {408 p0: packed struct {
test/behavior/pointers.zig-6
...@@ -136,8 +136,6 @@ test "implicit cast single item pointer to C pointer and back" {...@@ -136,8 +136,6 @@ test "implicit cast single item pointer to C pointer and back" {
136}136}
137137
138test "initialize const optional C pointer to null" {138test "initialize const optional C pointer to null" {
139 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
140
141 const a: ?[*c]i32 = null;139 const a: ?[*c]i32 = null;
142 try expect(a == null);140 try expect(a == null);
143 comptime assert(a == null);141 comptime assert(a == null);
...@@ -146,7 +144,6 @@ test "initialize const optional C pointer to null" {...@@ -146,7 +144,6 @@ test "initialize const optional C pointer to null" {
146test "assigning integer to C pointer" {144test "assigning integer to C pointer" {
147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
148 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
149
150 var x: i32 = 0;147 var x: i32 = 0;
151 var y: i32 = 1;148 var y: i32 = 1;
152 var ptr: [*c]u8 = 0;149 var ptr: [*c]u8 = 0;
...@@ -645,8 +642,6 @@ test "result type preserved through multiple references" {...@@ -645,8 +642,6 @@ test "result type preserved through multiple references" {
645}642}
646643
647test "result type found through optional pointer" {644test "result type found through optional pointer" {
648 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
649
650 const ptr1: ?*const u32 = &@intCast(123);645 const ptr1: ?*const u32 = &@intCast(123);
651 const ptr2: ?[]const u8 = &.{ @intCast(123), @truncate(0xABCD) };646 const ptr2: ?[]const u8 = &.{ @intCast(123), @truncate(0xABCD) };
652 try expect(ptr1.?.* == 123);647 try expect(ptr1.?.* == 123);
...@@ -700,7 +695,6 @@ fn constant() !void {...@@ -700,7 +695,6 @@ fn constant() !void {
700test "pointer-to-array constness for zero-size elements, var" {695test "pointer-to-array constness for zero-size elements, var" {
701 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO696 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
702 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;697 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
703
704 try mutable();698 try mutable();
705 try comptime mutable();699 try comptime mutable();
706}700}
test/behavior/shuffle.zig-3
...@@ -54,8 +54,6 @@ test "@shuffle int strange sizes" {...@@ -54,8 +54,6 @@ test "@shuffle int strange sizes" {
54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;56 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
57 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
58
59 try comptime testShuffle(2, 2, 2);57 try comptime testShuffle(2, 2, 2);
60 try testShuffle(2, 2, 2);58 try testShuffle(2, 2, 2);
61 try comptime testShuffle(4, 4, 4);59 try comptime testShuffle(4, 4, 4);
...@@ -136,7 +134,6 @@ test "@shuffle bool 1" {...@@ -136,7 +134,6 @@ test "@shuffle bool 1" {
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;135 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
138 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
139
140 const S = struct {137 const S = struct {
141 fn doTheTest() !void {138 fn doTheTest() !void {
142 var x: @Vector(4, bool) = [4]bool{ false, true, false, true };139 var x: @Vector(4, bool) = [4]bool{ false, true, false, true };
test/behavior/sizeof_and_typeof.zig-3
...@@ -211,8 +211,6 @@ test "@sizeOf comparison against zero" {...@@ -211,8 +211,6 @@ test "@sizeOf comparison against zero" {
211}211}
212212
213test "hardcoded address in typeof expression" {213test "hardcoded address in typeof expression" {
214 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
215
216 const S = struct {214 const S = struct {
217 fn func() @TypeOf(@as(*[]u8, @ptrFromInt(0x10)).*[0]) {215 fn func() @TypeOf(@as(*[]u8, @ptrFromInt(0x10)).*[0]) {
218 return 0;216 return 0;
...@@ -301,7 +299,6 @@ test "lazy abi size used in comparison" {...@@ -301,7 +299,6 @@ test "lazy abi size used in comparison" {
301test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {299test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
304
305 const T = struct {302 const T = struct {
306 next: @TypeOf(null, @as(*const @This(), undefined)),303 next: @TypeOf(null, @as(*const @This(), undefined)),
307 };304 };
test/behavior/slice.zig-6
...@@ -173,8 +173,6 @@ test "pass a slice of types to a function" {...@@ -173,8 +173,6 @@ test "pass a slice of types to a function" {
173173
174test "generic malloc free" {174test "generic malloc free" {
175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
176 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
177
178 const a = memAlloc(u8, 10) catch unreachable;176 const a = memAlloc(u8, 10) catch unreachable;
179 memFree(u8, a);177 memFree(u8, a);
180}178}
...@@ -188,7 +186,6 @@ fn memFree(comptime T: type, memory: []T) void {...@@ -188,7 +186,6 @@ fn memFree(comptime T: type, memory: []T) void {
188186
189test "slice of hardcoded address to pointer" {187test "slice of hardcoded address to pointer" {
190 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;188 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
191
192 const S = struct {189 const S = struct {
193 fn doTheTest() !void {190 fn doTheTest() !void {
194 const pointer = @as([*]u8, @ptrFromInt(0x04))[0..2];191 const pointer = @as([*]u8, @ptrFromInt(0x04))[0..2];
...@@ -212,8 +209,6 @@ test "comptime slice of pointer preserves comptime var" {...@@ -212,8 +209,6 @@ test "comptime slice of pointer preserves comptime var" {
212}209}
213210
214test "comptime pointer cast array and then slice" {211test "comptime pointer cast array and then slice" {
215 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
216
217 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };212 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
218213
219 const ptrA: [*]const u8 = @as([*]const u8, @ptrCast(&array));214 const ptrA: [*]const u8 = @as([*]const u8, @ptrCast(&array));
...@@ -229,7 +224,6 @@ test "comptime pointer cast array and then slice" {...@@ -229,7 +224,6 @@ test "comptime pointer cast array and then slice" {
229test "slicing zero length array" {224test "slicing zero length array" {
230 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO225 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
232
233 const s1 = ""[0..];227 const s1 = ""[0..];
234 const s2 = ([_]u32{})[0..];228 const s2 = ([_]u32{})[0..];
235 try expect(s1.len == 0);229 try expect(s1.len == 0);
test/behavior/string_literals.zig-3
...@@ -84,8 +84,6 @@ test "string literal pointer sentinel" {...@@ -84,8 +84,6 @@ test "string literal pointer sentinel" {
84}84}
8585
86test "sentinel slice of string literal" {86test "sentinel slice of string literal" {
87 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
88
89 const string = "Hello!\x00World!";87 const string = "Hello!\x00World!";
90 try std.testing.expect(@TypeOf(string) == *const [13:0]u8);88 try std.testing.expect(@TypeOf(string) == *const [13:0]u8);
9189
...@@ -103,7 +101,6 @@ test "Peer type resolution with string literals and unknown length u8 pointers"...@@ -103,7 +101,6 @@ test "Peer type resolution with string literals and unknown length u8 pointers"
103101
104test "including the sentinel when dereferencing a string literal" {102test "including the sentinel when dereferencing a string literal" {
105 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
106
107 var var_str = "abc";104 var var_str = "abc";
108 const var_derefed = var_str[0 .. var_str.len + 1].*;105 const var_derefed = var_str[0 .. var_str.len + 1].*;
109106
test/behavior/struct.zig-6
...@@ -342,7 +342,6 @@ test "self-referencing struct via array member" {...@@ -342,7 +342,6 @@ test "self-referencing struct via array member" {
342}342}
343343
344test "empty struct method call" {344test "empty struct method call" {
345 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
346 const es = EmptyStruct{};345 const es = EmptyStruct{};
347 try expect(es.method() == 1234);346 try expect(es.method() == 1234);
348}347}
...@@ -379,7 +378,6 @@ const APackedStruct = packed struct {...@@ -379,7 +378,6 @@ const APackedStruct = packed struct {
379test "packed struct" {378test "packed struct" {
380 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
382 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
383 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
384382
385 var foo = APackedStruct{383 var foo = APackedStruct{
...@@ -448,8 +446,6 @@ test "runtime struct initialization of bitfield" {...@@ -448,8 +446,6 @@ test "runtime struct initialization of bitfield" {
448 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;446 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO447 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
451 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
452 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
453449
454 const s1 = Nibbles{450 const s1 = Nibbles{
455 .x = x1,451 .x = x1,
...@@ -489,7 +485,6 @@ test "packed struct fields are ordered from LSB to MSB" {...@@ -489,7 +485,6 @@ test "packed struct fields are ordered from LSB to MSB" {
489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO485 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;487 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
492
493 var all: u64 = 0x7765443322221111;488 var all: u64 = 0x7765443322221111;
494 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;489 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;
495 @memcpy(bytes[0..8], @as([*]u8, @ptrCast(&all)));490 @memcpy(bytes[0..8], @as([*]u8, @ptrCast(&all)));
...@@ -1776,7 +1771,6 @@ test "circular dependency through pointer field of a struct" {...@@ -1776,7 +1771,6 @@ test "circular dependency through pointer field of a struct" {
1776}1771}
17771772
1778test "field calls do not force struct field init resolution" {1773test "field calls do not force struct field init resolution" {
1779 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1780 const S = struct {1774 const S = struct {
1781 x: u32 = blk: {1775 x: u32 = blk: {
1782 _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution1776 _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution
test/behavior/switch.zig-6
...@@ -9,7 +9,6 @@ const maxInt = std.math.maxInt;...@@ -9,7 +9,6 @@ const maxInt = std.math.maxInt;
99
10test "switch with numbers" {10test "switch with numbers" {
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1312
14 try testSwitchWithNumbers(13);13 try testSwitchWithNumbers(13);
15}14}
...@@ -25,7 +24,6 @@ fn testSwitchWithNumbers(x: u32) !void {...@@ -25,7 +24,6 @@ fn testSwitchWithNumbers(x: u32) !void {
2524
26test "switch with all ranges" {25test "switch with all ranges" {
27 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
2927
30 try expect(testSwitchWithAllRanges(50, 3) == 1);28 try expect(testSwitchWithAllRanges(50, 3) == 1);
31 try expect(testSwitchWithAllRanges(101, 0) == 2);29 try expect(testSwitchWithAllRanges(101, 0) == 2);
...@@ -214,8 +212,6 @@ test "undefined.u0" {...@@ -214,8 +212,6 @@ test "undefined.u0" {
214212
215test "switch with disjoint range" {213test "switch with disjoint range" {
216 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO214 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
217 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
218
219 var q: u8 = 0;215 var q: u8 = 0;
220 _ = &q;216 _ = &q;
221 switch (q) {217 switch (q) {
...@@ -226,8 +222,6 @@ test "switch with disjoint range" {...@@ -226,8 +222,6 @@ test "switch with disjoint range" {
226}222}
227223
228test "switch variable for range and multiple prongs" {224test "switch variable for range and multiple prongs" {
229 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
230
231 const S = struct {225 const S = struct {
232 fn doTheTest() !void {226 fn doTheTest() !void {
233 try doTheSwitch(16);227 try doTheSwitch(16);
test/behavior/switch_loop.zig-11
...@@ -7,7 +7,6 @@ test "simple switch loop" {...@@ -7,7 +7,6 @@ test "simple switch loop" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1110
12 const S = struct {11 const S = struct {
13 fn doTheTest() !void {12 fn doTheTest() !void {
...@@ -31,7 +30,6 @@ test "switch loop with ranges" {...@@ -31,7 +30,6 @@ test "switch loop with ranges" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
3533
36 const S = struct {34 const S = struct {
37 fn doTheTest() !void {35 fn doTheTest() !void {
...@@ -52,7 +50,6 @@ test "switch loop on enum" {...@@ -52,7 +50,6 @@ test "switch loop on enum" {
52 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
5653
57 const S = struct {54 const S = struct {
58 const E = enum { a, b, c };55 const E = enum { a, b, c };
...@@ -76,7 +73,6 @@ test "switch loop with error set" {...@@ -76,7 +73,6 @@ test "switch loop with error set" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;73 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
8076
81 const S = struct {77 const S = struct {
82 const E = error{ Foo, Bar, Baz };78 const E = error{ Foo, Bar, Baz };
...@@ -252,7 +248,6 @@ test "switch loop on non-exhaustive enum" {...@@ -252,7 +248,6 @@ test "switch loop on non-exhaustive enum" {
252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO250 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
255 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
256251
257 const S = struct {252 const S = struct {
258 const E = enum(u8) { a, b, c, _ };253 const E = enum(u8) { a, b, c, _ };
...@@ -275,8 +270,6 @@ test "switch loop on non-exhaustive enum" {...@@ -275,8 +270,6 @@ test "switch loop on non-exhaustive enum" {
275test "switch loop with discarded tag capture" {270test "switch loop with discarded tag capture" {
276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
277 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;272 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
279
280 const S = struct {273 const S = struct {
281 const U = union(enum) {274 const U = union(enum) {
282 a: u32,275 a: u32,
...@@ -301,7 +294,6 @@ test "switch loop with discarded tag capture" {...@@ -301,7 +294,6 @@ test "switch loop with discarded tag capture" {
301294
302test "switch loop with single catch-all prong" {295test "switch loop with single catch-all prong" {
303 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;296 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
304
305 const S = struct {297 const S = struct {
306 const E = enum { a, b, c };298 const E = enum { a, b, c };
307 const U = union(E) { a: u32, b: u16, c: u8 };299 const U = union(E) { a: u32, b: u16, c: u8 };
...@@ -469,8 +461,6 @@ test "switch loop with tag capture" {...@@ -469,8 +461,6 @@ test "switch loop with tag capture" {
469}461}
470462
471test "switch loop for error handling" {463test "switch loop for error handling" {
472 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
473
474 const Error = error{ MyError, MyOtherError };464 const Error = error{ MyError, MyOtherError };
475 const S = struct {465 const S = struct {
476 fn doTheTest() !void {466 fn doTheTest() !void {
...@@ -516,7 +506,6 @@ test "switch loop for error handling" {...@@ -516,7 +506,6 @@ test "switch loop for error handling" {
516506
517test "switch loop with packed structs" {507test "switch loop with packed structs" {
518 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;508 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
519
520 const P = packed struct {509 const P = packed struct {
521 a: u7,510 a: u7,
522 b: u20,511 b: u20,
test/behavior/tuple.zig-6
...@@ -105,8 +105,6 @@ test "tuple initializer for var" {...@@ -105,8 +105,6 @@ test "tuple initializer for var" {
105105
106test "array-like initializer for tuple types" {106test "array-like initializer for tuple types" {
107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
109
110 const T = @Tuple(&.{ i32, u8 });108 const T = @Tuple(&.{ i32, u8 });
111 const S = struct {109 const S = struct {
112 fn doTheTest() !void {110 fn doTheTest() !void {
...@@ -172,7 +170,6 @@ test "fieldParentPtr of tuple" {...@@ -172,7 +170,6 @@ test "fieldParentPtr of tuple" {
172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
173 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;171 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
174 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;172 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
175
176 var x: u32 = 0;173 var x: u32 = 0;
177 _ = &x;174 _ = &x;
178 const tuple = .{ x, x };175 const tuple = .{ x, x };
...@@ -217,8 +214,6 @@ test "initializing tuple with mixed comptime-runtime fields" {...@@ -217,8 +214,6 @@ test "initializing tuple with mixed comptime-runtime fields" {
217}214}
218215
219test "initializing anon struct with mixed comptime-runtime fields" {216test "initializing anon struct with mixed comptime-runtime fields" {
220 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
221
222 var x: u32 = 15;217 var x: u32 = 15;
223 _ = &x;218 _ = &x;
224 const T = @TypeOf(.{ .foo = @as(i32, -1234), .bar = x });219 const T = @TypeOf(.{ .foo = @as(i32, -1234), .bar = x });
...@@ -231,7 +226,6 @@ test "tuple in tuple passed to generic function" {...@@ -231,7 +226,6 @@ test "tuple in tuple passed to generic function" {
231 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
232 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO227 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
233 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;228 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
234
235 const S = struct {229 const S = struct {
236 fn pair(x: f32, y: f32) @Tuple(&.{ f32, f32 }) {230 fn pair(x: f32, y: f32) @Tuple(&.{ f32, f32 }) {
237 return .{ x, y };231 return .{ x, y };
test/behavior/union.zig-6
...@@ -885,8 +885,6 @@ test "union no tag with struct member" {...@@ -885,8 +885,6 @@ test "union no tag with struct member" {
885}885}
886886
887test "extern union doesn't trigger field check at comptime" {887test "extern union doesn't trigger field check at comptime" {
888 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
889
890 const U = extern union {888 const U = extern union {
891 x: u32,889 x: u32,
892 y: u8,890 y: u8,
...@@ -901,7 +899,6 @@ test "anonymous union literal syntax" {...@@ -901,7 +899,6 @@ test "anonymous union literal syntax" {
901 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO899 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
902 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;900 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
903 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;901 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
904
905 const S = struct {902 const S = struct {
906 const Number = union {903 const Number = union {
907 int: i32,904 int: i32,
...@@ -1216,8 +1213,6 @@ test "return an extern union from C calling convention" {...@@ -1216,8 +1213,6 @@ test "return an extern union from C calling convention" {
1216test "noreturn field in union" {1213test "noreturn field in union" {
1217 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1219 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1220
1221 const U = union(enum) {1216 const U = union(enum) {
1222 a: u32,1217 a: u32,
1223 b: noreturn,1218 b: noreturn,
...@@ -1269,7 +1264,6 @@ test "@unionInit uses tag value instead of field index" {...@@ -1269,7 +1264,6 @@ test "@unionInit uses tag value instead of field index" {
1269 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1270 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1265 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1271 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1266 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1272
1273 const E = enum(u8) {1267 const E = enum(u8) {
1274 b = 255,1268 b = 255,
1275 a = 3,1269 a = 3,
test/behavior/vector.zig-6
...@@ -379,8 +379,6 @@ test "vector @splat" {...@@ -379,8 +379,6 @@ test "vector @splat" {
379 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
382 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
383
384 const S = struct {382 const S = struct {
385 fn testForT(comptime N: comptime_int, v: anytype) !void {383 fn testForT(comptime N: comptime_int, v: anytype) !void {
386 const T = @TypeOf(v);384 const T = @TypeOf(v);
...@@ -417,7 +415,6 @@ test "vector @splat" {...@@ -417,7 +415,6 @@ test "vector @splat" {
417415
418test "load vector elements via comptime index" {416test "load vector elements via comptime index" {
419 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;417 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
421 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
422419
423 const S = struct {420 const S = struct {
...@@ -533,8 +530,6 @@ test "vector division operators" {...@@ -533,8 +530,6 @@ test "vector division operators" {
533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO530 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;532 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
536 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
537
538 const S = struct {533 const S = struct {
539 fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {534 fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
540 const is_signed_int = switch (@typeInfo(T)) {535 const is_signed_int = switch (@typeInfo(T)) {
...@@ -622,7 +617,6 @@ test "vector division operators" {...@@ -622,7 +617,6 @@ test "vector division operators" {
622test "vector bitwise not operator" {617test "vector bitwise not operator" {
623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;618 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
624 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;619 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
626 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO620 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
627 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;621 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
628622