| author | |
| committer | |
| log | 4653794852923e08cceab69620b7d0bb5d11e42d |
| tree | 233b20624ff8fc8da7ff0e297a336efd02f6ba86 |
| parent | a5fbbb83050f2dad0a9ebc0bd995a5a8f58d0a49 |
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 { |
| 45 | 45 | ||
| 46 | pub const zig_call_abi_ver = 3; | 46 | pub const zig_call_abi_ver = 3; |
| 47 | 47 | ||
| 48 | const ControlFlow = union(enum) { | 48 | const LoopSwitch = struct { cond_var: Id, continue_label: Id }; |
| 49 | const Structured = struct { | 49 | |
| 50 | /// This type indicates the way that a block is terminated. The | 50 | /// This type indicates the way that a block is terminated. The |
| 51 | /// state of a particular block is used to track how a jump from | 51 | /// 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) { | 53 | const 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 the | 56 | /// 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 | }; |
| 115 | 60 | ||
| 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, |
| 121 | 66 | /// 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 | }; |
| 131 | 71 | ||
| 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 | }, | ||
| 134 | 102 | ||
| 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 | }; |
| 148 | 111 | ||
| ... | @@ -151,23 +114,27 @@ air: Air, | ... | @@ -151,23 +114,27 @@ air: Air, |
| 151 | liveness: Air.Liveness, | 114 | liveness: Air.Liveness, |
| 152 | owner_nav: InternPool.Nav.Index, | 115 | owner_nav: InternPool.Nav.Index, |
| 153 | module: *Module, | 116 | module: *Module, |
| 154 | control_flow: ControlFlow, | 117 | block_stack: std.ArrayList(*Block) = .empty, |
| 118 | block_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty, | ||
| 155 | base_line: u32, | 119 | base_line: u32, |
| 156 | block_label: Id = .none, | 120 | block_label: Id = .none, |
| 157 | next_arg_index: u32 = 0, | 121 | next_arg_index: u32 = 0, |
| 158 | args: std.ArrayList(Id) = .empty, | 122 | args: std.ArrayList(Id) = .empty, |
| 159 | virtual_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty, | 123 | virtual_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty, |
| 160 | inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty, | 124 | inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty, |
| 125 | loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, LoopSwitch) = .empty, | ||
| 161 | id_scratch: std.ArrayList(Id) = .empty, | 126 | id_scratch: std.ArrayList(Id) = .empty, |
| 162 | prologue: Section = .{}, | 127 | prologue: Section = .{}, |
| 163 | body: Section = .{}, | 128 | body: Section = .{}, |
| 164 | 129 | ||
| 165 | pub fn deinit(cg: *CodeGen) void { | 130 | pub 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; | ||
| 187 | 153 | ||
| 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; | ||
| 226 | 187 | ||
| 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; |
| 434 | 391 | ||
| 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 block | 396 | 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 | } |
| 1054 | 1004 | ||
| 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. | ||
| 1055 | pub fn constructComposite(cg: *CodeGen, result_ty_id: Id, constituents: []const Id) !Id { | 1008 | pub 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), |
| 3898 | 3874 | ||
| 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), // TODO | 3883 | .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(), | ||
| 3912 | 3890 | ||
| 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 emitted | 6530 | /// 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. |
| 6535 | fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Block.Incoming) !Id { | 6533 | fn 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. |
| 6554 | fn structuredBreak(cg: *CodeGen, target_block: Id) !void { | 6550 | fn 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; |
| 6604 | 6596 | ||
| 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); |
| 6612 | 6604 | ||
| 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(); |
| 6616 | 6608 | ||
| 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); |
| 6651 | 6643 | ||
| 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); |
| 6701 | 6693 | ||
| 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)); |
| 6755 | 6701 | ||
| 6756 | const next_block = try cg.genStructuredBody(.selection, body); | 6702 | const next_block = try cg.genStructuredBody(.selection, body); |
| 6757 | 6703 | ||
| 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); |
| 6761 | 6707 | ||
| 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 | }); |
| 6772 | 6718 | ||
| 6773 | const sblock = cf.block_stack.getLast().?; | 6719 | const sblock = cg.block_stack.getLast().?; |
| 6774 | 6720 | ||
| 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 | } |
| 6829 | 6775 | ||
| 6830 | fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void { | 6776 | fn 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); |
| 6835 | 6780 | ||
| 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 | } |
| 6867 | 6790 | ||
| 6868 | fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { | 6791 | fn 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(); |
| 6877 | 6800 | ||
| 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 | }); | ||
| 6891 | 6802 | ||
| 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 | }); | ||
| 6898 | 6812 | ||
| 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 | }; | ||
| 6900 | 6819 | ||
| 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 | }; | ||
| 6907 | 6821 | ||
| 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 | }; | ||
| 6909 | 6828 | ||
| 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 }); | ||
| 6912 | 6830 | ||
| 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 | }); | ||
| 6921 | 6833 | ||
| 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 | } |
| 6929 | 6836 | ||
| 6930 | fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void { | 6837 | fn 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 { |
| 6933 | 6840 | ||
| 6934 | const body_label = cg.module.allocId(); | 6841 | const body_label = cg.module.allocId(); |
| 6935 | 6842 | ||
| 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. | ||
| 6945 | 6846 | ||
| 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. | ||
| 6948 | 6850 | ||
| 6949 | // Emit loop header and jump to loop body | 6851 | 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 | }); | ||
| 6955 | 6853 | ||
| 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 | }); | ||
| 6957 | 6860 | ||
| 6958 | try cg.beginSpvBlock(body_label); | 6861 | try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label }); |
| 6959 | 6862 | ||
| 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); | ||
| 6965 | 6864 | ||
| 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); | ||
| 6967 | 6870 | ||
| 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); | ||
| 6974 | 6872 | ||
| 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 | } |
| 6979 | 6875 | ||
| 6980 | fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 6876 | fn 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; |
| 6987 | 6885 | ||
| 6988 | if (cg.virtual_allocas.get(operand)) |stored| return stored.?; | 6886 | if (cg.virtual_allocas.get(operand)) |stored| return stored.?; |
| 6989 | 6887 | ||
| 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 | } |
| 6992 | 6915 | ||
| 6993 | fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void { | 6916 | fn 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 | } |
| 7005 | 6930 | ||
| 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 | } |
| 7008 | 6975 | ||
| ... | @@ -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(); |
| 7093 | 7060 | ||
| 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 guaranteed | 7063 | // 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 use | 7065 | .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 | } | ||
| 7107 | 7068 | ||
| 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 { |
| 7419 | 7380 | ||
| 7420 | const num_cases = switch_br.cases_len; | 7381 | const num_cases = switch_br.cases_len; |
| 7421 | 7382 | ||
| 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 them | 7384 | 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 | }; | ||
| 7433 | 7396 | ||
| 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; | ||
| 7438 | 7402 | ||
| 7439 | const merge_label = switch (cg.control_flow) { | 7403 | const merge_label = cg.module.allocId(); |
| 7440 | .structured => cg.module.allocId(), | ||
| 7441 | .unstructured => null, | ||
| 7442 | }; | ||
| 7443 | 7404 | ||
| 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 | } | ||
| 7450 | 7409 | ||
| 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); |
| 7455 | 7414 | ||
| 7456 | // Emit each of the cases | 7415 | // 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); |
| 7462 | 7422 | ||
| 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 | } |
| 7482 | 7442 | ||
| 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 | } | ||
| 7485 | 7499 | ||
| 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 | } |
| 7489 | 7520 | ||
| 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); |
| 7494 | 7525 | ||
| 7495 | try cg.beginSpvBlock(label); | 7526 | try cg.beginSpvBlock(label); |
| 7496 | 7527 | ||
| 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 | }); | ||
| 7504 | 7533 | ||
| 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 | } |
| 7512 | 7536 | ||
| 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 | }); | ||
| 7523 | 7549 | ||
| 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 | } |
| 7533 | 7554 | ||
| 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 | |||
| 7560 | fn 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 | |||
| 7822 | fn 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 | } |
| 7540 | 7832 | ||
| 7541 | fn airUnreach(cg: *CodeGen) !void { | 7833 | fn 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); | ||
| 7747 | 8038 | ||
| 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 | } |
| 7751 | 8053 |
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 | } |
| 775 | 775 | ||
| 776 | pub 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 | |||
| 776 | pub fn functionType(module: *Module, return_ty_id: Id, param_type_ids: []const Id) !Id { | 783 | pub 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 | } |
| 102 | 102 | ||
| 103 | test "@alignCast pointers" { | 103 | test "@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" { |
| 223 | test "implicitly decreasing slice alignment" { | 221 | test "implicitly decreasing slice alignment" { |
| 224 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 222 | 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; // TODO | 262 | 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; // TODO | 264 | 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 | } |
| 272 | fn give() anyerror!u128 { | 267 | fn 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; // TODO | 274 | 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" { |
| 22 | test "arrays" { | 22 | test "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; // TODO | 24 | 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; |
| 28 | 26 | ||
| 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 | } |
| 1073 | 1070 | ||
| 1074 | test "initialize sentinel-terminated slice with reference to empty array initializer" { | 1071 | test "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 |
| 1081 | 1076 | ||
| 1082 | test "initialize sentinel-terminated many-pointer with reference to empty array initializer" { | 1077 | test "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; // TODO | 82 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 83 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 83 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 84 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 84 | 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; |
| 87 | 86 | ||
| 88 | if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly | 87 | 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 | } |
| 303 | 303 | ||
| 304 | test "cast undefined" { | 304 | test "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; // TODO | 306 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 307 | 307 | ||
| 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; // TODO | 24 | 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 }; |
| 29 | 27 | ||
| 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; // TODO | 37 | 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 }; |
| 44 | 39 | ||
| 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; // TODO | 78 | 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; | ||
| 86 | 80 | ||
| 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 | } |
| 104 | 104 | ||
| 105 | test "@floatFromInt" { | 105 | test "@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 { |
| 133 | 128 | ||
| 134 | test "@intFromFloat > 128 bits" { | 129 | test "@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; | ||
| 139 | 132 | ||
| 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); |
| 145 | 136 | ||
| ... | @@ -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; | ||
| 165 | 155 | ||
| 166 | try testFloatFromInt(u140, 1024, f16, 1024); | 156 | try testFloatFromInt(u140, 1024, f16, 1024); |
| 167 | try testFloatFromInt(i140, -1024, f16, -1024); | ||
| 168 | 157 | ||
| 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); | ||
| 171 | 159 | ||
| 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" { |
| 282 | test "@intFromFloat" { | 270 | test "@intFromFloat" { |
| 283 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 271 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 284 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 272 | 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 { |
| 347 | test "implicitly cast indirect pointer to maybe-indirect pointer" { | 333 | test "implicitly cast indirect pointer to maybe-indirect pointer" { |
| 348 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 334 | 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; |
| 432 | 417 | ||
| 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 | |||
| 439 | test "*usize to *void" { | 422 | test "*usize to *void" { |
| 440 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 423 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 441 | 424 | ||
| ... | @@ -510,7 +493,6 @@ test "array coercion to undefined at runtime" { | ... | @@ -510,7 +493,6 @@ test "array coercion to undefined at runtime" { |
| 510 | 493 | ||
| 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; |
| 8 | test "@intCast i32 to u7" { | 8 | test "@intCast i32 to u7" { |
| 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 10 | 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 { |
| 145 | test "@intCast <= 64 bits" { | 142 | test "@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; |
| 175 | 170 | ||
| 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 | } |
| 432 | 432 | ||
| 433 | test "type pun null pointer-like optional" { | 433 | test "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 bug | 435 | // 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 | } |
| 519 | test "pointer in aggregate field can mutate comptime state" { | 517 | test "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 | } |
| 524 | 521 |
test/behavior/defer.zig-3| ... | @@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual; | ... | @@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual; |
| 5 | const expectError = std.testing.expectError; | 5 | const expectError = std.testing.expectError; |
| 6 | 6 | ||
| 7 | test "break and continue inside loop inside defer expression" { | 7 | test "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" { |
| 111 | test "simple else prong doesn't emit an error for unreachable else prong" { | 109 | test "simple else prong doesn't emit an error for unreachable else prong" { |
| 112 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 110 | 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; // TODO | 931 | 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 | } |
| 938 | const Test3Foo = union(enum) { | 936 | const 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; // TODO | 973 | 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; |
| 977 | 975 | ||
| 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 | } |
| 981 | 978 | ||
| ... | @@ -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; // TODO | 988 | 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; | ||
| 994 | 990 | ||
| 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 | } |
| 998 | const NonExhaustive = enum(u8) { A, B, _ }; | 993 | const 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; |
| 1035 | 1030 | ||
| 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 | } |
| 1039 | 1033 | ||
| 1040 | test "tag name with signed enum values" { | 1034 | test "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 | } |
| 146 | 146 | ||
| 147 | test "fn returning empty error set can be passed as fn returning any error" { | 147 | test "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 | } |
| 153 | 149 | ||
| 154 | test "fn returning empty error set can be passed as fn returning any error - pointer" { | 150 | test "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 | |||
| 161 | fn entry() void { | 154 | fn 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; |
| 370 | 363 | ||
| 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 | } |
| 378 | 369 | ||
| ... | @@ -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}; |
| 516 | 506 | ||
| 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" { |
| 699 | test "error union payload is properly aligned" { | 689 | test "error union payload is properly aligned" { |
| 700 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 690 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 701 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 691 | 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; | ||
| 704 | 692 | ||
| 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; // TODO | 746 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 759 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 747 | 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; | ||
| 762 | 749 | ||
| 763 | var err_union: anyerror!u8 = 15; | 750 | var err_union: anyerror!u8 = 15; |
| 764 | 751 |
test/behavior/floatop.zig-8| ... | @@ -134,9 +134,6 @@ test "cmp f32" { | ... | @@ -134,9 +134,6 @@ test "cmp f32" { |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | test "cmp f64" { | 136 | test "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; |
| 148 | 145 | ||
| 149 | try testCmp(f128); | ||
| 150 | try comptime testCmp(f128); | 146 | try comptime testCmp(f128); |
| 151 | } | 147 | } |
| 152 | 148 | ||
| ... | @@ -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; // TODO | 150 | 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; | ||
| 158 | 153 | ||
| 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; // TODO | 226 | 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; |
| 238 | 230 |
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 { |
| 292 | 292 | ||
| 293 | test "call function with empty string" { | 293 | test "call function with empty string" { |
| 294 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 294 | 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 | } |
| 299 | 296 | ||
| 300 | fn acceptsString(foo: []u8) void { | 297 | fn 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; // TODO | 302 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 306 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 303 | 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; |
| 446 | 441 | ||
| 447 | const S = struct { | 442 | const S = struct { |
| 448 | x: i32 = 1234, | ||
| 449 | 443 | ||
| 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 | } |
| 440 | 440 | ||
| 441 | test "coerced function body has inequal value with its uncoerced body" { | 441 | test "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" { |
| 488 | 486 | ||
| 489 | test "function argument tuple used as struct field" { | 487 | test "function argument tuple used as struct field" { |
| 490 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 488 | 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" { |
| 34 | const E = enum { a, b, c, d }; | 34 | const E = enum { a, b, c, d }; |
| 35 | test "inline switch enums" { | 35 | test "inline switch enums" { |
| 36 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 36 | 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; // TODO | 47 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 50 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 48 | 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" { |
| 74 | 71 | ||
| 75 | test "inline else bool" { | 72 | test "inline else bool" { |
| 76 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 73 | 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" { |
| 87 | test "inline else error" { | 82 | test "inline else error" { |
| 88 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 83 | 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 | } |
| 305 | 305 | ||
| 306 | test "@min/@max of signed and unsigned runtime integers" { | 306 | test "@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" { |
| 352 | 350 | ||
| 353 | test "@min/@max with runtime vectors of signed and unsigned integers of same size" { | 351 | test "@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; // TODO | 353 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 357 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 354 | 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 | } |
| 169 | 169 | ||
| 170 | test "@memcpy no sentinel source into sentinel destination" { | 170 | test "@memcpy no sentinel source into sentinel destination" { |
| 171 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 172 | 171 | ||
| 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 { |
| 13 | 13 | ||
| 14 | test "merge error sets" { | 14 | test "merge error sets" { |
| 15 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 15 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 16 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 17 | 16 | ||
| 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; |
| 35 | 35 | ||
| 36 | try comptime testMulAdd16(); | 36 | try comptime testMulAdd16(); |
| 37 | try testMulAdd16(); | ||
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | fn testMulAdd16() !void { | 39 | fn 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; // TODO | 48 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 50 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 49 | 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" { |
| 338 | test "0-bit child type coerced to optional return ptr result location" { | 338 | test "0-bit child type coerced to optional return ptr result location" { |
| 339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 340 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 340 | 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; // TODO | 364 | 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 | } |
| 515 | 512 | ||
| 516 | test "orelse on C pointer" { | 513 | test "orelse on C pointer" { |
| 517 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 518 | |||
| 519 | // TODO https://github.com/ziglang/zig/issues/6597 | 514 | // 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; // TODO | 523 | 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; | ||
| 531 | 525 | ||
| 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" { |
| 227 | test "regular in irregular packed struct" { | 227 | test "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; // TODO | 229 | 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; // TODO | 247 | 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 access | 404 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access |
| 410 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 405 | 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 | } |
| 137 | 137 | ||
| 138 | test "initialize const optional C pointer to null" { | 138 | test "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" { |
| 146 | test "assigning integer to C pointer" { | 144 | test "assigning integer to C pointer" { |
| 147 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 145 | 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 | } |
| 646 | 643 | ||
| 647 | test "result type found through optional pointer" { | 644 | test "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 { |
| 700 | test "pointer-to-array constness for zero-size elements, var" { | 695 | test "pointer-to-array constness for zero-size elements, var" { |
| 701 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 696 | 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; // TODO | 54 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 55 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 55 | 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; // TODO | 134 | 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 | } |
| 212 | 212 | ||
| 213 | test "hardcoded address in typeof expression" { | 213 | test "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" { |
| 301 | test "peer type resolution with @TypeOf doesn't trigger dependency loop check" { | 299 | test "peer type resolution with @TypeOf doesn't trigger dependency loop check" { |
| 302 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 300 | 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" { |
| 173 | 173 | ||
| 174 | test "generic malloc free" { | 174 | test "generic malloc free" { |
| 175 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 175 | 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 { |
| 188 | 186 | ||
| 189 | test "slice of hardcoded address to pointer" { | 187 | test "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 | } |
| 213 | 210 | ||
| 214 | test "comptime pointer cast array and then slice" { | 211 | test "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 }; |
| 218 | 213 | ||
| 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" { |
| 229 | test "slicing zero length array" { | 224 | test "slicing zero length array" { |
| 230 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 225 | 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 | } |
| 85 | 85 | ||
| 86 | test "sentinel slice of string literal" { | 86 | test "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); |
| 91 | 89 | ||
| ... | @@ -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" |
| 103 | 101 | ||
| 104 | test "including the sentinel when dereferencing a string literal" { | 102 | test "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].*; |
| 109 | 106 |
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 | } |
| 343 | 343 | ||
| 344 | test "empty struct method call" { | 344 | test "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 { |
| 379 | test "packed struct" { | 378 | test "packed struct" { |
| 380 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 379 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 381 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 380 | 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; |
| 384 | 382 | ||
| 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; // TODO | 447 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 450 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 448 | 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; | ||
| 453 | 449 | ||
| 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; // TODO | 485 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 490 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 486 | 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 | } |
| 1777 | 1772 | ||
| 1778 | test "field calls do not force struct field init resolution" { | 1773 | test "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 resolution | 1776 | _ = @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; |
| 9 | 9 | ||
| 10 | test "switch with numbers" { | 10 | test "switch with numbers" { |
| 11 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 11 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 13 | 12 | ||
| 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 { |
| 25 | 24 | ||
| 26 | test "switch with all ranges" { | 25 | test "switch with all ranges" { |
| 27 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 26 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 28 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | ||
| 29 | 27 | ||
| 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" { |
| 214 | 212 | ||
| 215 | test "switch with disjoint range" { | 213 | test "switch with disjoint range" { |
| 216 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 214 | 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 | } |
| 227 | 223 | ||
| 228 | test "switch variable for range and multiple prongs" { | 224 | test "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; // TODO | 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | ||
| 11 | 10 | ||
| 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; // TODO | 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 33 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 32 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 34 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | ||
| 35 | 33 | ||
| 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; // TODO | 51 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 54 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 52 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 55 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | ||
| 56 | 53 | ||
| 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; // TODO | 74 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 78 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 75 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 79 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | ||
| 80 | 76 | ||
| 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; // TODO | 248 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 253 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 249 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 254 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 250 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 255 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | ||
| 256 | 251 | ||
| 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" { |
| 275 | test "switch loop with discarded tag capture" { | 270 | test "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" { |
| 301 | 294 | ||
| 302 | test "switch loop with single catch-all prong" { | 295 | test "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 | } |
| 470 | 462 | ||
| 471 | test "switch loop for error handling" { | 463 | test "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" { |
| 516 | 506 | ||
| 517 | test "switch loop with packed structs" { | 507 | test "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" { |
| 105 | 105 | ||
| 106 | test "array-like initializer for tuple types" { | 106 | test "array-like initializer for tuple types" { |
| 107 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 107 | 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; // TODO | 170 | 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 | } |
| 218 | 215 | ||
| 219 | test "initializing anon struct with mixed comptime-runtime fields" { | 216 | test "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; // TODO | 226 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 232 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 227 | 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 | } |
| 886 | 886 | ||
| 887 | test "extern union doesn't trigger field check at comptime" { | 887 | test "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; // TODO | 899 | 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" { |
| 1216 | test "noreturn field in union" { | 1213 | test "noreturn field in union" { |
| 1217 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1214 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1218 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1215 | 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; // TODO | 1264 | 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; // TODO | 379 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 380 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 380 | 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" { |
| 417 | 415 | ||
| 418 | test "load vector elements via comptime index" { | 416 | test "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; // TODO | 418 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 422 | 419 | ||
| 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; // TODO | 530 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 534 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 531 | 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" { |
| 622 | test "vector bitwise not operator" { | 617 | test "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; // TODO | 620 | 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; |
| 628 | 622 |