@@ -1682,20 +1682,70 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
16821682 }
16831683}
16841684
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" ) ;
16971746
16981747 let tcx = bcx. tcx ( ) ;
1748+ let lhs_t = lhs. ty ;
16991749 assert ! ( !lhs_t. is_simd( ) ) ;
17001750 let is_float = lhs_t. is_fp ( ) ;
17011751 let is_signed = lhs_t. is_signed ( ) ;
@@ -1704,6 +1754,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
17041754 let binop_debug_loc = binop_expr. debug_loc ( ) ;
17051755
17061756 let mut bcx = bcx;
1757+ let lhs = lhs. to_llscalarish ( bcx) ;
1758+ let rhs = rhs. to_llscalarish ( bcx) ;
17071759 let val = match op. node {
17081760 hir:: BiAdd => {
17091761 if is_float {
@@ -1745,7 +1797,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
17451797 op,
17461798 lhs,
17471799 rhs,
1748- rhs_t ) ;
1800+ lhs_t ) ;
17491801 if is_signed {
17501802 SDiv ( bcx, lhs, rhs, binop_debug_loc)
17511803 } else {
@@ -1796,7 +1848,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
17961848 // Only zero-check integers; fp %0 is NaN
17971849 bcx = base:: fail_if_zero_or_overflows ( bcx,
17981850 expr_info ( binop_expr) ,
1799- op, lhs, rhs, rhs_t ) ;
1851+ op, lhs, rhs, lhs_t ) ;
18001852 if is_signed {
18011853 SRem ( bcx, lhs, rhs, binop_debug_loc)
18021854 } else {
@@ -1896,23 +1948,26 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
18961948 }
18971949 _ => {
18981950 let mut bcx = bcx;
1899- let lhs_datum = unpack_datum ! ( bcx, trans( bcx, lhs) ) ;
1900- let rhs_datum = unpack_datum ! ( bcx, trans( bcx, rhs) ) ;
19011951 let binop_ty = expr_ty ( bcx, expr) ;
19021952
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+ }
19161971 }
19171972 }
19181973}
@@ -2123,21 +2178,19 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
21232178 assert ! ( !bcx. tcx( ) . is_method_call( expr. id) ) ;
21242179
21252180 // 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 ) ;
21302185
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" ) ) ;
21352189
21362190 // Perform computation and store the result
21372191 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 ) ;
21412194}
21422195
21432196fn auto_ref < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
0 commit comments