about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/cast.rs14
-rw-r--r--src/libcore/unstable/intrinsics.rs3
-rw-r--r--src/libcore/vec.rs95
-rw-r--r--src/librustc/middle/trans/foreign.rs3
-rw-r--r--src/librustc/middle/trans/type_use.rs2
-rw-r--r--src/librustc/middle/typeck/check/mod.rs1
-rw-r--r--src/libstd/priority_queue.rs49
-rw-r--r--src/libstd/rc.rs35
-rw-r--r--src/test/run-pass/intrinsic-uninit.rs19
9 files changed, 215 insertions, 6 deletions
diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs
index 5e6d2f8b910..7451353458e 100644
--- a/src/libcore/cast.rs
+++ b/src/libcore/cast.rs
@@ -24,6 +24,20 @@ pub mod rusti {
 }
 
 /// Casts the value at `src` to U. The two types must have the same length.
+#[cfg(not(stage0))]
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    let mut dest: U = unstable::intrinsics::uninit();
+    {
+        let dest_ptr: *mut u8 = rusti::transmute(&mut dest);
+        let src_ptr: *u8 = rusti::transmute(src);
+        unstable::intrinsics::memmove64(dest_ptr,
+                                        src_ptr,
+                                        sys::size_of::<U>() as u64);
+    }
+    dest
+}
+
+#[cfg(stage0)]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
     let mut dest: U = unstable::intrinsics::init();
     {
diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs
index 363dbb84c1c..cfd305f4b70 100644
--- a/src/libcore/unstable/intrinsics.rs
+++ b/src/libcore/unstable/intrinsics.rs
@@ -44,6 +44,9 @@ pub extern "rust-intrinsic" {
 
     pub fn init<T>() -> T;
 
+    #[cfg(not(stage0))]
+    pub unsafe fn uninit<T>() -> T;
+
     pub fn forget<T>(_: T) -> ();
 
     pub fn needs_drop<T>() -> bool;
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index bf8f5b4ce18..3f3691670ef 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -584,6 +584,22 @@ pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) {
 }
 
 /// Remove the last element from a vector and return it
+#[cfg(not(stage0))]
+pub fn pop<T>(v: &mut ~[T]) -> T {
+    let ln = v.len();
+    if ln == 0 {
+        fail!(~"sorry, cannot vec::pop an empty vector")
+    }
+    let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
+    unsafe {
+        let mut val = intrinsics::uninit();
+        val <-> *valptr;
+        raw::set_len(v, ln - 1u);
+        val
+    }
+}
+
+#[cfg(stage0)]
 pub fn pop<T>(v: &mut ~[T]) -> T {
     let ln = v.len();
     if ln == 0 {
@@ -591,7 +607,6 @@ pub fn pop<T>(v: &mut ~[T]) -> T {
     }
     let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
     unsafe {
-        // FIXME #4204: Should be uninit() - we don't need this zeroed
         let mut val = intrinsics::init();
         val <-> *valptr;
         raw::set_len(v, ln - 1u);
@@ -660,13 +675,30 @@ pub fn push_all<T:Copy>(v: &mut ~[T], rhs: &const [T]) {
 }
 
 #[inline(always)]
+#[cfg(not(stage0))]
+pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
+    let new_len = v.len() + rhs.len();
+    reserve(&mut *v, new_len);
+    unsafe {
+        do as_mut_buf(rhs) |p, len| {
+            for uint::range(0, len) |i| {
+                let mut x = intrinsics::uninit();
+                x <-> *ptr::mut_offset(p, i);
+                push(&mut *v, x);
+            }
+        }
+        raw::set_len(&mut rhs, 0);
+    }
+}
+
+#[inline(always)]
+#[cfg(stage0)]
 pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
     let new_len = v.len() + rhs.len();
     reserve(&mut *v, new_len);
     unsafe {
         do as_mut_buf(rhs) |p, len| {
             for uint::range(0, len) |i| {
-                // FIXME #4204 Should be uninit() - don't need to zero
                 let mut x = intrinsics::init();
                 x <-> *ptr::mut_offset(p, i);
                 push(&mut *v, x);
@@ -677,13 +709,29 @@ pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
 }
 
 /// Shorten a vector, dropping excess elements.
+#[cfg(not(stage0))]
+pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
+    do as_mut_buf(*v) |p, oldlen| {
+        assert!(newlen <= oldlen);
+        unsafe {
+            // This loop is optimized out for non-drop types.
+            for uint::range(newlen, oldlen) |i| {
+                let mut dropped = intrinsics::uninit();
+                dropped <-> *ptr::mut_offset(p, i);
+            }
+        }
+    }
+    unsafe { raw::set_len(&mut *v, newlen); }
+}
+
+/// Shorten a vector, dropping excess elements.
+#[cfg(stage0)]
 pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
     do as_mut_buf(*v) |p, oldlen| {
         assert!(newlen <= oldlen);
         unsafe {
             // This loop is optimized out for non-drop types.
             for uint::range(newlen, oldlen) |i| {
-                // FIXME #4204 Should be uninit() - don't need to zero
                 let mut dropped = intrinsics::init();
                 dropped <-> *ptr::mut_offset(p, i);
             }
@@ -696,6 +744,45 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
  * Remove consecutive repeated elements from a vector; if the vector is
  * sorted, this removes all duplicates.
  */
+#[cfg(not(stage0))]
+pub fn dedup<T:Eq>(v: &mut ~[T]) {
+    unsafe {
+        if v.len() < 1 { return; }
+        let mut last_written = 0, next_to_read = 1;
+        do as_const_buf(*v) |p, ln| {
+            // We have a mutable reference to v, so we can make arbitrary
+            // changes. (cf. push and pop)
+            let p = p as *mut T;
+            // last_written < next_to_read <= ln
+            while next_to_read < ln {
+                // last_written < next_to_read < ln
+                if *ptr::mut_offset(p, next_to_read) ==
+                    *ptr::mut_offset(p, last_written) {
+                    let mut dropped = intrinsics::uninit();
+                    dropped <-> *ptr::mut_offset(p, next_to_read);
+                } else {
+                    last_written += 1;
+                    // last_written <= next_to_read < ln
+                    if next_to_read != last_written {
+                        *ptr::mut_offset(p, last_written) <->
+                            *ptr::mut_offset(p, next_to_read);
+                    }
+                }
+                // last_written <= next_to_read < ln
+                next_to_read += 1;
+                // last_written < next_to_read <= ln
+            }
+        }
+        // last_written < next_to_read == ln
+        raw::set_len(v, last_written + 1);
+    }
+}
+
+/**
+ * Remove consecutive repeated elements from a vector; if the vector is
+ * sorted, this removes all duplicates.
+ */
+#[cfg(stage0)]
 pub fn dedup<T:Eq>(v: &mut ~[T]) {
     unsafe {
         if v.len() < 1 { return; }
@@ -709,8 +796,6 @@ pub fn dedup<T:Eq>(v: &mut ~[T]) {
                 // last_written < next_to_read < ln
                 if *ptr::mut_offset(p, next_to_read) ==
                     *ptr::mut_offset(p, last_written) {
-                    // FIXME #4204 Should be uninit() - don't need to
-                    // zero
                     let mut dropped = intrinsics::init();
                     dropped <-> *ptr::mut_offset(p, next_to_read);
                 } else {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 7eea65e458f..26654cf31f8 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -715,6 +715,9 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                 Store(bcx, C_null(lltp_ty), fcx.llretptr.get());
             }
         }
+        ~"uninit" => {
+            // Do nothing, this is effectively a no-op
+        }
         ~"forget" => {}
         ~"transmute" => {
             let (in_type, out_type) = (substs.tys[0], substs.tys[1]);
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index f1c3a42d158..cbad7bcb3a6 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -118,7 +118,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
         if abi.is_intrinsic() {
             let flags = match *cx.ccx.sess.str_of(i.ident) {
                 ~"size_of"  | ~"pref_align_of" | ~"min_align_of" |
-                ~"init"     | ~"transmute"     | ~"move_val"     |
+                ~"uninit"   | ~"init" | ~"transmute" | ~"move_val" |
                 ~"move_val_init" => use_repr,
 
                 ~"get_tydesc" | ~"needs_drop" => use_tydesc,
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 6cd10b5bd6f..a6f2f0da234 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3447,6 +3447,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
       ~"size_of" |
       ~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()),
       ~"init" => (1u, ~[], param(ccx, 0u)),
+      ~"uninit" => (1u, ~[], param(ccx, 0u)),
       ~"forget" => (1u, ~[arg(param(ccx, 0u))], ty::mk_nil()),
       ~"transmute" => (2, ~[ arg(param(ccx, 0)) ], param(ccx, 1)),
       ~"move_val" | ~"move_val_init" => {
diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs
index 248650452de..b2f8c9c3c4e 100644
--- a/src/libstd/priority_queue.rs
+++ b/src/libstd/priority_queue.rs
@@ -16,6 +16,8 @@ use core::old_iter::BaseIter;
 extern "rust-intrinsic" mod rusti {
     fn move_val_init<T>(dst: &mut T, src: T);
     fn init<T>() -> T;
+    #[cfg(not(stage0))]
+    fn uninit<T>() -> T;
 }
 
 pub struct PriorityQueue<T> {
@@ -132,6 +134,27 @@ pub impl <T:Ord> PriorityQueue<T> {
     // vector over the junk element.  This reduces the constant factor
     // compared to using swaps, which involves twice as many moves.
 
+    #[cfg(not(stage0))]
+    priv fn siftup(&mut self, start: uint, mut pos: uint) {
+        unsafe {
+            let new = *ptr::to_unsafe_ptr(&self.data[pos]);
+
+            while pos > start {
+                let parent = (pos - 1) >> 1;
+                if new > self.data[parent] {
+                    let mut x = rusti::uninit();
+                    x <-> self.data[parent];
+                    rusti::move_val_init(&mut self.data[pos], x);
+                    pos = parent;
+                    loop
+                }
+                break
+            }
+            rusti::move_val_init(&mut self.data[pos], new);
+        }
+    }
+
+    #[cfg(stage0)]
     priv fn siftup(&mut self, start: uint, mut pos: uint) {
         unsafe {
             let new = *ptr::to_unsafe_ptr(&self.data[pos]);
@@ -151,6 +174,32 @@ pub impl <T:Ord> PriorityQueue<T> {
         }
     }
 
+
+    #[cfg(not(stage0))]
+    priv fn siftdown_range(&mut self, mut pos: uint, end: uint) {
+        unsafe {
+            let start = pos;
+            let new = *ptr::to_unsafe_ptr(&self.data[pos]);
+
+            let mut child = 2 * pos + 1;
+            while child < end {
+                let right = child + 1;
+                if right < end && !(self.data[child] > self.data[right]) {
+                    child = right;
+                }
+                let mut x = rusti::uninit();
+                x <-> self.data[child];
+                rusti::move_val_init(&mut self.data[pos], x);
+                pos = child;
+                child = 2 * pos + 1;
+            }
+
+            rusti::move_val_init(&mut self.data[pos], new);
+            self.siftup(start, pos);
+        }
+    }
+
+    #[cfg(stage0)]
     priv fn siftdown_range(&mut self, mut pos: uint, end: uint) {
         unsafe {
             let start = pos;
diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs
index 815f03f4269..9eab1adde47 100644
--- a/src/libstd/rc.rs
+++ b/src/libstd/rc.rs
@@ -46,6 +46,22 @@ pub impl<T: Owned> Rc<T> {
 }
 
 #[unsafe_destructor]
+#[cfg(not(stage0))]
+impl<T: Owned> Drop for Rc<T> {
+    fn finalize(&self) {
+        unsafe {
+            (*self.ptr).count -= 1;
+            if (*self.ptr).count == 0 {
+                let mut x = intrinsics::uninit();
+                x <-> *self.ptr;
+                free(self.ptr as *c_void)
+            }
+        }
+    }
+}
+
+#[unsafe_destructor]
+#[cfg(stage0)]
 impl<T: Owned> Drop for Rc<T> {
     fn finalize(&self) {
         unsafe {
@@ -59,6 +75,7 @@ impl<T: Owned> Drop for Rc<T> {
     }
 }
 
+
 impl<T: Owned> Clone for Rc<T> {
     #[inline]
     fn clone(&self) -> Rc<T> {
@@ -97,6 +114,8 @@ mod test_rc {
 #[abi = "rust-intrinsic"]
 extern "rust-intrinsic" mod rusti {
     fn init<T>() -> T;
+    #[cfg(not(stage0))]
+    fn uninit<T>() -> T;
 }
 
 #[deriving(Eq)]
@@ -154,6 +173,22 @@ pub impl<T: Owned> RcMut<T> {
 }
 
 #[unsafe_destructor]
+#[cfg(not(stage0))]
+impl<T: Owned> Drop for RcMut<T> {
+    fn finalize(&self) {
+        unsafe {
+            (*self.ptr).count -= 1;
+            if (*self.ptr).count == 0 {
+                let mut x = rusti::uninit();
+                x <-> *self.ptr;
+                free(self.ptr as *c_void)
+            }
+        }
+    }
+}
+
+#[unsafe_destructor]
+#[cfg(stage0)]
 impl<T: Owned> Drop for RcMut<T> {
     fn finalize(&self) {
         unsafe {
diff --git a/src/test/run-pass/intrinsic-uninit.rs b/src/test/run-pass/intrinsic-uninit.rs
new file mode 100644
index 00000000000..a835c9531bf
--- /dev/null
+++ b/src/test/run-pass/intrinsic-uninit.rs
@@ -0,0 +1,19 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod rusti {
+    #[abi = "rust-intrinsic"]
+    pub extern "rust-intrinsic" {
+        fn uninit<T>() -> T;
+    }
+}
+pub fn main() {
+    let _a : int = unsafe {rusti::uninit()};
+}