From db88b414722e698a392ec65a3ef46730341aea25 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 1 May 2023 16:58:55 -0400 Subject: [PATCH] x86_64: fix switch multi-prongs and mul/div flags clobber --- src/arch/x86_64/CodeGen.zig | 10 ++++++---- test/behavior/inline_switch.zig | 1 - test/behavior/switch.zig | 4 ---- test/behavior/union.zig | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index d5c5938ba0..8e61af1c9f 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2435,6 +2435,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { } }; const src_ty = Type.initPayload(&src_pl.base); + try self.spillEflagsIfOccupied(); try self.spillRegisters(&.{ .rax, .rdx }); const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -7236,15 +7237,16 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { var relocs = try self.gpa.alloc(u32, items.len); defer self.gpa.free(relocs); - for (items, relocs) |item, *reloc| { - try self.spillEflagsIfOccupied(); + try self.spillEflagsIfOccupied(); + for (items, relocs, 0..) |item, *reloc, i| { const item_mcv = try self.resolveInst(item); try self.genBinOpMir(.cmp, condition_ty, condition, item_mcv); - reloc.* = try self.asmJccReloc(undefined, .ne); + reloc.* = try self.asmJccReloc(undefined, if (i < relocs.len - 1) .e else .ne); } for (liveness.deaths[case_i]) |operand| self.processDeath(operand); + for (relocs[0 .. relocs.len - 1]) |reloc| try self.performReloc(reloc); try self.genBody(case_body); try self.restoreState(state, &.{}, .{ .emit_instructions = false, @@ -7253,7 +7255,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { .close_scope = true, }); - for (relocs) |reloc| try self.performReloc(reloc); + try self.performReloc(relocs[relocs.len - 1]); } if (switch_br.data.else_body_len > 0) { diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig index dcd603c94f..6e5013d83b 100644 --- a/test/behavior/inline_switch.zig +++ b/test/behavior/inline_switch.zig @@ -94,7 +94,6 @@ test "inline else error" { test "inline else enum" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 }; diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 3924d1d6c1..5e2d6d28c1 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -88,7 +88,6 @@ fn nonConstSwitch(foo: SwitchStatementFoo) !void { const SwitchStatementFoo = enum { A, B, C, D }; test "switch with multiple expressions" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const x = switch (returnsFive()) { @@ -275,7 +274,6 @@ fn testSwitchEnumPtrCapture() !void { } test "switch handles all cases of number" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try testSwitchHandleAllCases(); @@ -455,7 +453,6 @@ test "else prong of switch on error set excludes other cases" { } test "switch prongs with error set cases make a new error set type for capture value" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -532,7 +529,6 @@ test "switch with null and T peer types and inferred result location type" { test "switch prongs with cases with identical payload types" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const Union = union(enum) { diff --git a/test/behavior/union.zig b/test/behavior/union.zig index f90a336e76..3dd8919935 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1288,7 +1288,6 @@ test "return an extern union from C calling convention" { test "noreturn field in union" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const U = union(enum) {