Skip to content

Reduce dependence on the taget pointer width #27845

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
#![feature(lang_items)]
#![feature(no_std)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(optin_builtin_traits)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
Expand Down
10 changes: 4 additions & 6 deletions src/liballoc/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use heap;
use super::oom;
use super::boxed::Box;
use core::ops::Drop;
use core;

/// A low-level utility for more ergonomically allocating, reallocating, and deallocating a
/// a buffer of memory on the heap without having to worry about all the corner cases
Expand Down Expand Up @@ -443,11 +444,8 @@ impl<T> Drop for RawVec<T> {
// user-space. e.g. PAE or x32

#[inline]
#[cfg(target_pointer_width = "64")]
fn alloc_guard(_alloc_size: usize) { }

#[inline]
#[cfg(target_pointer_width = "32")]
fn alloc_guard(alloc_size: usize) {
assert!(alloc_size <= ::core::isize::MAX as usize, "capacity overflow");
if core::usize::BITS < 64 {
assert!(alloc_size <= ::core::isize::MAX as usize, "capacity overflow");
}
}
7 changes: 1 addition & 6 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1340,12 +1340,7 @@ impl<T> Pointer for *const T {
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);

if let None = f.width {
// The formats need two extra bytes, for the 0x
if cfg!(target_pointer_width = "32") {
f.width = Some(10);
} else {
f.width = Some(18);
}
f.width = Some((::usize::BITS/4) + 2);
}
}
f.flags |= 1 << (FlagV1::Alternate as u32);
Expand Down
10 changes: 5 additions & 5 deletions src/libcore/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ pub trait Hasher {
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_usize(&mut self, i: usize) {
if cfg!(target_pointer_width = "32") {
self.write_u32(i as u32)
} else {
self.write_u64(i as u64)
}
let bytes = unsafe {
::slice::from_raw_parts(&i as *const usize as *const u8,
mem::size_of::<usize>())
};
self.write(bytes);
}

/// Write a single `i8` into this hasher.
Expand Down
4 changes: 3 additions & 1 deletion src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2234,7 +2234,9 @@ step_impl_signed!(isize i8 i16 i32);
step_impl_unsigned!(u64);
#[cfg(target_pointer_width = "64")]
step_impl_signed!(i64);
#[cfg(target_pointer_width = "32")]
// If the target pointer width is not 64-bits, we
// assume here that it is less than 64-bits.
#[cfg(not(target_pointer_width = "64"))]
step_impl_no_between!(u64 i64);

/// An adapter for stepping range iterators by a custom amount.
Expand Down
15 changes: 4 additions & 11 deletions src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -943,11 +943,8 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
let _icx = push_ctxt("call_memcpy");
let ccx = cx.ccx();
let key = match &ccx.sess().target.target.target_pointer_width[..] {
"32" => "llvm.memcpy.p0i8.p0i8.i32",
"64" => "llvm.memcpy.p0i8.p0i8.i64",
tws => panic!("Unsupported target word size for memcpy: {}", tws),
};
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As of this PR we only have 16, 32 and 64 bit intrinsics bound. The error message will be much worse here now for target_ptr_width ∉ {16, 32, 64}.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in a new commit - the compiler will now panic, saying that the intrinsic is unknown to Rust, along with the intrinsic in question.

let memcpy = ccx.get_intrinsic(&key);
let src_ptr = PointerCast(cx, src, Type::i8p(ccx));
let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx));
Expand Down Expand Up @@ -996,12 +993,8 @@ fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte:
let ccx = b.ccx;

let llty = type_of::type_of(ccx, ty);

let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[..] {
"32" => "llvm.memset.p0i8.i32",
"64" => "llvm.memset.p0i8.i64",
tws => panic!("Unsupported target word size for memset: {}", tws),
};
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);

