@@ -128,12 +128,8 @@ pub const MCValue = union(enum) {
128
128
immediate : u64 ,
129
129
/// The value is in a GP register.
130
130
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 },
137
133
/// The value is in memory at a hard-coded address.
138
134
/// If the type is a pointer, it means the pointer address is at this memory location.
139
135
memory : u64 ,
@@ -183,8 +179,7 @@ pub const MCValue = union(enum) {
183
179
.eflags ,
184
180
.ptr_stack_offset ,
185
181
.undef ,
186
- .register_overflow_unsigned ,
187
- .register_overflow_signed ,
182
+ .register_overflow ,
188
183
= > false ,
189
184
190
185
.register ,
@@ -774,8 +769,8 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
774
769
.register = > | reg | {
775
770
self .register_manager .freeReg (reg .to64 ());
776
771
},
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 ());
779
774
self .eflags_inst = null ;
780
775
},
781
776
.eflags = > {
@@ -809,20 +804,22 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
809
804
const branch = & self .branch_stack .items [self .branch_stack .items .len - 1 ];
810
805
branch .inst_table .putAssumeCapacityNoClobber (inst , result );
811
806
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.
812
812
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 | {
822
814
if (self .register_manager .isRegFree (reg )) {
823
815
self .register_manager .getRegAssumeFree (reg , inst );
824
816
}
825
817
},
818
+ .register_overflow = > | ro | {
819
+ if (self .register_manager .isRegFree (ro .reg )) {
820
+ self .register_manager .getRegAssumeFree (ro .reg , inst );
821
+ }
822
+ },
826
823
else = > {},
827
824
}
828
825
}
@@ -912,12 +909,12 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
912
909
log .debug ("spilling {d} to stack mcv {any}" , .{ inst , stack_mcv });
913
910
const reg_mcv = self .getResolvedInstValue (inst );
914
911
switch (reg_mcv ) {
915
- .register ,
916
- .register_overflow_unsigned ,
917
- .register_overflow_signed ,
918
- = > | other | {
912
+ .register = > | other | {
919
913
assert (reg .to64 () == other .to64 ());
920
914
},
915
+ .register_overflow = > | ro | {
916
+ assert (reg .to64 () == ro .reg .to64 ());
917
+ },
921
918
else = > {},
922
919
}
923
920
const branch = & self .branch_stack .items [self .branch_stack .items .len - 1 ];
@@ -929,9 +926,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
929
926
if (self .eflags_inst ) | inst_to_save | {
930
927
const mcv = self .getResolvedInstValue (inst_to_save );
931
928
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 ),
935
930
.eflags = > try self .allocRegOrMem (inst_to_save , true ),
936
931
else = > unreachable ,
937
932
};
@@ -947,9 +942,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
947
942
// TODO consolidate with register manager and spillInstruction
948
943
// this call should really belong in the register manager!
949
944
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 ),
953
946
else = > {},
954
947
}
955
948
}
@@ -1339,11 +1332,14 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1339
1332
if (math .isPowerOfTwo (int_info .bits ) and int_info .bits >= 8 ) {
1340
1333
self .eflags_inst = inst ;
1341
1334
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 ,
1345
1338
};
1346
- break :result result ;
1339
+ break :result MCValue { .register_overflow = .{
1340
+ .reg = partial .register ,
1341
+ .eflags = cc ,
1342
+ } };
1347
1343
}
1348
1344
1349
1345
self .eflags_inst = null ;
@@ -1460,10 +1456,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1460
1456
const rhs = try self .resolveInst (bin_op .rhs );
1461
1457
1462
1458
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 ,
1466
1462
};
1463
+ break :result MCValue { .register_overflow = .{
1464
+ .reg = partial .register ,
1465
+ .eflags = cc ,
1466
+ } };
1467
1467
}
1468
1468
1469
1469
try self .spillEflagsIfOccupied ();
@@ -2486,8 +2486,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2486
2486
.unreach = > unreachable ,
2487
2487
.dead = > unreachable ,
2488
2488
.eflags = > unreachable ,
2489
- .register_overflow_unsigned = > unreachable ,
2490
- .register_overflow_signed = > unreachable ,
2489
+ .register_overflow = > unreachable ,
2491
2490
.immediate = > | imm | {
2492
2491
try self .setRegOrMem (elem_ty , dst_mcv , .{ .memory = imm });
2493
2492
},
@@ -2610,8 +2609,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2610
2609
.unreach = > unreachable ,
2611
2610
.dead = > unreachable ,
2612
2611
.eflags = > unreachable ,
2613
- .register_overflow_unsigned = > unreachable ,
2614
- .register_overflow_signed = > unreachable ,
2612
+ .register_overflow = > unreachable ,
2615
2613
.immediate = > | imm | {
2616
2614
try self .setRegOrMem (value_ty , .{ .memory = imm }, value );
2617
2615
},
@@ -2997,31 +2995,24 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2997
2995
2998
2996
break :result dst_mcv ;
2999
2997
},
3000
- .register_overflow_unsigned ,
3001
- .register_overflow_signed ,
3002
- = > | reg | {
2998
+ .register_overflow = > | ro | {
3003
2999
switch (index ) {
3004
3000
0 = > {
3005
3001
// Get wrapped value for overflow operation.
3006
- break :result MCValue { .register = reg };
3002
+ break :result MCValue { .register = ro . reg };
3007
3003
},
3008
3004
1 = > {
3009
3005
// Get overflow bit.
3010
- const reg_lock = self .register_manager .lockRegAssumeUnused (reg );
3006
+ const reg_lock = self .register_manager .lockRegAssumeUnused (ro . reg );
3011
3007
defer self .register_manager .unlockReg (reg_lock );
3012
3008
3013
3009
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
- };
3019
3010
_ = try self .addInst (.{
3020
3011
.tag = .cond_set_byte ,
3021
3012
.ops = Mir .Inst .Ops .encode (.{
3022
3013
.reg1 = dst_reg .to8 (),
3023
3014
}),
3024
- .data = .{ .cc = cc },
3015
+ .data = .{ .cc = ro . eflags },
3025
3016
});
3026
3017
break :result MCValue { .register = dst_reg .to8 () };
3027
3018
},
@@ -3449,15 +3440,13 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
3449
3440
.undef = > unreachable ,
3450
3441
.dead , .unreach , .immediate = > unreachable ,
3451
3442
.eflags = > unreachable ,
3452
- .register_overflow_unsigned = > unreachable ,
3453
- .register_overflow_signed = > unreachable ,
3443
+ .register_overflow = > unreachable ,
3454
3444
.register = > | dst_reg | {
3455
3445
switch (src_mcv ) {
3456
3446
.none = > unreachable ,
3457
3447
.undef = > unreachable ,
3458
3448
.dead , .unreach = > unreachable ,
3459
- .register_overflow_unsigned = > unreachable ,
3460
- .register_overflow_signed = > unreachable ,
3449
+ .register_overflow = > unreachable ,
3461
3450
.ptr_stack_offset = > {
3462
3451
const dst_reg_lock = self .register_manager .lockReg (dst_reg );
3463
3452
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
3564
3553
.none = > unreachable ,
3565
3554
.undef = > unreachable ,
3566
3555
.dead , .unreach = > unreachable ,
3567
- .register_overflow_unsigned = > unreachable ,
3568
- .register_overflow_signed = > unreachable ,
3556
+ .register_overflow = > unreachable ,
3569
3557
.register = > | src_reg | {
3570
3558
_ = try self .addInst (.{
3571
3559
.tag = mir_tag ,
@@ -3640,16 +3628,14 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3640
3628
.dead , .unreach , .immediate = > unreachable ,
3641
3629
.eflags = > unreachable ,
3642
3630
.ptr_stack_offset = > unreachable ,
3643
- .register_overflow_unsigned = > unreachable ,
3644
- .register_overflow_signed = > unreachable ,
3631
+ .register_overflow = > unreachable ,
3645
3632
.register = > | dst_reg | {
3646
3633
switch (src_mcv ) {
3647
3634
.none = > unreachable ,
3648
3635
.undef = > try self .genSetReg (dst_ty , dst_reg , .undef ),
3649
3636
.dead , .unreach = > unreachable ,
3650
3637
.ptr_stack_offset = > unreachable ,
3651
- .register_overflow_unsigned = > unreachable ,
3652
- .register_overflow_signed = > unreachable ,
3638
+ .register_overflow = > unreachable ,
3653
3639
.register = > | src_reg | {
3654
3640
// register, register
3655
3641
_ = try self .addInst (.{
@@ -3708,8 +3694,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3708
3694
.undef = > return self .genSetStack (dst_ty , off , .undef , .{}),
3709
3695
.dead , .unreach = > unreachable ,
3710
3696
.ptr_stack_offset = > unreachable ,
3711
- .register_overflow_unsigned = > unreachable ,
3712
- .register_overflow_signed = > unreachable ,
3697
+ .register_overflow = > unreachable ,
3713
3698
.register = > | src_reg | {
3714
3699
// copy dst to a register
3715
3700
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.
3915
3900
.got_load = > unreachable ,
3916
3901
.direct_load = > unreachable ,
3917
3902
.eflags = > unreachable ,
3918
- .register_overflow_signed = > unreachable ,
3919
- .register_overflow_unsigned = > unreachable ,
3903
+ .register_overflow = > unreachable ,
3920
3904
}
3921
3905
}
3922
3906
@@ -5291,9 +5275,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
5291
5275
.{ .dest_stack_base = .rsp },
5292
5276
);
5293
5277
},
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" , .{}),
5297
5279
.eflags = > {
5298
5280
const reg = try self .copyToTmpRegister (ty , mcv );
5299
5281
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
5429
5411
),
5430
5412
}
5431
5413
},
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 );
5436
5416
defer if (reg_lock ) | lock | self .register_manager .unlockReg (lock );
5437
5417
5438
5418
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 }, .{});
5440
5420
5441
5421
const overflow_bit_ty = ty .structFieldType (1 );
5442
5422
const overflow_bit_offset = ty .structFieldOffset (1 , self .target .* );
5443
5423
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
- };
5449
5424
_ = try self .addInst (.{
5450
5425
.tag = .cond_set_byte ,
5451
5426
.ops = Mir .Inst .Ops .encode (.{
5452
5427
.reg1 = tmp_reg .to8 (),
5453
5428
}),
5454
- .data = .{ .cc = cc },
5429
+ .data = .{ .cc = ro . eflags },
5455
5430
});
5456
5431
5457
5432
return self .genSetStack (
@@ -5956,9 +5931,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5956
5931
const abi_size = @intCast (u32 , ty .abiSize (self .target .* ));
5957
5932
switch (mcv ) {
5958
5933
.dead = > unreachable ,
5959
- .register_overflow_unsigned ,
5960
- .register_overflow_signed ,
5961
- = > unreachable ,
5934
+ .register_overflow = > unreachable ,
5962
5935
.ptr_stack_offset = > | off | {
5963
5936
if (off < std .math .minInt (i32 ) or off > std .math .maxInt (i32 )) {
5964
5937
return self .fail ("stack offset too large" , .{});
0 commit comments