@@ -713,14 +713,21 @@ fn codegen_regular_intrinsic_call<'tcx>(
713713 ret. write_cvalue( fx, val) ;
714714 } ;
715715
716- ptr_offset_from, ( v ptr, v base) {
716+ ptr_offset_from | ptr_offset_from_unsigned , ( v ptr, v base) {
717717 let ty = substs. type_at( 0 ) ;
718718 let isize_layout = fx. layout_of( fx. tcx. types. isize ) ;
719719
720720 let pointee_size: u64 = fx. layout_of( ty) . size. bytes( ) ;
721- let diff = fx. bcx. ins( ) . isub( ptr, base) ;
721+ let diff_bytes = fx. bcx. ins( ) . isub( ptr, base) ;
722722 // FIXME this can be an exact division.
723- let val = CValue :: by_val( fx. bcx. ins( ) . sdiv_imm( diff, pointee_size as i64 ) , isize_layout) ;
723+ let diff = if intrinsic == sym:: ptr_offset_from_unsigned {
724+ // Because diff_bytes ULE isize::MAX, this would be fine as signed,
725+ // but unsigned is slightly easier to codegen, so might as well.
726+ fx. bcx. ins( ) . udiv_imm( diff_bytes, pointee_size as i64 )
727+ } else {
728+ fx. bcx. ins( ) . sdiv_imm( diff_bytes, pointee_size as i64 )
729+ } ;
730+ let val = CValue :: by_val( diff, isize_layout) ;
724731 ret. write_cvalue( fx, val) ;
725732 } ;
726733
0 commit comments