let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
Expand Down
18 changes: 10 additions & 8 deletions src/librustc_trans/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,10 +833,11 @@ pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
pub fn C_int<I: AsI64>(ccx: &CrateContext, i: I) -> ValueRef {
let v = i.as_i64();

match machine::llbitsize_of_real(ccx, ccx.int_type()) {
32 => assert!(v < (1<<31) && v >= -(1<<31)),
64 => {},
n => panic!("unsupported target size: {}", n)
let bit_size = machine::llbitsize_of_real(ccx, ccx.int_type());

if bit_size < 64 {
// make sure it doesn't overflow
assert!(v < (1<<(bit_size-1)) && v >= -(1<<(bit_size-1)));
}

C_integral(ccx.int_type(), v as u64, true)
Expand All @@ -845,10 +846,11 @@ pub fn C_int<I: AsI64>(ccx: &CrateContext, i: I) -> ValueRef {
pub fn C_uint<I: AsU64>(ccx: &CrateContext, i: I) -> ValueRef {
let v = i.as_u64();

match machine::llbitsize_of_real(ccx, ccx.int_type()) {
32 => assert!(v < (1<<32)),
64 => {},
n => panic!("unsupported target size: {}", n)
let bit_size = machine::llbitsize_of_real(ccx, ccx.int_type());

if bit_size < 64 {
// make sure it doesn't overflow
assert!(v < (1<<bit_size));
}

C_integral(ccx.int_type(), v, false)
Expand Down
17 changes: 10 additions & 7 deletions src/librustc_trans/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,13 +560,13 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
self.local.builder.b
}

pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef {
pub fn get_intrinsic(&self, key: &str) -> ValueRef {
if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
return v;
}
match declare_intrinsic(self, key) {
Some(v) => return v,
None => panic!()
None => panic!("unknown intrinsic '{}'", key)
}
}

Expand Down Expand Up @@ -791,18 +791,18 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
}

/// Declare any llvm intrinsics that you might need
fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
macro_rules! ifn {
($name:expr, fn() -> $ret:expr) => (
if *key == $name {
if key == $name {
let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret),
ccx.tcx().mk_nil());
ccx.intrinsics().borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
if *key == $name {
if key == $name {
let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret),
ccx.tcx().mk_nil());
ccx.intrinsics().borrow_mut().insert($name, f.clone());
Expand All @@ -824,10 +824,13 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
let t_f32 = Type::f32(ccx);
let t_f64 = Type::f64(ccx);

ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void);

Expand Down Expand Up @@ -942,7 +945,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } {
// The `if key == $name` is already in ifn!
ifn!($name, fn($($arg),*) -> void);
} else if *key == $name {
} else if key == $name {
let f = declare::declare_cfn(ccx, stringify!($cname),
Type::func(&[$($arg),*], &void),
ccx.tcx().mk_nil());
Expand All @@ -965,7 +968,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } {
// The `if key == $name` is already in ifn!
ifn!($name, fn($($arg),*) -> $ret);
} else if *key == $name {
} else if key == $name {
let f = declare::declare_cfn(ccx, stringify!($cname),
Type::func(&[$($arg),*], &$ret),
ccx.tcx().mk_nil());
Expand Down
25 changes: 9 additions & 16 deletions src/librustc_trans/trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,20 +932,15 @@ fn copy_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let align = C_i32(ccx, type_of::align_of(ccx, tp_ty) as i32);
let size = machine::llsize_of(ccx, lltp_ty);
let int_size = machine::llbitsize_of_real(ccx, ccx.int_type());
let name = if allow_overlap {
if int_size == 32 {
"llvm.memmove.p0i8.p0i8.i32"
} else {
"llvm.memmove.p0i8.p0i8.i64"
}

let operation = if allow_overlap {
"memmove"
} else {
if int_size == 32 {
"llvm.memcpy.p0i8.p0i8.i32"
} else {
"llvm.memcpy.p0i8.p0i8.i64"
}
"memcpy"
};

let name = format!("llvm.{}.p0i8.p0i8.i{}", operation, int_size);

let dst_ptr = PointerCast(bcx, dst, Type::i8p(ccx));
let src_ptr = PointerCast(bcx, src, Type::i8p(ccx));
let llfn = ccx.get_intrinsic(&name);
Expand Down Expand Up @@ -973,11 +968,9 @@ fn memset_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let lltp_ty = type_of::type_of(ccx, tp_ty);
let align = C_i32(ccx, type_of::align_of(ccx, tp_ty) as i32);
let size = machine::llsize_of(ccx, lltp_ty);
let name = if machine::llbitsize_of_real(ccx, ccx.int_type()) == 32 {
"llvm.memset.p0i8.i32"
} else {
"llvm.memset.p0i8.i64"
};
let int_size = machine::llbitsize_of_real(ccx, ccx.int_type());

let name = format!("llvm.memset.p0i8.i{}", int_size);

let dst_ptr = PointerCast(bcx, dst, Type::i8p(ccx));
let llfn = ccx.get_intrinsic(&name);
Expand Down