@@ -1314,6 +1314,9 @@ fn binOpRegister(
1314
1314
const lhs_is_register = lhs == .register ;
1315
1315
const rhs_is_register = rhs == .register ;
1316
1316
1317
+ if (lhs_is_register ) assert (lhs .register == registerAlias (lhs .register , lhs_ty .abiSize (self .target .* )));
1318
+ if (rhs_is_register ) assert (rhs .register == registerAlias (rhs .register , rhs_ty .abiSize (self .target .* )));
1319
+
1317
1320
const lhs_lock : ? RegisterLock = if (lhs_is_register )
1318
1321
self .register_manager .lockReg (lhs .register )
1319
1322
else
@@ -1343,13 +1346,22 @@ fn binOpRegister(
1343
1346
const new_lhs_lock = self .register_manager .lockReg (lhs_reg );
1344
1347
defer if (new_lhs_lock ) | reg | self .register_manager .unlockReg (reg );
1345
1348
1346
- const rhs_reg = if (rhs_is_register ) rhs .register else blk : {
1349
+ const rhs_reg = if (rhs_is_register )
1350
+ // lhs is almost always equal to rhs, except in shifts. In
1351
+ // order to guarantee that registers will have equal sizes, we
1352
+ // use the register alias of rhs corresponding to the size of
1353
+ // lhs.
1354
+ registerAlias (rhs .register , lhs_ty .abiSize (self .target .* ))
1355
+ else blk : {
1347
1356
const track_inst : ? Air.Inst.Index = if (metadata ) | md | inst : {
1348
1357
break :inst Air .refToIndex (md .rhs ).? ;
1349
1358
} else null ;
1350
1359
1351
1360
const raw_reg = try self .register_manager .allocReg (track_inst , gp );
1352
- const reg = registerAlias (raw_reg , rhs_ty .abiAlignment (self .target .* ));
1361
+
1362
+ // Here, we deliberately use lhs as lhs and rhs may differ in
1363
+ // the case of shifts. See comment above.
1364
+ const reg = registerAlias (raw_reg , lhs_ty .abiSize (self .target .* ));
1353
1365
1354
1366
if (track_inst ) | inst | branch .inst_table .putAssumeCapacity (inst , .{ .register = reg });
1355
1367
@@ -1458,6 +1470,8 @@ fn binOpImmediate(
1458
1470
) ! MCValue {
1459
1471
const lhs_is_register = lhs == .register ;
1460
1472
1473
+ if (lhs_is_register ) assert (lhs .register == registerAlias (lhs .register , lhs_ty .abiSize (self .target .* )));
1474
+
1461
1475
const lhs_lock : ? RegisterLock = if (lhs_is_register )
1462
1476
self .register_manager .lockReg (lhs .register )
1463
1477
else
@@ -1698,21 +1712,52 @@ fn binOp(
1698
1712
null ;
1699
1713
defer if (lhs_lock ) | reg | self .register_manager .unlockReg (reg );
1700
1714
1701
- const lhs_reg = if (lhs_is_register )
1702
- lhs . register
1715
+ const rhs_lock : ? RegisterLock = if (rhs_is_register )
1716
+ self . register_manager . lockReg ( rhs . register )
1703
1717
else
1704
- try self .register_manager .allocReg (null , gp );
1718
+ null ;
1719
+ defer if (rhs_lock ) | reg | self .register_manager .unlockReg (reg );
1720
+
1721
+ const branch = & self .branch_stack .items [self .branch_stack .items .len - 1 ];
1722
+
1723
+ const lhs_reg = if (lhs_is_register ) lhs .register else blk : {
1724
+ const track_inst : ? Air.Inst.Index = if (metadata ) | md | inst : {
1725
+ break :inst Air .refToIndex (md .lhs ).? ;
1726
+ } else null ;
1727
+
1728
+ const raw_reg = try self .register_manager .allocReg (track_inst , gp );
1729
+ const reg = registerAlias (raw_reg , lhs_ty .abiSize (self .target .* ));
1730
+
1731
+ if (track_inst ) | inst | branch .inst_table .putAssumeCapacity (inst , .{ .register = reg });
1732
+
1733
+ break :blk reg ;
1734
+ };
1705
1735
const new_lhs_lock = self .register_manager .lockReg (lhs_reg );
1706
1736
defer if (new_lhs_lock ) | reg | self .register_manager .unlockReg (reg );
1707
1737
1708
- const rhs_reg = if (rhs_is_register )
1709
- rhs .register
1710
- else
1711
- try self .register_manager .allocReg (null , gp );
1738
+ const rhs_reg = if (rhs_is_register ) rhs .register else blk : {
1739
+ const track_inst : ? Air.Inst.Index = if (metadata ) | md | inst : {
1740
+ break :inst Air .refToIndex (md .rhs ).? ;
1741
+ } else null ;
1742
+
1743
+ const raw_reg = try self .register_manager .allocReg (track_inst , gp );
1744
+ const reg = registerAlias (raw_reg , rhs_ty .abiAlignment (self .target .* ));
1745
+
1746
+ if (track_inst ) | inst | branch .inst_table .putAssumeCapacity (inst , .{ .register = reg });
1747
+
1748
+ break :blk reg ;
1749
+ };
1712
1750
const new_rhs_lock = self .register_manager .lockReg (rhs_reg );
1713
1751
defer if (new_rhs_lock ) | reg | self .register_manager .unlockReg (reg );
1714
1752
1715
- const dest_regs = try self .register_manager .allocRegs (2 , .{ null , null }, gp );
1753
+ const dest_regs : [2 ]Register = blk : {
1754
+ const raw_regs = try self .register_manager .allocRegs (2 , .{ null , null }, gp );
1755
+ const abi_size = lhs_ty .abiSize (self .target .* );
1756
+ break :blk .{
1757
+ registerAlias (raw_regs [0 ], abi_size ),
1758
+ registerAlias (raw_regs [1 ], abi_size ),
1759
+ };
1760
+ };
1716
1761
const dest_regs_locks = self .register_manager .lockRegsAssumeUnused (2 , dest_regs );
1717
1762
defer for (dest_regs_locks ) | reg | {
1718
1763
self .register_manager .unlockReg (reg );
@@ -2037,7 +2082,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
2037
2082
try self .truncRegister (dest_reg , truncated_reg , int_info .signedness , int_info .bits );
2038
2083
2039
2084
// cmp dest, truncated
2040
- _ = try self .binOp (.cmp_eq , dest , .{ .register = truncated_reg }, Type . usize , Type . usize , null );
2085
+ _ = try self .binOp (.cmp_eq , dest , .{ .register = truncated_reg }, lhs_ty , lhs_ty , null );
2041
2086
2042
2087
try self .genSetStack (lhs_ty , stack_offset , .{ .register = truncated_reg });
2043
2088
try self .genSetStack (Type .initTag (.u1 ), stack_offset - overflow_bit_offset , .{ .condition_flags = .ne });
@@ -2753,7 +2798,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2753
2798
fn airPtrElemPtr (self : * Self , inst : Air.Inst.Index ) ! void {
2754
2799
const ty_pl = self .air .instructions .items (.data )[inst ].ty_pl ;
2755
2800
const extra = self .air .extraData (Air .Bin , ty_pl .payload ).data ;
2756
- const result : MCValue = if (self .liveness .isUnused (inst )) .dead else return self .fail ("TODO implement ptr_elem_ptr for {}" , .{self .target .cpu .arch });
2801
+ const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
2802
+ const ptr_mcv = try self .resolveInst (extra .lhs );
2803
+ const index_mcv = try self .resolveInst (extra .rhs );
2804
+
2805
+ const ptr_ty = self .air .typeOf (extra .lhs );
2806
+
2807
+ const addr = try self .binOp (.ptr_add , ptr_mcv , index_mcv , ptr_ty , Type .usize , null );
2808
+ break :result addr ;
2809
+ };
2757
2810
return self .finishAir (inst , result , .{ extra .lhs , extra .rhs , .none });
2758
2811
}
2759
2812
@@ -3219,6 +3272,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3219
3272
const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
3220
3273
const mcv = try self .resolveInst (operand );
3221
3274
const struct_ty = self .air .typeOf (operand );
3275
+ const struct_field_ty = struct_ty .structFieldType (index );
3222
3276
const struct_field_offset = @intCast (u32 , struct_ty .structFieldOffset (index , self .target .* ));
3223
3277
3224
3278
switch (mcv ) {
@@ -3250,8 +3304,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3250
3304
break :result field ;
3251
3305
} else {
3252
3306
// Copy to new register
3253
- const dest_reg = try self .register_manager .allocReg (null , gp );
3254
- try self .genSetReg (struct_ty .structFieldType (index ), dest_reg , field );
3307
+ const raw_dest_reg = try self .register_manager .allocReg (null , gp );
3308
+ const dest_reg = registerAlias (raw_dest_reg , struct_field_ty .abiSize (self .target .* ));
3309
+ try self .genSetReg (struct_field_ty , dest_reg , field );
3255
3310
3256
3311
break :result MCValue { .register = dest_reg };
3257
3312
}
0 commit comments