@@ -1682,20 +1682,70 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1682
1682
}
1683
1683
}
1684
1684
1685
- // Important to get types for both lhs and rhs, because one might be _|_
1686
- // and the other not.
1687
- fn trans_eager_binop < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
1688
- binop_expr : & hir:: Expr ,
1689
- binop_ty : Ty < ' tcx > ,
1690
- op : hir:: BinOp ,
1691
- lhs_t : Ty < ' tcx > ,
1692
- lhs : ValueRef ,
1693
- rhs_t : Ty < ' tcx > ,
1694
- rhs : ValueRef )
1695
- -> DatumBlock < ' blk , ' tcx , Expr > {
1696
- let _icx = push_ctxt ( "trans_eager_binop" ) ;
1685
+ fn trans_fat_ptr_binop < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
1686
+ binop_expr : & hir:: Expr ,
1687
+ binop_ty : Ty < ' tcx > ,
1688
+ op : hir:: BinOp ,
1689
+ lhs : Datum < ' tcx , Rvalue > ,
1690
+ rhs : Datum < ' tcx , Rvalue > )
1691
+ -> DatumBlock < ' blk , ' tcx , Expr >
1692
+ {
1693
+ let debug_loc = binop_expr. debug_loc ( ) ;
1694
+
1695
+ let lhs_addr = Load ( bcx, GEPi ( bcx, lhs. val , & [ 0 , abi:: FAT_PTR_ADDR ] ) ) ;
1696
+ let lhs_extra = Load ( bcx, GEPi ( bcx, lhs. val , & [ 0 , abi:: FAT_PTR_EXTRA ] ) ) ;
1697
+
1698
+ let rhs_addr = Load ( bcx, GEPi ( bcx, rhs. val , & [ 0 , abi:: FAT_PTR_ADDR ] ) ) ;
1699
+ let rhs_extra = Load ( bcx, GEPi ( bcx, rhs. val , & [ 0 , abi:: FAT_PTR_EXTRA ] ) ) ;
1700
+
1701
+ let val = match op. node {
1702
+ hir:: BiEq => {
1703
+ let addr_eq = ICmp ( bcx, llvm:: IntEQ , lhs_addr, rhs_addr, debug_loc) ;
1704
+ let extra_eq = ICmp ( bcx, llvm:: IntEQ , lhs_extra, rhs_extra, debug_loc) ;
1705
+ And ( bcx, addr_eq, extra_eq, debug_loc)
1706
+ }
1707
+ hir:: BiNe => {
1708
+ let addr_eq = ICmp ( bcx, llvm:: IntNE , lhs_addr, rhs_addr, debug_loc) ;
1709
+ let extra_eq = ICmp ( bcx, llvm:: IntNE , lhs_extra, rhs_extra, debug_loc) ;
1710
+ Or ( bcx, addr_eq, extra_eq, debug_loc)
1711
+ }
1712
+ hir:: BiLe | hir:: BiLt | hir:: BiGe | hir:: BiGt => {
1713
+ // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
1714
+ let ( op, strict_op) = match op. node {
1715
+ hir:: BiLt => ( llvm:: IntULT , llvm:: IntULT ) ,
1716
+ hir:: BiLe => ( llvm:: IntULE , llvm:: IntULT ) ,
1717
+ hir:: BiGt => ( llvm:: IntUGT , llvm:: IntUGT ) ,
1718
+ hir:: BiGe => ( llvm:: IntUGE , llvm:: IntUGT ) ,
1719
+ _ => unreachable ! ( )
1720
+ } ;
1721
+
1722
+ let addr_eq = ICmp ( bcx, llvm:: IntEQ , lhs_addr, rhs_addr, debug_loc) ;
1723
+ let extra_op = ICmp ( bcx, op, lhs_extra, rhs_extra, debug_loc) ;
1724
+ let addr_eq_extra_op = And ( bcx, addr_eq, extra_op, debug_loc) ;
1725
+
1726
+ let addr_strict = ICmp ( bcx, strict_op, lhs_addr, rhs_addr, debug_loc) ;
1727
+ Or ( bcx, addr_strict, addr_eq_extra_op, debug_loc)
1728
+ }
1729
+ _ => {
1730
+ bcx. tcx ( ) . sess . span_bug ( binop_expr. span , "unexpected binop" ) ;
1731
+ }
1732
+ } ;
1733
+
1734
+ immediate_rvalue_bcx ( bcx, val, binop_ty) . to_expr_datumblock ( )
1735
+ }
1736
+
1737
+ fn trans_scalar_binop < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
1738
+ binop_expr : & hir:: Expr ,
1739
+ binop_ty : Ty < ' tcx > ,
1740
+ op : hir:: BinOp ,
1741
+ lhs : Datum < ' tcx , Rvalue > ,
1742
+ rhs : Datum < ' tcx , Rvalue > )
1743
+ -> DatumBlock < ' blk , ' tcx , Expr >
1744
+ {
1745
+ let _icx = push_ctxt ( "trans_scalar_binop" ) ;
1697
1746
1698
1747
let tcx = bcx. tcx ( ) ;
1748
+ let lhs_t = lhs. ty ;
1699
1749
assert ! ( !lhs_t. is_simd( ) ) ;
1700
1750
let is_float = lhs_t. is_fp ( ) ;
1701
1751
let is_signed = lhs_t. is_signed ( ) ;
@@ -1704,6 +1754,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1704
1754
let binop_debug_loc = binop_expr. debug_loc ( ) ;
1705
1755
1706
1756
let mut bcx = bcx;
1757
+ let lhs = lhs. to_llscalarish ( bcx) ;
1758
+ let rhs = rhs. to_llscalarish ( bcx) ;
1707
1759
let val = match op. node {
1708
1760
hir:: BiAdd => {
1709
1761
if is_float {
@@ -1745,7 +1797,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1745
1797
op,
1746
1798
lhs,
1747
1799
rhs,
1748
- rhs_t ) ;
1800
+ lhs_t ) ;
1749
1801
if is_signed {
1750
1802
SDiv ( bcx, lhs, rhs, binop_debug_loc)
1751
1803
} else {
@@ -1796,7 +1848,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1796
1848
// Only zero-check integers; fp %0 is NaN
1797
1849
bcx = base:: fail_if_zero_or_overflows ( bcx,
1798
1850
expr_info ( binop_expr) ,
1799
- op, lhs, rhs, rhs_t ) ;
1851
+ op, lhs, rhs, lhs_t ) ;
1800
1852
if is_signed {
1801
1853
SRem ( bcx, lhs, rhs, binop_debug_loc)
1802
1854
} else {
@@ -1896,23 +1948,26 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1896
1948
}
1897
1949
_ => {
1898
1950
let mut bcx = bcx;
1899
- let lhs_datum = unpack_datum ! ( bcx, trans( bcx, lhs) ) ;
1900
- let rhs_datum = unpack_datum ! ( bcx, trans( bcx, rhs) ) ;
1901
1951
let binop_ty = expr_ty ( bcx, expr) ;
1902
1952
1903
- debug ! ( "trans_binary (expr {}): lhs_datum={}" ,
1904
- expr. id,
1905
- lhs_datum. to_string( ccx) ) ;
1906
- let lhs_ty = lhs_datum. ty ;
1907
- let lhs = lhs_datum. to_llscalarish ( bcx) ;
1908
-
1909
- debug ! ( "trans_binary (expr {}): rhs_datum={}" ,
1910
- expr. id,
1911
- rhs_datum. to_string( ccx) ) ;
1912
- let rhs_ty = rhs_datum. ty ;
1913
- let rhs = rhs_datum. to_llscalarish ( bcx) ;
1914
- trans_eager_binop ( bcx, expr, binop_ty, op,
1915
- lhs_ty, lhs, rhs_ty, rhs)
1953
+ let lhs = unpack_datum ! ( bcx, trans( bcx, lhs) ) ;
1954
+ let lhs = unpack_datum ! ( bcx, lhs. to_rvalue_datum( bcx, "binop_lhs" ) ) ;
1955
+ debug ! ( "trans_binary (expr {}): lhs={}" ,
1956
+ expr. id, lhs. to_string( ccx) ) ;
1957
+ let rhs = unpack_datum ! ( bcx, trans( bcx, rhs) ) ;
1958
+ let rhs = unpack_datum ! ( bcx, rhs. to_rvalue_datum( bcx, "binop_rhs" ) ) ;
1959
+ debug ! ( "trans_binary (expr {}): rhs={}" ,
1960
+ expr. id, rhs. to_string( ccx) ) ;
1961
+
1962
+ if type_is_fat_ptr ( ccx. tcx ( ) , lhs. ty ) {
1963
+ assert ! ( type_is_fat_ptr( ccx. tcx( ) , rhs. ty) ,
1964
+ "built-in binary operators on fat pointers are homogeneous" ) ;
1965
+ trans_fat_ptr_binop ( bcx, expr, binop_ty, op, lhs, rhs)
1966
+ } else {
1967
+ assert ! ( !type_is_fat_ptr( ccx. tcx( ) , rhs. ty) ,
1968
+ "built-in binary operators on fat pointers are homogeneous" ) ;
1969
+ trans_scalar_binop ( bcx, expr, binop_ty, op, lhs, rhs)
1970
+ }
1916
1971
}
1917
1972
}
1918
1973
}
@@ -2123,21 +2178,19 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
2123
2178
assert ! ( !bcx. tcx( ) . is_method_call( expr. id) ) ;
2124
2179
2125
2180
// Evaluate LHS (destination), which should be an lvalue
2126
- let dst_datum = unpack_datum ! ( bcx, trans_to_lvalue( bcx, dst, "assign_op" ) ) ;
2127
- assert ! ( !bcx. fcx. type_needs_drop( dst_datum . ty) ) ;
2128
- let dst_ty = dst_datum . ty ;
2129
- let dst = load_ty ( bcx , dst_datum . val , dst_datum . ty ) ;
2181
+ let dst = unpack_datum ! ( bcx, trans_to_lvalue( bcx, dst, "assign_op" ) ) ;
2182
+ assert ! ( !bcx. fcx. type_needs_drop( dst . ty) ) ;
2183
+ let lhs = load_ty ( bcx , dst . val , dst . ty ) ;
2184
+ let lhs = immediate_rvalue ( lhs , dst . ty ) ;
2130
2185
2131
- // Evaluate RHS
2132
- let rhs_datum = unpack_datum ! ( bcx, trans( bcx, & * src) ) ;
2133
- let rhs_ty = rhs_datum. ty ;
2134
- let rhs = rhs_datum. to_llscalarish ( bcx) ;
2186
+ // Evaluate RHS - FIXME(#28160) this sucks
2187
+ let rhs = unpack_datum ! ( bcx, trans( bcx, & * src) ) ;
2188
+ let rhs = unpack_datum ! ( bcx, rhs. to_rvalue_datum( bcx, "assign_op_rhs" ) ) ;
2135
2189
2136
2190
// Perform computation and store the result
2137
2191
let result_datum = unpack_datum ! (
2138
- bcx, trans_eager_binop( bcx, expr, dst_datum. ty, op,
2139
- dst_ty, dst, rhs_ty, rhs) ) ;
2140
- return result_datum. store_to ( bcx, dst_datum. val ) ;
2192
+ bcx, trans_scalar_binop( bcx, expr, dst. ty, op, lhs, rhs) ) ;
2193
+ return result_datum. store_to ( bcx, dst. val ) ;
2141
2194
}
2142
2195
2143
2196
fn auto_ref < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
0 commit comments