about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-08-15 19:10:40 +0000
committerbors <bors@rust-lang.org>2015-08-15 19:10:40 +0000
commitf05b22efb5e739b92b47527d29c5fa903f7e64b6 (patch)
tree8195c04753eb184726a2733d8a32d4cb84f5e71b
parent753a6a9e29d4c8b4ee92345051fef61908c276b6 (diff)
parentea7768c2dd8089cc3c3dc1e27158cf1bed277308 (diff)
downloadrust-f05b22efb5e739b92b47527d29c5fa903f7e64b6.tar.gz
rust-f05b22efb5e739b92b47527d29c5fa903f7e64b6.zip
Auto merge of #27845 - dylanmckay:abstract-pointer-size-away, r=alexcrichton
This patch rewrites code in several places which assume that the current target has either 32-bit or 64-bit pointers so that it can support arbitrary-width pointers.

It does not completely remove all assumptions of pointer width, but it does reduce them significantly. There is a discussion [here](https://internals.rust-lang.org/t/adding-16-bit-pointer-support/2484/10) about the change.
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/raw_vec.rs10
-rw-r--r--src/libcore/fmt/mod.rs7
-rw-r--r--src/libcore/hash/mod.rs10
-rw-r--r--src/libcore/iter.rs4
-rw-r--r--src/librustc_trans/trans/base.rs15
-rw-r--r--src/librustc_trans/trans/common.rs18
-rw-r--r--src/librustc_trans/trans/context.rs17
-rw-r--r--src/librustc_trans/trans/intrinsic.rs25
9 files changed, 47 insertions, 60 deletions
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index ca86850f5df..2db9cc7c4d8 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -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)]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 9311f44d9df..97acd0db524 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -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
@@ -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");
+    }
 }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index ea2a9d1cfaf..86700583f2d 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -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);
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 361c6d700de..2a4c909d638 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -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.
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 9db3bf6ec89..ed4053f35be 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -2236,7 +2236,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.
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 1b4e14d7ad7..1982f04195f 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -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);
     let memcpy = ccx.get_intrinsic(&key);
     let src_ptr = PointerCast(cx, src, Type::i8p(ccx));
     let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx));
@@ -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());
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 98301221f96..5707566b047 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -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)
@@ -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)
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index 79f01c2f137..7f383f568a0 100644
--- a/src/librustc_trans/trans/context.rs
+++ b/src/librustc_trans/trans/context.rs
@@ -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)
         }
     }
 
@@ -791,10 +791,10 @@ 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());
@@ -802,7 +802,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
             }
         );
         ($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());
@@ -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);
 
@@ -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());
@@ -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());
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 293a0a6a4ca..33e5d814eb1 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -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);
@@ -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);