Skip to content

Commit 7000395

Browse files
committed
x64: use new condition codes enum for register with overflow mcv
1 parent 5fb7070 commit 7000395

File tree

1 file changed

+55
-82
lines changed

1 file changed

+55
-82
lines changed

src/arch/x86_64/CodeGen.zig

Lines changed: 55 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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", .{});

0 commit comments

Comments
 (0)