| author | |
| committer | |
| log | 004d0c8978d4b5e4212c06abb33d7a594930f8c5 |
| tree | bfce4fb25e6e6b220f50e06a121c6e528d7a7180 |
| parent | 4aa15440c7a12bcc6bc0cd589ade02295549d48c |
| signature |
10 files changed, 158 insertions(+), 55 deletions(-)
src/arch/riscv64/CodeGen.zig+148-11| ... | ... | @@ -1223,7 +1223,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1223 | 1223 | |
| 1224 | 1224 | .field_parent_ptr => try self.airFieldParentPtr(inst), |
| 1225 | 1225 | |
| 1226 | .switch_br => try self.airSwitch(inst), | |
| 1226 | .switch_br => try self.airSwitchBr(inst), | |
| 1227 | 1227 | .slice_ptr => try self.airSlicePtr(inst), |
| 1228 | 1228 | .slice_len => try self.airSliceLen(inst), |
| 1229 | 1229 | |
| ... | ... | @@ -1960,7 +1960,7 @@ fn binOp( |
| 1960 | 1960 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 1961 | 1961 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1962 | 1962 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1963 | .Int => { | |
| 1963 | .Int, .Enum => { | |
| 1964 | 1964 | assert(lhs_ty.eql(rhs_ty, zcu)); |
| 1965 | 1965 | const int_info = lhs_ty.intInfo(zcu); |
| 1966 | 1966 | if (int_info.bits <= 64) { |
| ... | ... | @@ -3682,7 +3682,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3682 | 3682 | switch (self.ret_mcv.short) { |
| 3683 | 3683 | .none => {}, |
| 3684 | 3684 | .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty), |
| 3685 | .indirect => |reg_off| try self.genSetReg(ptr_ty, reg_off.reg, ptr), | |
| 3686 | 3685 | else => unreachable, |
| 3687 | 3686 | } |
| 3688 | 3687 | self.ret_mcv.liveOut(self, inst); |
| ... | ... | @@ -4160,12 +4159,97 @@ fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) ! |
| 4160 | 4159 | self.finishAirBookkeeping(); |
| 4161 | 4160 | } |
| 4162 | 4161 | |
| 4163 | fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { | |
| 4162 | fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { | |
| 4164 | 4163 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 4165 | const condition = pl_op.operand; | |
| 4166 | _ = condition; | |
| 4167 | return self.fail("TODO airSwitch for {}", .{self.target.cpu.arch}); | |
| 4168 | // return self.finishAir(inst, .dead, .{ condition, .none, .none }); | |
| 4164 | const condition = try self.resolveInst(pl_op.operand); | |
| 4165 | const condition_ty = self.typeOf(pl_op.operand); | |
| 4166 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); | |
| 4167 | var extra_index: usize = switch_br.end; | |
| 4168 | var case_i: u32 = 0; | |
| 4169 | const liveness = try self.liveness.getSwitchBr(self.gpa, inst, switch_br.data.cases_len + 1); | |
| 4170 | defer self.gpa.free(liveness.deaths); | |
| 4171 | ||
| 4172 | // If the condition dies here in this switch instruction, process | |
| 4173 | // that death now instead of later as this has an effect on | |
| 4174 | // whether it needs to be spilled in the branches | |
| 4175 | if (self.liveness.operandDies(inst, 0)) { | |
| 4176 | if (pl_op.operand.toIndex()) |op_inst| try self.processDeath(op_inst); | |
| 4177 | } | |
| 4178 | ||
| 4179 | self.scope_generation += 1; | |
| 4180 | const state = try self.saveState(); | |
| 4181 | ||
| 4182 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { | |
| 4183 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); | |
| 4184 | const items: []const Air.Inst.Ref = | |
| 4185 | @ptrCast(self.air.extra[case.end..][0..case.data.items_len]); | |
| 4186 | const case_body: []const Air.Inst.Index = | |
| 4187 | @ptrCast(self.air.extra[case.end + items.len ..][0..case.data.body_len]); | |
| 4188 | extra_index = case.end + items.len + case_body.len; | |
| 4189 | ||
| 4190 | var relocs = try self.gpa.alloc(Mir.Inst.Index, items.len); | |
| 4191 | defer self.gpa.free(relocs); | |
| 4192 | ||
| 4193 | for (items, relocs, 0..) |item, *reloc, i| { | |
| 4194 | // switch branches must be comptime-known, so this is stored in an immediate | |
| 4195 | const item_mcv = try self.resolveInst(item); | |
| 4196 | ||
| 4197 | const cmp_mcv: MCValue = try self.binOp( | |
| 4198 | .cmp_neq, | |
| 4199 | condition, | |
| 4200 | condition_ty, | |
| 4201 | item_mcv, | |
| 4202 | condition_ty, | |
| 4203 | ); | |
| 4204 | ||
| 4205 | const cmp_reg = try self.copyToTmpRegister(Type.bool, cmp_mcv); | |
| 4206 | ||
| 4207 | if (!(i < relocs.len - 1)) { | |
| 4208 | _ = try self.addInst(.{ | |
| 4209 | .tag = .pseudo, | |
| 4210 | .ops = .pseudo_not, | |
| 4211 | .data = .{ .rr = .{ | |
| 4212 | .rd = cmp_reg, | |
| 4213 | .rs = cmp_reg, | |
| 4214 | } }, | |
| 4215 | }); | |
| 4216 | } | |
| 4217 | ||
| 4218 | reloc.* = try self.condBr(condition_ty, .{ .register = cmp_reg }); | |
| 4219 | } | |
| 4220 | ||
| 4221 | for (liveness.deaths[case_i]) |operand| try self.processDeath(operand); | |
| 4222 | ||
| 4223 | for (relocs[0 .. relocs.len - 1]) |reloc| self.performReloc(reloc); | |
| 4224 | try self.genBody(case_body); | |
| 4225 | try self.restoreState(state, &.{}, .{ | |
| 4226 | .emit_instructions = false, | |
| 4227 | .update_tracking = true, | |
| 4228 | .resurrect = true, | |
| 4229 | .close_scope = true, | |
| 4230 | }); | |
| 4231 | ||
| 4232 | self.performReloc(relocs[relocs.len - 1]); | |
| 4233 | } | |
| 4234 | ||
| 4235 | if (switch_br.data.else_body_len > 0) { | |
| 4236 | const else_body: []const Air.Inst.Index = | |
| 4237 | @ptrCast(self.air.extra[extra_index..][0..switch_br.data.else_body_len]); | |
| 4238 | ||
| 4239 | const else_deaths = liveness.deaths.len - 1; | |
| 4240 | for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand); | |
| 4241 | ||
| 4242 | try self.genBody(else_body); | |
| 4243 | try self.restoreState(state, &.{}, .{ | |
| 4244 | .emit_instructions = false, | |
| 4245 | .update_tracking = true, | |
| 4246 | .resurrect = true, | |
| 4247 | .close_scope = true, | |
| 4248 | }); | |
| 4249 | } | |
| 4250 | ||
| 4251 | // We already took care of pl_op.operand earlier, so there's nothing left to do | |
| 4252 | self.finishAirBookkeeping(); | |
| 4169 | 4253 | } |
| 4170 | 4254 | |
| 4171 | 4255 | fn performReloc(self: *Self, inst: Mir.Inst.Index) void { |
| ... | ... | @@ -4249,9 +4333,60 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 4249 | 4333 | |
| 4250 | 4334 | fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4251 | 4335 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4252 | const air_tags = self.air.instructions.items(.tag); | |
| 4253 | _ = air_tags; | |
| 4254 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement boolean operations for {}", .{self.target.cpu.arch}); | |
| 4336 | const tag: Air.Inst.Tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; | |
| 4337 | ||
| 4338 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { | |
| 4339 | const lhs = try self.resolveInst(bin_op.lhs); | |
| 4340 | const rhs = try self.resolveInst(bin_op.rhs); | |
| 4341 | const lhs_ty = Type.bool; | |
| 4342 | const rhs_ty = Type.bool; | |
| 4343 | ||
| 4344 | const lhs_reg, const lhs_lock = blk: { | |
| 4345 | if (lhs == .register) break :blk .{ lhs.register, null }; | |
| 4346 | ||
| 4347 | const lhs_reg, const lhs_lock = try self.allocReg(); | |
| 4348 | try self.genSetReg(lhs_ty, lhs_reg, lhs); | |
| 4349 | break :blk .{ lhs_reg, lhs_lock }; | |
| 4350 | }; | |
| 4351 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); | |
| 4352 | ||
| 4353 | const rhs_reg, const rhs_lock = blk: { | |
| 4354 | if (rhs == .register) break :blk .{ rhs.register, null }; | |
| 4355 | ||
| 4356 | const rhs_reg, const rhs_lock = try self.allocReg(); | |
| 4357 | try self.genSetReg(rhs_ty, rhs_reg, rhs); | |
| 4358 | break :blk .{ rhs_reg, rhs_lock }; | |
| 4359 | }; | |
| 4360 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | |
| 4361 | ||
| 4362 | const result_reg, const result_lock = try self.allocReg(); | |
| 4363 | defer self.register_manager.unlockReg(result_lock); | |
| 4364 | ||
| 4365 | _ = try self.addInst(.{ | |
| 4366 | .tag = if (tag == .bool_or) .@"or" else .@"and", | |
| 4367 | .ops = .rrr, | |
| 4368 | .data = .{ .r_type = .{ | |
| 4369 | .rd = result_reg, | |
| 4370 | .rs1 = lhs_reg, | |
| 4371 | .rs2 = rhs_reg, | |
| 4372 | } }, | |
| 4373 | }); | |
| 4374 | ||
| 4375 | // safety truncate | |
| 4376 | if (self.wantSafety()) { | |
| 4377 | _ = try self.addInst(.{ | |
| 4378 | .tag = .andi, | |
| 4379 | .ops = .rri, | |
| 4380 | .data = .{ .i_type = .{ | |
| 4381 | .rd = result_reg, | |
| 4382 | .rs1 = result_reg, | |
| 4383 | .imm12 = Immediate.s(1), | |
| 4384 | } }, | |
| 4385 | }); | |
| 4386 | } | |
| 4387 | ||
| 4388 | break :result .{ .register = result_reg }; | |
| 4389 | }; | |
| 4255 | 4390 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4256 | 4391 | } |
| 4257 | 4392 | |
| ... | ... | @@ -5265,7 +5400,9 @@ fn resolveCallingConventionValues( |
| 5265 | 5400 | }, |
| 5266 | 5401 | .memory => { |
| 5267 | 5402 | const param_int_regs = abi.function_arg_regs; |
| 5403 | ||
| 5268 | 5404 | const param_int_reg = param_int_regs[param_int_reg_i]; |
| 5405 | param_int_reg_i += 1; | |
| 5269 | 5406 | |
| 5270 | 5407 | arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } }; |
| 5271 | 5408 | arg_mcv_i += 1; |
src/arch/riscv64/Encoding.zig+3| ... | ... | @@ -38,6 +38,7 @@ pub const Mnemonic = enum { |
| 38 | 38 | // R Type |
| 39 | 39 | add, |
| 40 | 40 | @"and", |
| 41 | @"or", | |
| 41 | 42 | sub, |
| 42 | 43 | slt, |
| 43 | 44 | mul, |
| ... | ... | @@ -55,6 +56,7 @@ pub const Mnemonic = enum { |
| 55 | 56 | .add => .{ .opcode = 0b0110011, .funct3 = 0b000, .funct7 = 0b0000000 }, |
| 56 | 57 | .sltu => .{ .opcode = 0b0110011, .funct3 = 0b011, .funct7 = 0b0000000 }, |
| 57 | 58 | .@"and" => .{ .opcode = 0b0110011, .funct3 = 0b111, .funct7 = 0b0000000 }, |
| 59 | .@"or" => .{ .opcode = 0b0110011, .funct3 = 0b110, .funct7 = 0b0000000 }, | |
| 58 | 60 | .sub => .{ .opcode = 0b0110011, .funct3 = 0b000, .funct7 = 0b0100000 }, |
| 59 | 61 | |
| 60 | 62 | .ld => .{ .opcode = 0b0000011, .funct3 = 0b011, .funct7 = null }, |
| ... | ... | @@ -152,6 +154,7 @@ pub const InstEnc = enum { |
| 152 | 154 | .add, |
| 153 | 155 | .sub, |
| 154 | 156 | .@"and", |
| 157 | .@"or", | |
| 155 | 158 | => .R, |
| 156 | 159 | |
| 157 | 160 | .ecall, |
src/arch/riscv64/Mir.zig-3| ... | ... | @@ -80,9 +80,6 @@ pub const Inst = struct { |
| 80 | 80 | /// Branch if not equal, Uses b_type |
| 81 | 81 | bne, |
| 82 | 82 | |
| 83 | /// Boolean NOT, Uses rr payload | |
| 84 | not, | |
| 85 | ||
| 86 | 83 | /// Generates a NO-OP, uses nop payload |
| 87 | 84 | nop, |
| 88 | 85 |
test/behavior/align.zig-1| ... | ... | @@ -624,7 +624,6 @@ test "alignment of slice element" { |
| 624 | 624 | } |
| 625 | 625 | |
| 626 | 626 | test "sub-aligned pointer field access" { |
| 627 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | |
| 628 | 627 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 629 | 628 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 630 | 629 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
test/behavior/cast.zig-1| ... | ... | @@ -881,7 +881,6 @@ test "peer resolution of string literals" { |
| 881 | 881 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 882 | 882 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 883 | 883 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 884 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 885 | 884 | |
| 886 | 885 | const S = struct { |
| 887 | 886 | const E = enum { a, b, c, d }; |
test/behavior/enum.zig-2| ... | ... | @@ -610,7 +610,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void { |
| 610 | 610 | test "enum with specified tag values" { |
| 611 | 611 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 612 | 612 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 613 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 614 | 613 | |
| 615 | 614 | try testEnumWithSpecifiedTagValues(MultipleChoice.C); |
| 616 | 615 | try comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); |
| ... | ... | @@ -749,7 +748,6 @@ test "cast integer literal to enum" { |
| 749 | 748 | test "enum with specified and unspecified tag values" { |
| 750 | 749 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 751 | 750 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 752 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 753 | 751 | |
| 754 | 752 | try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); |
| 755 | 753 | try comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); |
test/behavior/eval.zig-5| ... | ... | @@ -1088,7 +1088,6 @@ test "comptime break operand passing through runtime condition converted to runt |
| 1088 | 1088 | test "comptime break operand passing through runtime switch converted to runtime break" { |
| 1089 | 1089 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1090 | 1090 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1091 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1092 | 1091 | |
| 1093 | 1092 | const S = struct { |
| 1094 | 1093 | fn doTheTest(runtime: u8) !void { |
| ... | ... | @@ -1631,8 +1630,6 @@ test "struct in comptime false branch is not evaluated" { |
| 1631 | 1630 | } |
| 1632 | 1631 | |
| 1633 | 1632 | test "result of nested switch assigned to variable" { |
| 1634 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1635 | ||
| 1636 | 1633 | var zds: u32 = 0; |
| 1637 | 1634 | zds = switch (zds) { |
| 1638 | 1635 | 0 => switch (zds) { |
| ... | ... | @@ -1667,8 +1664,6 @@ test "inline for loop of functions returning error unions" { |
| 1667 | 1664 | } |
| 1668 | 1665 | |
| 1669 | 1666 | test "if inside a switch" { |
| 1670 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1671 | ||
| 1672 | 1667 | var condition = true; |
| 1673 | 1668 | var wave_type: u32 = 0; |
| 1674 | 1669 | _ = .{ &condition, &wave_type }; |
test/behavior/inline_switch.zig-6| ... | ... | @@ -5,7 +5,6 @@ const builtin = @import("builtin"); |
| 5 | 5 | test "inline scalar prongs" { |
| 6 | 6 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 7 | 7 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 8 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 9 | 8 | |
| 10 | 9 | var x: usize = 0; |
| 11 | 10 | switch (x) { |
| ... | ... | @@ -21,7 +20,6 @@ test "inline scalar prongs" { |
| 21 | 20 | test "inline prong ranges" { |
| 22 | 21 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 23 | 22 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 24 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 25 | 23 | |
| 26 | 24 | var x: usize = 0; |
| 27 | 25 | _ = &x; |
| ... | ... | @@ -37,7 +35,6 @@ const E = enum { a, b, c, d }; |
| 37 | 35 | test "inline switch enums" { |
| 38 | 36 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 39 | 37 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 40 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 41 | 38 | |
| 42 | 39 | var x: E = .a; |
| 43 | 40 | _ = &x; |
| ... | ... | @@ -106,7 +103,6 @@ test "inline else error" { |
| 106 | 103 | test "inline else enum" { |
| 107 | 104 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 108 | 105 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 109 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 110 | 106 | |
| 111 | 107 | const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 }; |
| 112 | 108 | var a: E2 = .a; |
| ... | ... | @@ -120,7 +116,6 @@ test "inline else enum" { |
| 120 | 116 | test "inline else int with gaps" { |
| 121 | 117 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 122 | 118 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 123 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 124 | 119 | |
| 125 | 120 | var a: u8 = 0; |
| 126 | 121 | _ = &a; |
| ... | ... | @@ -139,7 +134,6 @@ test "inline else int with gaps" { |
| 139 | 134 | test "inline else int all values" { |
| 140 | 135 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 141 | 136 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 142 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 143 | 137 | |
| 144 | 138 | var a: u2 = 0; |
| 145 | 139 | _ = &a; |
test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig-1| ... | ... | @@ -8,7 +8,6 @@ test "reference a variable in an if after an if in the 2nd switch prong" { |
| 8 | 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 9 | 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 10 | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 11 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 12 | 11 | |
| 13 | 12 | try foo(true, Num.Two, false, "aoeu"); |
| 14 | 13 | try expect(!ok); |
test/behavior/switch.zig+7-25| ... | ... | @@ -7,7 +7,6 @@ const expectEqual = std.testing.expectEqual; |
| 7 | 7 | |
| 8 | 8 | test "switch with numbers" { |
| 9 | 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 11 | 10 | |
| 12 | 11 | try testSwitchWithNumbers(13); |
| 13 | 12 | } |
| ... | ... | @@ -23,7 +22,6 @@ fn testSwitchWithNumbers(x: u32) !void { |
| 23 | 22 | |
| 24 | 23 | test "switch with all ranges" { |
| 25 | 24 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 26 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 27 | 25 | |
| 28 | 26 | try expect(testSwitchWithAllRanges(50, 3) == 1); |
| 29 | 27 | try expect(testSwitchWithAllRanges(101, 0) == 2); |
| ... | ... | @@ -57,27 +55,25 @@ test "implicit comptime switch" { |
| 57 | 55 | |
| 58 | 56 | test "switch on enum" { |
| 59 | 57 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 60 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 61 | 58 | |
| 62 | 59 | const fruit = Fruit.Orange; |
| 63 | nonConstSwitchOnEnum(fruit); | |
| 60 | try expect(nonConstSwitchOnEnum(fruit)); | |
| 64 | 61 | } |
| 65 | 62 | const Fruit = enum { |
| 66 | 63 | Apple, |
| 67 | 64 | Orange, |
| 68 | 65 | Banana, |
| 69 | 66 | }; |
| 70 | fn nonConstSwitchOnEnum(fruit: Fruit) void { | |
| 71 | switch (fruit) { | |
| 72 | Fruit.Apple => unreachable, | |
| 73 | Fruit.Orange => {}, | |
| 74 | Fruit.Banana => unreachable, | |
| 75 | } | |
| 67 | fn nonConstSwitchOnEnum(fruit: Fruit) bool { | |
| 68 | return switch (fruit) { | |
| 69 | Fruit.Apple => false, | |
| 70 | Fruit.Orange => true, | |
| 71 | Fruit.Banana => false, | |
| 72 | }; | |
| 76 | 73 | } |
| 77 | 74 | |
| 78 | 75 | test "switch statement" { |
| 79 | 76 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 80 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 81 | 77 | |
| 82 | 78 | try nonConstSwitch(SwitchStatementFoo.C); |
| 83 | 79 | } |
| ... | ... | @@ -94,7 +90,6 @@ const SwitchStatementFoo = enum { A, B, C, D }; |
| 94 | 90 | |
| 95 | 91 | test "switch with multiple expressions" { |
| 96 | 92 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 97 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 98 | 93 | |
| 99 | 94 | const x = switch (returnsFive()) { |
| 100 | 95 | 1, 2, 3 => 1, |
| ... | ... | @@ -179,7 +174,6 @@ test "undefined.u0" { |
| 179 | 174 | |
| 180 | 175 | test "switch with disjoint range" { |
| 181 | 176 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 182 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 183 | 177 | |
| 184 | 178 | var q: u8 = 0; |
| 185 | 179 | _ = &q; |
| ... | ... | @@ -191,8 +185,6 @@ test "switch with disjoint range" { |
| 191 | 185 | } |
| 192 | 186 | |
| 193 | 187 | test "switch variable for range and multiple prongs" { |
| 194 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 195 | ||
| 196 | 188 | const S = struct { |
| 197 | 189 | fn doTheTest() !void { |
| 198 | 190 | try doTheSwitch(16); |
| ... | ... | @@ -382,7 +374,6 @@ test "anon enum literal used in switch on union enum" { |
| 382 | 374 | |
| 383 | 375 | test "switch all prongs unreachable" { |
| 384 | 376 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 385 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 386 | 377 | |
| 387 | 378 | try testAllProngsUnreachable(); |
| 388 | 379 | try comptime testAllProngsUnreachable(); |
| ... | ... | @@ -420,7 +411,6 @@ fn return_a_number() anyerror!i32 { |
| 420 | 411 | |
| 421 | 412 | test "switch on integer with else capturing expr" { |
| 422 | 413 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 423 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 424 | 414 | |
| 425 | 415 | const S = struct { |
| 426 | 416 | fn doTheTest() !void { |
| ... | ... | @@ -735,7 +725,6 @@ test "switch capture copies its payload" { |
| 735 | 725 | |
| 736 | 726 | test "capture of integer forwards the switch condition directly" { |
| 737 | 727 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 738 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 739 | 728 | |
| 740 | 729 | const S = struct { |
| 741 | 730 | fn foo(x: u8) !void { |
| ... | ... | @@ -757,7 +746,6 @@ test "capture of integer forwards the switch condition directly" { |
| 757 | 746 | |
| 758 | 747 | test "enum value without tag name used as switch item" { |
| 759 | 748 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 760 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 761 | 749 | |
| 762 | 750 | const E = enum(u32) { |
| 763 | 751 | a = 1, |
| ... | ... | @@ -775,8 +763,6 @@ test "enum value without tag name used as switch item" { |
| 775 | 763 | } |
| 776 | 764 | |
| 777 | 765 | test "switch item sizeof" { |
| 778 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 779 | ||
| 780 | 766 | const S = struct { |
| 781 | 767 | fn doTheTest() !void { |
| 782 | 768 | var a: usize = 0; |
| ... | ... | @@ -873,8 +859,6 @@ test "switch pointer capture peer type resolution" { |
| 873 | 859 | } |
| 874 | 860 | |
| 875 | 861 | test "inline switch range that includes the maximum value of the switched type" { |
| 876 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 877 | ||
| 878 | 862 | const inputs: [3]u8 = .{ 0, 254, 255 }; |
| 879 | 863 | for (inputs) |input| { |
| 880 | 864 | switch (input) { |
| ... | ... | @@ -970,8 +954,6 @@ test "prong with inline call to unreachable" { |
| 970 | 954 | } |
| 971 | 955 | |
| 972 | 956 | test "block error return trace index is reset between prongs" { |
| 973 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 974 | ||
| 975 | 957 | const S = struct { |
| 976 | 958 | fn returnError() error{TestFailed} { |
| 977 | 959 | return error.TestFailed; |