let offset = get_param(decl, first_real_arg + 1);
Ret(bcx, GEP(bcx, ptr, [offset]));
}
+ "offset_inbounds" => {
+ let ptr = get_param(decl, first_real_arg);
+ let offset = get_param(decl, first_real_arg + 1);
+ Ret(bcx, InBoundsGEP(bcx, ptr, [offset]));
+ }
"memcpy32" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i32", substs.tys[0], 32),
"memcpy64" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i64", substs.tys[0], 64),
"memmove32" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i32", substs.tys[0], 32),
"visit_tydesc" | "forget" | "frame_address" |
"morestack_addr" => 0,
- "offset" | "memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
+ "offset" | "offset_inbounds" |
+ "memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
"memset32" | "memset64" => use_repr,
"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
mutbl: ast::m_imm
}))
}
+ "offset_inbounds" => {
+ (1,
+ ~[
+ ty::mk_ptr(tcx, ty::mt {
+ ty: param(ccx, 0),
+ mutbl: ast::m_imm
+ }),
+ ty::mk_int()
+ ],
+ ty::mk_ptr(tcx, ty::mt {
+ ty: param(ccx, 0),
+ mutbl: ast::m_imm
+ }))
+ }
"memcpy32" => {
(1,
~[
fn is_not_null(&self) -> bool;
unsafe fn to_option(&self) -> Option<&T>;
fn offset(&self, count: int) -> Self;
+ #[cfg(not(stage0))]
+ unsafe fn offset_inbounds(self, count: int) -> Self;
}
/// Extension methods for immutable pointers
/// Calculates the offset from a pointer.
#[inline]
fn offset(&self, count: int) -> *T { offset(*self, count) }
+
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end.
+ #[inline]
+ #[cfg(not(stage0))]
+ unsafe fn offset_inbounds(self, count: int) -> *T {
+ intrinsics::offset_inbounds(self, count)
+ }
}
/// Extension methods for mutable pointers
/// Calculates the offset from a mutable pointer.
#[inline]
fn offset(&self, count: int) -> *mut T { mut_offset(*self, count) }
+
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end. An arithmetic overflow is also
+ /// undefined behaviour.
+ ///
+ /// This method should be preferred over `offset` when the guarantee can be
+ /// satisfied, to enable better optimization.
+ #[inline]
+ #[cfg(not(stage0))]
+ unsafe fn offset_inbounds(self, count: int) -> *mut T {
+ intrinsics::offset_inbounds(self as *T, count) as *mut T
+ }
}
// Equality for pointers
/// Get the address of the `__morestack` stack growth function.
pub fn morestack_addr() -> *();
- /// Adjust a pointer by an offset.
+ /// Calculates the offset from a pointer.
///
/// This is implemented as an intrinsic to avoid converting to and from an
/// integer, since the conversion would throw away aliasing information.
pub fn offset<T>(dst: *T, offset: int) -> *T;
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end. An arithmetic overflow is also
+ /// undefined behaviour.
+ ///
+ /// This intrinsic should be preferred over `offset` when the guarantee can
+ /// be satisfied, to enable better optimization.
+ #[cfg(not(stage0))]
+ pub fn offset_inbounds<T>(dst: *T, offset: int) -> *T;
+
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32);