authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-25 17:18:43+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-25 17:18:43+02:00
log7000395a7d002a6d242d717de60614516f4e29af
treec78a0a7480d91d5e0d512265358b8a6b4dda1a21
parent5fb7070642b660a83a2333a23d9163032f0dfcb9

x64: use new condition codes enum for register with overflow mcv


1 files changed, 55 insertions(+), 82 deletions(-)

src/arch/x86_64/CodeGen.zig+55-82
......@@ -128,12 +128,8 @@ pub const MCValue = union(enum) {
128128 immediate: u64,
129129 /// The value is in a GP register.
130130 register: Register,
131 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register,
132 /// and the operation is an unsigned operation.
133 register_overflow_unsigned: Register,
134 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register,
135 /// and the operation is a signed operation.
136 register_overflow_signed: Register,
131 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
132 register_overflow: struct { reg: Register, eflags: Condition },
137133 /// The value is in memory at a hard-coded address.
138134 /// If the type is a pointer, it means the pointer address is at this memory location.
139135 memory: u64,
......@@ -183,8 +179,7 @@ pub const MCValue = union(enum) {
183179 .eflags,
184180 .ptr_stack_offset,
185181 .undef,
186 .register_overflow_unsigned,
187 .register_overflow_signed,
182 .register_overflow,
188183 => false,
189184
190185 .register,
......@@ -774,8 +769,8 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
774769 .register => |reg| {
775770 self.register_manager.freeReg(reg.to64());
776771 },
777 .register_overflow_signed, .register_overflow_unsigned => |reg| {
778 self.register_manager.freeReg(reg.to64());
772 .register_overflow => |ro| {
773 self.register_manager.freeReg(ro.reg.to64());
779774 self.eflags_inst = null;
780775 },
781776 .eflags => {
......@@ -809,20 +804,22 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
809804 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
810805 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
811806
807 // In some cases (such as bitcast), an operand
808 // may be the same MCValue as the result. If
809 // that operand died and was a register, it
810 // was freed by processDeath. We have to
811 // "re-allocate" the register.
812812 switch (result) {
813 .register,
814 .register_overflow_signed,
815 .register_overflow_unsigned,
816 => |reg| {
817 // In some cases (such as bitcast), an operand
818 // may be the same MCValue as the result. If
819 // that operand died and was a register, it
820 // was freed by processDeath. We have to
821 // "re-allocate" the register.
813 .register => |reg| {
822814 if (self.register_manager.isRegFree(reg)) {
823815 self.register_manager.getRegAssumeFree(reg, inst);
824816 }
825817 },
818 .register_overflow => |ro| {
819 if (self.register_manager.isRegFree(ro.reg)) {
820 self.register_manager.getRegAssumeFree(ro.reg, inst);
821 }
822 },
826823 else => {},
827824 }
828825 }
......@@ -912,12 +909,12 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
912909 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
913910 const reg_mcv = self.getResolvedInstValue(inst);
914911 switch (reg_mcv) {
915 .register,
916 .register_overflow_unsigned,
917 .register_overflow_signed,
918 => |other| {
912 .register => |other| {
919913 assert(reg.to64() == other.to64());
920914 },
915 .register_overflow => |ro| {
916 assert(reg.to64() == ro.reg.to64());
917 },
921918 else => {},
922919 }
923920 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -929,9 +926,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
929926 if (self.eflags_inst) |inst_to_save| {
930927 const mcv = self.getResolvedInstValue(inst_to_save);
931928 const new_mcv = switch (mcv) {
932 .register_overflow_signed,
933 .register_overflow_unsigned,
934 => try self.allocRegOrMem(inst_to_save, false),
929 .register_overflow => try self.allocRegOrMem(inst_to_save, false),
935930 .eflags => try self.allocRegOrMem(inst_to_save, true),
936931 else => unreachable,
937932 };
......@@ -947,9 +942,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
947942 // TODO consolidate with register manager and spillInstruction
948943 // this call should really belong in the register manager!
949944 switch (mcv) {
950 .register_overflow_signed,
951 .register_overflow_unsigned,
952 => |reg| self.register_manager.freeReg(reg),
945 .register_overflow => |ro| self.register_manager.freeReg(ro.reg),
953946 else => {},
954947 }
955948 }
......@@ -1339,11 +1332,14 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
13391332 if (math.isPowerOfTwo(int_info.bits) and int_info.bits >= 8) {
13401333 self.eflags_inst = inst;
13411334
1342 const result: MCValue = switch (int_info.signedness) {
1343 .signed => .{ .register_overflow_signed = partial.register },
1344 .unsigned => .{ .register_overflow_unsigned = partial.register },
1335 const cc: Condition = switch (int_info.signedness) {
1336 .unsigned => .c,
1337 .signed => .o,
13451338 };
1346 break :result result;
1339 break :result MCValue{ .register_overflow = .{
1340 .reg = partial.register,
1341 .eflags = cc,
1342 } };
13471343 }
13481344
13491345 self.eflags_inst = null;
......@@ -1460,10 +1456,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14601456 const rhs = try self.resolveInst(bin_op.rhs);
14611457
14621458 const partial = try self.genMulDivBinOp(.mul, null, ty, lhs, rhs);
1463 break :result switch (int_info.signedness) {
1464 .signed => MCValue{ .register_overflow_signed = partial.register },
1465 .unsigned => MCValue{ .register_overflow_unsigned = partial.register },
1459 const cc: Condition = switch (int_info.signedness) {
1460 .unsigned => .c,
1461 .signed => .o,
14661462 };
1463 break :result MCValue{ .register_overflow = .{
1464 .reg = partial.register,
1465 .eflags = cc,
1466 } };
14671467 }
14681468
14691469 try self.spillEflagsIfOccupied();
......@@ -2486,8 +2486,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
24862486 .unreach => unreachable,
24872487 .dead => unreachable,
24882488 .eflags => unreachable,
2489 .register_overflow_unsigned => unreachable,
2490 .register_overflow_signed => unreachable,
2489 .register_overflow => unreachable,
24912490 .immediate => |imm| {
24922491 try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm });
24932492 },
......@@ -2610,8 +2609,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
26102609 .unreach => unreachable,
26112610 .dead => unreachable,
26122611 .eflags => unreachable,
2613 .register_overflow_unsigned => unreachable,
2614 .register_overflow_signed => unreachable,
2612 .register_overflow => unreachable,
26152613 .immediate => |imm| {
26162614 try self.setRegOrMem(value_ty, .{ .memory = imm }, value);
26172615 },
......@@ -2997,31 +2995,24 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
29972995
29982996 break :result dst_mcv;
29992997 },
3000 .register_overflow_unsigned,
3001 .register_overflow_signed,
3002 => |reg| {
2998 .register_overflow => |ro| {
30032999 switch (index) {
30043000 0 => {
30053001 // Get wrapped value for overflow operation.
3006 break :result MCValue{ .register = reg };
3002 break :result MCValue{ .register = ro.reg };
30073003 },
30083004 1 => {
30093005 // Get overflow bit.
3010 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
3006 const reg_lock = self.register_manager.lockRegAssumeUnused(ro.reg);
30113007 defer self.register_manager.unlockReg(reg_lock);
30123008
30133009 const dst_reg = try self.register_manager.allocReg(inst, gp);
3014 const cc: Condition = switch (mcv) {
3015 .register_overflow_unsigned => .c,
3016 .register_overflow_signed => .o,
3017 else => unreachable,
3018 };
30193010 _ = try self.addInst(.{
30203011 .tag = .cond_set_byte,
30213012 .ops = Mir.Inst.Ops.encode(.{
30223013 .reg1 = dst_reg.to8(),
30233014 }),
3024 .data = .{ .cc = cc },
3015 .data = .{ .cc = ro.eflags },
30253016 });
30263017 break :result MCValue{ .register = dst_reg.to8() };
30273018 },
......@@ -3449,15 +3440,13 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
34493440 .undef => unreachable,
34503441 .dead, .unreach, .immediate => unreachable,
34513442 .eflags => unreachable,
3452 .register_overflow_unsigned => unreachable,
3453 .register_overflow_signed => unreachable,
3443 .register_overflow => unreachable,
34543444 .register => |dst_reg| {
34553445 switch (src_mcv) {
34563446 .none => unreachable,
34573447 .undef => unreachable,
34583448 .dead, .unreach => unreachable,
3459 .register_overflow_unsigned => unreachable,
3460 .register_overflow_signed => unreachable,
3449 .register_overflow => unreachable,
34613450 .ptr_stack_offset => {
34623451 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
34633452 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
......@@ -3564,8 +3553,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
35643553 .none => unreachable,
35653554 .undef => unreachable,
35663555 .dead, .unreach => unreachable,
3567 .register_overflow_unsigned => unreachable,
3568 .register_overflow_signed => unreachable,
3556 .register_overflow => unreachable,
35693557 .register => |src_reg| {
35703558 _ = try self.addInst(.{
35713559 .tag = mir_tag,
......@@ -3640,16 +3628,14 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
36403628 .dead, .unreach, .immediate => unreachable,
36413629 .eflags => unreachable,
36423630 .ptr_stack_offset => unreachable,
3643 .register_overflow_unsigned => unreachable,
3644 .register_overflow_signed => unreachable,
3631 .register_overflow => unreachable,
36453632 .register => |dst_reg| {
36463633 switch (src_mcv) {
36473634 .none => unreachable,
36483635 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),
36493636 .dead, .unreach => unreachable,
36503637 .ptr_stack_offset => unreachable,
3651 .register_overflow_unsigned => unreachable,
3652 .register_overflow_signed => unreachable,
3638 .register_overflow => unreachable,
36533639 .register => |src_reg| {
36543640 // register, register
36553641 _ = try self.addInst(.{
......@@ -3708,8 +3694,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
37083694 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
37093695 .dead, .unreach => unreachable,
37103696 .ptr_stack_offset => unreachable,
3711 .register_overflow_unsigned => unreachable,
3712 .register_overflow_signed => unreachable,
3697 .register_overflow => unreachable,
37133698 .register => |src_reg| {
37143699 // copy dst to a register
37153700 const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
......@@ -3915,8 +3900,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
39153900 .got_load => unreachable,
39163901 .direct_load => unreachable,
39173902 .eflags => unreachable,
3918 .register_overflow_signed => unreachable,
3919 .register_overflow_unsigned => unreachable,
3903 .register_overflow => unreachable,
39203904 }
39213905 }
39223906
......@@ -5291,9 +5275,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
52915275 .{ .dest_stack_base = .rsp },
52925276 );
52935277 },
5294 .register_overflow_unsigned,
5295 .register_overflow_signed,
5296 => return self.fail("TODO genSetStackArg for register with overflow bit", .{}),
5278 .register_overflow => return self.fail("TODO genSetStackArg for register with overflow bit", .{}),
52975279 .eflags => {
52985280 const reg = try self.copyToTmpRegister(ty, mcv);
52995281 return self.genSetStackArg(ty, stack_offset, .{ .register = reg });
......@@ -5429,29 +5411,22 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
54295411 ),
54305412 }
54315413 },
5432 .register_overflow_unsigned,
5433 .register_overflow_signed,
5434 => |reg| {
5435 const reg_lock = self.register_manager.lockReg(reg);
5414 .register_overflow => |ro| {
5415 const reg_lock = self.register_manager.lockReg(ro.reg);
54365416 defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);
54375417
54385418 const wrapped_ty = ty.structFieldType(0);
5439 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }, .{});
5419 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = ro.reg }, .{});
54405420
54415421 const overflow_bit_ty = ty.structFieldType(1);
54425422 const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);
54435423 const tmp_reg = try self.register_manager.allocReg(null, gp);
5444 const cc: Condition = switch (mcv) {
5445 .register_overflow_unsigned => .c,
5446 .register_overflow_signed => .o,
5447 else => unreachable,
5448 };
54495424 _ = try self.addInst(.{
54505425 .tag = .cond_set_byte,
54515426 .ops = Mir.Inst.Ops.encode(.{
54525427 .reg1 = tmp_reg.to8(),
54535428 }),
5454 .data = .{ .cc = cc },
5429 .data = .{ .cc = ro.eflags },
54555430 });
54565431
54575432 return self.genSetStack(
......@@ -5956,9 +5931,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
59565931 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
59575932 switch (mcv) {
59585933 .dead => unreachable,
5959 .register_overflow_unsigned,
5960 .register_overflow_signed,
5961 => unreachable,
5934 .register_overflow => unreachable,
59625935 .ptr_stack_offset => |off| {
59635936 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {
59645937 return self.fail("stack offset too large", .{});