diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2013-04-18 15:53:29 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2013-04-19 12:00:08 -0700 |
| commit | c995a62d44ce8534d4f8bf36284419661b87e167 (patch) | |
| tree | e262af9ba09eb89d97b631596c344f9f3620c17a | |
| parent | 7720c15ae11141e2b1a2a3a560b1cdacb6ddada4 (diff) | |
| download | rust-c995a62d44ce8534d4f8bf36284419661b87e167.tar.gz rust-c995a62d44ce8534d4f8bf36284419661b87e167.zip | |
librustc: WIP patch for using the return value.
26 files changed, 778 insertions, 406 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 4080c70c8ae..81190ea8fc6 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -95,7 +95,7 @@ pub use str::{StrSlice}; pub use container::{Container, Mutable}; pub use vec::{CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; -pub use vec::{OwnedVector, OwnedCopyableVector}; +pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector}; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; pub use iter::{ExtendedMutableIter}; diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 3efe21fc42c..1d7cc8515a6 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -16,7 +16,6 @@ use container::{Container, Mutable, Map, Set}; use cmp::{Eq, Equiv}; use hash::Hash; -use to_bytes::IterBytes; use iter::BaseIter; use hash::Hash; use iter; @@ -72,7 +71,7 @@ fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>( } } -priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> { +priv impl<K:Hash + Eq,V> HashMap<K, V> { #[inline(always)] fn to_bucket(&self, h: uint) -> uint { // A good hash function with entropy spread over all of the @@ -111,9 +110,8 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> { } #[inline(always)] - fn bucket_for_key_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, - k: &Q) - -> SearchResult { + fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q) + -> SearchResult { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.bucket_for_key_with_hash_equiv(hash, k) } @@ -303,7 +301,7 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> { } } -impl<K:Hash + IterBytes + Eq,V> Container for HashMap<K, V> { +impl<K:Hash + Eq,V> Container for HashMap<K, V> { /// Return the number of elements in the map fn len(&const self) -> uint { self.size } @@ -311,7 +309,7 @@ impl<K:Hash + IterBytes + Eq,V> Container for HashMap<K, V> { fn is_empty(&const self) -> bool { self.len() == 0 } } -impl<K:Hash + IterBytes + Eq,V> Mutable for HashMap<K, V> { +impl<K:Hash + Eq,V> Mutable for HashMap<K, V> { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { for uint::range(0, self.buckets.len()) |idx| { @@ -321,7 +319,7 @@ impl<K:Hash + IterBytes + Eq,V> Mutable for HashMap<K, V> { } } -impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> { +impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> { /// Return true if the map contains a value for the specified key fn contains_key(&self, k: &K) -> bool { match self.bucket_for_key(k) { @@ -458,7 +456,7 @@ impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> { } } -pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> { +pub impl<K: Hash + Eq, V> HashMap<K, V> { /// Create an empty HashMap fn new() -> HashMap<K, V> { HashMap::with_capacity(INITIAL_CAPACITY) @@ -669,8 +667,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> { /// Return true if the map contains a value for the specified key, /// using equivalence - fn contains_key_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, key: &Q) - -> bool { + fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool { match self.bucket_for_key_equiv(key) { FoundEntry(_) => {true} TableFull | FoundHole(_) => {false} @@ -680,8 +677,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> { /// Return the value corresponding to the key in the map, using /// equivalence #[cfg(stage0)] - fn find_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, k: &Q) - -> Option<&'self V> { + fn find_equiv<Q:Hash + Equiv<K>>(&self, k: &Q) -> Option<&'self V> { match self.bucket_for_key_equiv(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), TableFull | FoundHole(_) => None, @@ -693,9 +689,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> { #[cfg(stage1)] #[cfg(stage2)] #[cfg(stage3)] - fn find_equiv<'a, Q:Hash + IterBytes + Equiv<K>>( - &'a self, k: &Q) -> Option<&'a V> - { + fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> { match self.bucket_for_key_equiv(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), TableFull | FoundHole(_) => None, @@ -703,7 +697,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> { } } -impl<K:Hash + IterBytes + Eq,V:Eq> Eq for HashMap<K, V> { +impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> { fn eq(&self, other: &HashMap<K, V>) -> bool { if self.len() != other.len() { return false; } @@ -724,18 +718,18 @@ pub struct HashSet<T> { priv map: HashMap<T, ()> } -impl<T:Hash + IterBytes + Eq> BaseIter<T> for HashSet<T> { +impl<T:Hash + Eq> BaseIter<T> for HashSet<T> { /// Visit all values in order fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } fn size_hint(&self) -> Option<uint> { Some(self.len()) } } -impl<T:Hash + IterBytes + Eq> Eq for HashSet<T> { +impl<T:Hash + Eq> Eq for HashSet<T> { fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map } fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map } } -impl<T:Hash + IterBytes + Eq> Container for HashSet<T> { +impl<T:Hash + Eq> Container for HashSet<T> { /// Return the number of elements in the set fn len(&const self) -> uint { self.map.len() } @@ -743,12 +737,12 @@ impl<T:Hash + IterBytes + Eq> Container for HashSet<T> { fn is_empty(&const self) -> bool { self.map.is_empty() } } -impl<T:Hash + IterBytes + Eq> Mutable for HashSet<T> { +impl<T:Hash + Eq> Mutable for HashSet<T> { /// Clear the set, removing all values. fn clear(&mut self) { self.map.clear() } } -impl<T:Hash + IterBytes + Eq> Set<T> for HashSet<T> { +impl<T:Hash + Eq> Set<T> for HashSet<T> { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } @@ -816,7 +810,7 @@ impl<T:Hash + IterBytes + Eq> Set<T> for HashSet<T> { } } -pub impl <T:Hash + IterBytes + Eq> HashSet<T> { +pub impl <T:Hash + Eq> HashSet<T> { /// Create an empty HashSet fn new() -> HashSet<T> { HashSet::with_capacity(INITIAL_CAPACITY) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 9d100d1d352..945d08323b4 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1097,9 +1097,12 @@ pub mod funcs { unsafe fn setbuf(stream: *FILE, buf: *c_char); // Omitted: printf and scanf variants. unsafe fn fgetc(stream: *FILE) -> c_int; + #[fast_ffi] unsafe fn fgets(buf: *mut c_char, n: c_int, stream: *FILE) -> *c_char; + #[fast_ffi] unsafe fn fputc(c: c_int, stream: *FILE) -> c_int; + #[fast_ffi] unsafe fn fputs(s: *c_char, stream: *FILE) -> *c_char; // Omitted: getc, getchar (might be macros). @@ -1263,6 +1266,7 @@ pub mod funcs { unsafe fn pclose(stream: *FILE) -> c_int; #[link_name = "_fdopen"] + #[fast_ffi] unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE; #[link_name = "_fileno"] diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 8fd61fb6187..e170d85cc71 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -503,4 +503,4 @@ mod tests { fn test_range_step_zero_step() { for range_step(0,10,0) |_i| {} } -} \ No newline at end of file +} diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 0109c915c60..0fb6ea614d8 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -474,4 +474,4 @@ mod tests { fn test_range_step_zero_step_down() { for range_step(0,-10,0) |_i| {} } -} \ No newline at end of file +} diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 95481d032a4..822fb2e476b 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -46,7 +46,7 @@ pub use to_str::ToStr; pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; pub use vec::{CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; -pub use vec::{OwnedVector, OwnedCopyableVector}; +pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector}; pub use io::{Reader, ReaderUtil, Writer, WriterUtil}; /* Reexported runtime types */ diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 6bde7d33849..837f9c1a9ad 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -430,6 +430,15 @@ pub fn byte_slice<T>(s: &str, f: &fn(v: &[u8]) -> T) -> T { } } +/// Work with the string as a byte slice, not including trailing null, without +/// a callback. +#[inline(always)] +pub fn byte_slice_no_callback<'a>(s: &'a str) -> &'a [u8] { + unsafe { + cast::transmute(s) + } +} + /// Convert a string to a unique vector of characters pub fn to_chars(s: &str) -> ~[char] { let mut buf = ~[]; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 8934b6cab67..0d612369cc5 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -76,6 +76,7 @@ pub fn same_length<T, U>(xs: &const [T], ys: &const [U]) -> bool { * * v - A vector * * n - The number of elements to reserve space for */ +#[inline] pub fn reserve<T>(v: &mut ~[T], n: uint) { // Only make the (slow) call into the runtime if we have to use managed; @@ -1831,6 +1832,7 @@ pub trait ImmutableVector<T> { fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool; fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U]; + unsafe fn unsafe_ref(&self, index: uint) -> *T; } /// Extension methods for vectors @@ -1941,6 +1943,14 @@ impl<'self,T> ImmutableVector<T> for &'self [T] { fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U] { filter_mapped(*self, f) } + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + #[inline(always)] + unsafe fn unsafe_ref(&self, index: uint) -> *T { + let (ptr, _): (*T, uint) = transmute(*self); + ptr.offset(index) + } } #[cfg(stage1)] @@ -2178,9 +2188,8 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] { /// Returns the element at the given index, without doing bounds checking. #[inline(always)] - unsafe fn unsafe_get(&self, elem: uint) -> T { - let (ptr, _): (*T, uint) = transmute(*self); - *ptr.offset(elem) + unsafe fn unsafe_get(&self, index: uint) -> T { + *self.unsafe_ref(index) } } @@ -2323,15 +2332,21 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] { } pub trait MutableVector<T> { - unsafe fn unsafe_set(&self, elem: uint, val: T); + unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T; + unsafe fn unsafe_set(&self, index: uint, val: T); } impl<'self,T> MutableVector<T> for &'self mut [T] { #[inline(always)] - unsafe fn unsafe_set(&self, elem: uint, val: T) { + unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T { let pair_ptr: &(*mut T, uint) = transmute(self); let (ptr, _) = *pair_ptr; - *ptr.offset(elem) = val; + ptr.offset(index) + } + + #[inline(always)] + unsafe fn unsafe_set(&self, index: uint, val: T) { + *self.unsafe_mut_ref(index) = val; } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 8794dae1178..eb7965e1ac6 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -188,8 +188,10 @@ pub mod write { return false; } - pub fn run_passes(sess: Session, llmod: ModuleRef, - output_type: output_type, output: &Path) { + pub fn run_passes(sess: Session, + llmod: ModuleRef, + output_type: output_type, + output: &Path) { unsafe { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 46813974af1..e897b4e1047 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -136,13 +136,17 @@ pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec, ccx.stats.fn_times.push((name, elapsed)); } -pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, - llty: TypeRef) -> ValueRef { +pub fn decl_fn(llmod: ModuleRef, + name: &str, + cc: lib::llvm::CallConv, + llty: TypeRef) + -> ValueRef { let llfn: ValueRef = str::as_c_str(name, |buf| { unsafe { llvm::LLVMGetOrInsertFunction(llmod, buf, llty) } }); + lib::llvm::SetFunctionCallConv(llfn, cc); return llfn; } @@ -478,17 +482,25 @@ pub fn note_unique_llvm_symbol(ccx: @CrateContext, sym: @~str) { } -pub fn get_res_dtor(ccx: @CrateContext, did: ast::def_id, - parent_id: ast::def_id, substs: &[ty::t]) - -> ValueRef { +pub fn get_res_dtor(ccx: @CrateContext, + did: ast::def_id, + parent_id: ast::def_id, + substs: &[ty::t]) + -> ValueRef { let _icx = ccx.insn_ctxt("trans_res_dtor"); if !substs.is_empty() { let did = if did.crate != ast::local_crate { inline::maybe_instantiate_inline(ccx, did, true) - } else { did }; + } else { + did + }; assert!(did.crate == ast::local_crate); - let (val, _) = - monomorphize::monomorphic_fn(ccx, did, substs, None, None, None); + let (val, _) = monomorphize::monomorphic_fn(ccx, + did, + substs, + None, + None, + None); val } else if did.crate == ast::local_crate { @@ -496,11 +508,16 @@ pub fn get_res_dtor(ccx: @CrateContext, did: ast::def_id, } else { let tcx = ccx.tcx; let name = csearch::get_symbol(ccx.sess.cstore, did); - let class_ty = ty::subst_tps(tcx, substs, None, - ty::lookup_item_type(tcx, parent_id).ty); + let class_ty = ty::subst_tps(tcx, + substs, + None, + ty::lookup_item_type(tcx, parent_id).ty); let llty = type_of_dtor(ccx, class_ty); let name = name.to_managed(); // :-( - get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv, + get_extern_fn(ccx.externs, + ccx.llmod, + name, + lib::llvm::CCallConv, llty) } } @@ -804,9 +821,12 @@ pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t) }; } -pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { +pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) + -> (ValueRef, block) { let _icx = bcx.insn_ctxt("invoke_"); - if bcx.unreachable { return bcx; } + if bcx.unreachable { + return (C_null(T_i8()), bcx); + } match bcx.node_info { None => debug!("invoke at ???"), @@ -826,8 +846,12 @@ pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { } } let normal_bcx = sub_block(bcx, ~"normal return"); - Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx)); - return normal_bcx; + let llresult = Invoke(bcx, + llfn, + llargs, + normal_bcx.llbb, + get_landing_pad(bcx)); + return (llresult, normal_bcx); } else { unsafe { debug!("calling %x at %x", @@ -837,8 +861,8 @@ pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { debug!("arg: %x", ::core::cast::transmute(llarg)); } } - Call(bcx, llfn, llargs); - return bcx; + let llresult = Call(bcx, llfn, llargs); + return (llresult, bcx); } } @@ -1568,6 +1592,18 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks { } } +// Creates and returns space for, or returns the argument representing, the +// slot where the return value of the function must go. +pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef { + unsafe { + if !ty::type_is_immediate(output_type) { + llvm::LLVMGetParam(fcx.llfn, 0) + } else { + let lloutputtype = type_of::type_of(*fcx.ccx, output_type); + alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype) + } + } +} // NB: must keep 4 fns in sync: // @@ -1579,10 +1615,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, +path: path, llfndecl: ValueRef, id: ast::node_id, + output_type: ty::t, impl_id: Option<ast::def_id>, param_substs: Option<@param_substs>, - sp: Option<span>) -> fn_ctxt -{ + sp: Option<span>) + -> fn_ctxt { for param_substs.each |p| { p.validate(); } debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \ @@ -1593,16 +1630,26 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, param_substs.repr(ccx.tcx)); let llbbs = mk_standard_basic_blocks(llfndecl); - return @mut fn_ctxt_ { + + let substd_output_type = match param_substs { + None => output_type, + Some(substs) => { + ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type) + } + }; + let is_immediate = ty::type_is_immediate(substd_output_type); + + let fcx = @mut fn_ctxt_ { llfn: llfndecl, llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) }, - llretptr: unsafe { llvm::LLVMGetParam(llfndecl, 0u as c_uint) }, + llretptr: None, llstaticallocas: llbbs.sa, llloadenv: None, llreturn: llbbs.rt, llself: None, personality: None, loop_ret: None, + has_immediate_return_value: is_immediate, llargs: @mut HashMap::new(), lllocals: @mut HashMap::new(), llupvars: @mut HashMap::new(), @@ -1613,14 +1660,18 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, path: path, ccx: @ccx }; + + fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type)); + fcx } pub fn new_fn_ctxt(ccx: @CrateContext, +path: path, llfndecl: ValueRef, + output_type: ty::t, sp: Option<span>) -> fn_ctxt { - return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp); + new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp) } // NB: must keep 4 fns in sync: @@ -1639,7 +1690,8 @@ pub fn new_fn_ctxt(ccx: @CrateContext, // field of the fn_ctxt with pub fn create_llargs_for_fn_args(cx: fn_ctxt, ty_self: self_arg, - args: &[ast::arg]) -> ~[ValueRef] { + args: &[ast::arg]) + -> ~[ValueRef] { let _icx = cx.insn_ctxt("create_llargs_for_fn_args"); match ty_self { @@ -1745,8 +1797,19 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) { let _icx = fcx.insn_ctxt("finish_fn"); tie_up_header_blocks(fcx, lltop); + build_return_block(fcx); +} + +// Builds the return block for a function. +pub fn build_return_block(fcx: fn_ctxt) { let ret_cx = raw_block(fcx, false, fcx.llreturn); - RetVoid(ret_cx); + + // Return the value if this function immediate; otherwise, return void. + if fcx.has_immediate_return_value { + Ret(ret_cx, Load(ret_cx, fcx.llretptr.get())) + } else { + RetVoid(ret_cx) + } } pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) { @@ -1777,6 +1840,7 @@ pub fn trans_closure(ccx: @CrateContext, id: ast::node_id, impl_id: Option<ast::def_id>, attributes: &[ast::attribute], + output_type: ty::t, maybe_load_env: &fn(fn_ctxt), finish: &fn(block)) { ccx.stats.n_closures += 1; @@ -1791,6 +1855,7 @@ pub fn trans_closure(ccx: @CrateContext, path, llfndecl, id, + output_type, impl_id, param_substs, Some(body.span)); @@ -1833,7 +1898,8 @@ pub fn trans_closure(ccx: @CrateContext, { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { - bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr)); + let dest = expr::SaveIn(fcx.llretptr.get()); + bcx = controlflow::trans_block(bcx, body, dest); } finish(bcx); @@ -1864,6 +1930,7 @@ pub fn trans_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; let the_path_str = path_str(ccx.sess, path); + let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id)); trans_closure(ccx, path, decl, @@ -1874,6 +1941,7 @@ pub fn trans_fn(ccx: @CrateContext, id, impl_id, attrs, + output_type, |fcx| { if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); @@ -1907,26 +1975,39 @@ pub fn trans_enum_variant(ccx: @CrateContext, id: varg.id, } }; - let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None, - param_substs, None); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); + let ty_param_substs = match param_substs { Some(ref substs) => { copy substs.tys } None => ~[] }; + let enum_ty = ty::subst_tps(ccx.tcx, + ty_param_substs, + None, + ty::node_id_to_type(ccx.tcx, enum_id)); + let fcx = new_fn_ctxt_w_id(ccx, + ~[], + llfndecl, + variant.node.id, + enum_ty, + None, + param_substs, + None); + + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); // XXX is there a better way to reconstruct the ty::t? - let enum_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None, - ty::node_id_to_type(ccx.tcx, enum_id)); let repr = adt::represent_type(ccx, enum_ty); - adt::trans_start_init(bcx, repr, fcx.llretptr, disr); + adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr); for vec::eachi(args) |i, va| { - let lldestptr = adt::trans_field_ptr(bcx, repr, fcx.llretptr, - disr, i); + let lldestptr = adt::trans_field_ptr(bcx, + repr, + fcx.llretptr.get(), + disr, + i); // If this argument to this function is a enum, it'll have come in to // this function as an opaque blob due to the way that type_of() @@ -1964,10 +2045,25 @@ pub fn trans_tuple_struct(ccx: @CrateContext, } }; + // XXX is there a better way to reconstruct the ty::t? + let ty_param_substs = match param_substs { + Some(ref substs) => { copy substs.tys } + None => ~[] + }; + let ctor_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None, + ty::node_id_to_type(ccx.tcx, ctor_id)); + let tup_ty = match ty::get(ctor_ty).sty { + ty::ty_bare_fn(ref bft) => bft.sig.output, + _ => ccx.sess.bug(fmt!("trans_tuple_struct: unexpected ctor \ + return type %s", + ty_to_str(ccx.tcx, ctor_ty))) + }; + let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, + tup_ty, None, param_substs, None); @@ -1979,23 +2075,14 @@ pub fn trans_tuple_struct(ccx: @CrateContext, let arg_tys = ty::ty_fn_args(node_id_type(bcx, ctor_id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); - // XXX is there a better way to reconstruct the ty::t? - let ty_param_substs = match param_substs { - Some(ref substs) => { copy substs.tys } - None => ~[] - }; - let ctor_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None, - ty::node_id_to_type(ccx.tcx, ctor_id)); - let tup_ty = match ty::get(ctor_ty).sty { - ty::ty_bare_fn(ref bft) => bft.sig.output, - _ => ccx.sess.bug(fmt!("trans_tuple_struct: unexpected ctor \ - return type %s", - ty_to_str(ccx.tcx, ctor_ty))) - }; let repr = adt::represent_type(ccx, tup_ty); for fields.eachi |i, field| { - let lldestptr = adt::trans_field_ptr(bcx, repr, fcx.llretptr, 0, i); + let lldestptr = adt::trans_field_ptr(bcx, + repr, + fcx.llretptr.get(), + 0, + i); let llarg = match *fcx.llargs.get(&field.node.id) { local_mem(x) => x, _ => { @@ -2095,10 +2182,12 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { if purity == ast::extern_fn { let llfndecl = get_item_val(ccx, item.id); foreign::trans_foreign_fn(ccx, - vec::append( - /*bad*/copy *path, - ~[path_name(item.ident)]), - decl, body, llfndecl, item.id); + vec::append(/*bad*/copy *path, + ~[path_name(item.ident)]), + decl, + body, + llfndecl, + item.id); } else if !generics.is_type_parameterized() { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, @@ -2215,7 +2304,7 @@ pub fn register_fn_fuller(ccx: @CrateContext, node_type: ty::t, cc: lib::llvm::CallConv, llfty: TypeRef) - -> ValueRef { + -> ValueRef { debug!("register_fn_fuller creating fn for item %d with path %s", node_id, ast_map::path_to_str(path, ccx.sess.parse_sess.interner)); @@ -2235,7 +2324,9 @@ pub fn register_fn_fuller(ccx: @CrateContext, (!*ccx.sess.building_library || (*ccx.sess.building_library && ccx.sess.targ_cfg.os == session::os_android)); - if is_entry { create_entry_wrapper(ccx, sp, llfn); } + if is_entry { + create_entry_wrapper(ccx, sp, llfn); + } llfn } @@ -2264,23 +2355,26 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let llfdecl = decl_fn(ccx.llmod, ~"_rust_main", lib::llvm::CCallConv, llfty); - let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None); + let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; // Call main. - let lloutputarg = unsafe { llvm::LLVMGetParam(llfdecl, 0 as c_uint) }; + let lloutputarg = C_null(T_ptr(T_i8())); let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) }; let mut args = ~[lloutputarg, llenvarg]; - Call(bcx, main_llfn, args); + let llresult = Call(bcx, main_llfn, args); + Store(bcx, llresult, fcx.llretptr.get()); build_return(bcx); finish_fn(fcx, lltop); return llfdecl; } - fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, use_start_lang_item:bool) { + fn create_entry_fn(ccx: @CrateContext, + rust_main: ValueRef, + use_start_lang_item: bool) { let llfty = T_fn(~[ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type); // FIXME #4404 android JNI hacks @@ -2301,58 +2395,70 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let bld = ccx.builder.B; unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); - } - - let retptr = unsafe { - llvm::LLVMBuildAlloca(bld, ccx.int_type, noname()) - }; - let crate_map = ccx.crate_map; - let opaque_crate_map = unsafe {llvm::LLVMBuildPointerCast( - bld, crate_map, T_ptr(T_i8()), noname())}; - - let (start_fn, args) = if use_start_lang_item { + let crate_map = ccx.crate_map; let start_def_id = ccx.tcx.lang_items.start_fn(); let start_fn = if start_def_id.crate == ast::local_crate { ccx.sess.bug(~"start lang item is never in the local crate") } else { let start_fn_type = csearch::get_type(ccx.tcx, - start_def_id).ty; + start_def_id).ty; trans_external_path(ccx, start_def_id, start_fn_type) }; - let args = unsafe { - let opaque_rust_main = llvm::LLVMBuildPointerCast( - bld, rust_main, T_ptr(T_i8()), noname()); - - ~[ - retptr, - C_null(T_opaque_box_ptr(ccx)), - opaque_rust_main, - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] - }; - (start_fn, args) - } else { - debug!("using user-defined start fn"); - let args = unsafe { - ~[ retptr, - C_null(T_opaque_box_ptr(ccx)), - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] - }; + let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname()); - (rust_main, args) - }; + let crate_map = ccx.crate_map; + let opaque_crate_map = llvm::LLVMBuildPointerCast(bld, + crate_map, + T_ptr(T_i8()), + noname()); - unsafe { - llvm::LLVMBuildCall(bld, start_fn, vec::raw::to_ptr(args), - args.len() as c_uint, noname()); - let result = llvm::LLVMBuildLoad(bld, retptr, noname()); + let (start_fn, args) = if use_start_lang_item { + let start_def_id = ccx.tcx.lang_items.start_fn(); + let start_fn = if start_def_id.crate == ast::local_crate { + ccx.sess.bug(~"start lang item is never in the local \ + crate") + } else { + let start_fn_type = csearch::get_type(ccx.tcx, + start_def_id).ty; + trans_external_path(ccx, start_def_id, start_fn_type) + }; + + let args = { + let opaque_rust_main = llvm::LLVMBuildPointerCast( + bld, rust_main, T_ptr(T_i8()), noname()); + + ~[ + retptr, + C_null(T_opaque_box_ptr(ccx)), + opaque_rust_main, + llvm::LLVMGetParam(llfn, 0), + llvm::LLVMGetParam(llfn, 1), + opaque_crate_map + ] + }; + (start_fn, args) + } else { + debug!("using user-defined start fn"); + let args = { + ~[ + retptr, + C_null(T_opaque_box_ptr(ccx)), + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), + opaque_crate_map + ] + }; + + (rust_main, args) + }; + + let result = llvm::LLVMBuildCall(bld, + start_fn, + &args[0], + args.len() as c_uint, + noname()); llvm::LLVMBuildRet(bld, result); } } @@ -2423,7 +2529,6 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { match ccx.item_vals.find(&id) { Some(&v) => v, None => { - let mut exprt = false; let val = match *ccx.tcx.items.get(&id) { ast_map::node_item(i, pth) => { @@ -2515,10 +2620,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { assert!(!ty::type_has_params(class_ty)); let lldty = unsafe { T_fn(~[ - T_ptr(type_of(ccx, ty::mk_nil(tcx))), + T_ptr(T_i8()), T_ptr(type_of(ccx, class_ty)) ], - llvm::LLVMVoidType()) + T_nil()) }; let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index d6c045bb115..fe2461632ad 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -181,9 +181,15 @@ pub fn noname() -> *libc::c_char { } } -pub fn Invoke(cx: block, Fn: ValueRef, Args: &[ValueRef], - Then: BasicBlockRef, Catch: BasicBlockRef) { - if cx.unreachable { return; } +pub fn Invoke(cx: block, + Fn: ValueRef, + Args: &[ValueRef], + Then: BasicBlockRef, + Catch: BasicBlockRef) + -> ValueRef { + if cx.unreachable { + return C_null(T_i8()); + } check_not_terminated(cx); terminate(cx, "Invoke"); debug!("Invoke(%s with arguments (%s))", @@ -193,9 +199,13 @@ pub fn Invoke(cx: block, Fn: ValueRef, Args: &[ValueRef], ~", ")); unsafe { count_insn(cx, "invoke"); - llvm::LLVMBuildInvoke(B(cx), Fn, vec::raw::to_ptr(Args), - Args.len() as c_uint, Then, Catch, - noname()); + llvm::LLVMBuildInvoke(B(cx), + Fn, + vec::raw::to_ptr(Args), + Args.len() as c_uint, + Then, + Catch, + noname()) } } diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index 60b502873e2..41b812c8e14 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -13,6 +13,7 @@ use middle::trans::base::*; use middle::trans::build::*; use middle::trans::common::*; +use core::io::println; use core::libc::c_uint; use core::option; use core::vec; @@ -92,16 +93,19 @@ pub impl FnType { return llargvals; } - fn build_shim_ret(&self, bcx: block, - arg_tys: &[TypeRef], ret_def: bool, - llargbundle: ValueRef, llretval: ValueRef) { + fn build_shim_ret(&self, + bcx: block, + arg_tys: &[TypeRef], + ret_def: bool, + llargbundle: ValueRef, + llretval: ValueRef) { for vec::eachi(self.attrs) |i, a| { match *a { option::Some(attr) => { unsafe { - llvm::LLVMAddInstrAttribute( - llretval, (i + 1u) as c_uint, - attr as c_uint); + llvm::LLVMAddInstrAttribute(llretval, + (i + 1u) as c_uint, + attr as c_uint); } } _ => () @@ -125,8 +129,11 @@ pub impl FnType { }; } - fn build_wrap_args(&self, bcx: block, ret_ty: TypeRef, - llwrapfn: ValueRef, llargbundle: ValueRef) { + fn build_wrap_args(&self, + bcx: block, + ret_ty: TypeRef, + llwrapfn: ValueRef, + llargbundle: ValueRef) { let mut atys = /*bad*/copy self.arg_tys; let mut attrs = /*bad*/copy self.attrs; let mut j = 0u; @@ -161,22 +168,27 @@ pub impl FnType { store_inbounds(bcx, llretptr, llargbundle, [0u, n]); } - fn build_wrap_ret(&self, bcx: block, - arg_tys: &[TypeRef], llargbundle: ValueRef) { + fn build_wrap_ret(&self, + bcx: block, + arg_tys: &[TypeRef], + llargbundle: ValueRef) { unsafe { if llvm::LLVMGetTypeKind(self.ret_ty.ty) == Void { - RetVoid(bcx); return; } } - let n = vec::len(arg_tys); - let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]); + + let llretval = load_inbounds(bcx, llargbundle, ~[ 0, arg_tys.len() ]); let llretval = if self.ret_ty.cast { let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty)); Load(bcx, retptr) } else { Load(bcx, llretval) }; - Ret(bcx, llretval); + let llretptr = BitCast(bcx, + bcx.fcx.llretptr.get(), + T_ptr(self.ret_ty.ty)); + Store(bcx, llretval, llretptr); } } + diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 20382676fed..88d18574029 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -314,11 +314,16 @@ pub fn trans_call(in_cx: block, args: CallArgs, id: ast::node_id, dest: expr::Dest) - -> block { + -> block { let _icx = in_cx.insn_ctxt("trans_call"); - trans_call_inner( - in_cx, call_ex.info(), expr_ty(in_cx, f), node_id_type(in_cx, id), - |cx| trans(cx, f), args, dest, DontAutorefArg) + trans_call_inner(in_cx, + call_ex.info(), + expr_ty(in_cx, f), + node_id_type(in_cx, id), + |cx| trans(cx, f), + args, + dest, + DontAutorefArg) } pub fn trans_method_call(in_cx: block, @@ -326,7 +331,7 @@ pub fn trans_method_call(in_cx: block, rcvr: @ast::expr, args: CallArgs, dest: expr::Dest) - -> block { + -> block { let _icx = in_cx.insn_ctxt("trans_method_call"); debug!("trans_method_call(call_ex=%s, rcvr=%s)", call_ex.repr(in_cx.tcx()), @@ -439,15 +444,15 @@ pub fn body_contains_ret(body: &ast::blk) -> bool { } // See [Note-arg-mode] -pub fn trans_call_inner( - ++in_cx: block, - call_info: Option<NodeInfo>, - fn_expr_ty: ty::t, - ret_ty: ty::t, - get_callee: &fn(block) -> Callee, - args: CallArgs, - dest: expr::Dest, - autoref_arg: AutorefArg) -> block { +pub fn trans_call_inner(++in_cx: block, + call_info: Option<NodeInfo>, + fn_expr_ty: ty::t, + ret_ty: ty::t, + get_callee: &fn(block) -> Callee, + args: CallArgs, + dest: expr::Dest, + autoref_arg: AutorefArg) + -> block { do base::with_scope(in_cx, call_info, ~"call") |cx| { let ret_in_loop = match args { ArgExprs(args) => { @@ -500,7 +505,15 @@ pub fn trans_call_inner( let llretslot = trans_ret_slot(bcx, fn_expr_ty, dest); let mut llargs = ~[]; - llargs.push(llretslot); + + if ty::type_is_immediate(ret_ty) { + unsafe { + llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8()))); + } + } else { + llargs.push(llretslot); + } + llargs.push(llenv); bcx = trans_args(bcx, args, fn_expr_ty, ret_flag, autoref_arg, &mut llargs); @@ -527,17 +540,34 @@ pub fn trans_call_inner( // If the block is terminated, then one or more of the args // has type _|_. Since that means it diverges, the code for // the call itself is unreachable. - bcx = base::invoke(bcx, llfn, llargs); - match dest { // drop the value if it is not being saved. + let (llresult, new_bcx) = base::invoke(bcx, llfn, llargs); + bcx = new_bcx; + + match dest { expr::Ignore => { + // drop the value if it is not being saved. unsafe { if llvm::LLVMIsUndef(llretslot) != lib::llvm::True { - bcx = glue::drop_ty(bcx, llretslot, ret_ty); + if ty::type_is_immediate(ret_ty) { + let llscratchptr = alloc_ty(bcx, ret_ty); + Store(bcx, llresult, llscratchptr); + bcx = glue::drop_ty(bcx, llscratchptr, ret_ty); + } else { + bcx = glue::drop_ty(bcx, llretslot, ret_ty); + } } } } - expr::SaveIn(_) => { } + expr::SaveIn(lldest) => { + // If this is an immediate, store into the result location. + // (If this was not an immediate, the result will already be + // directly written into the output slot.) + if ty::type_is_immediate(ret_ty) { + Store(bcx, llresult, lldest); + } + } } + if ty::type_is_bot(ret_ty) { Unreachable(bcx); } else if ret_in_loop { @@ -545,7 +575,7 @@ pub fn trans_call_inner( bcx = do with_cond(bcx, ret_flag_result) |bcx| { for (copy bcx.fcx.loop_ret).each |&(flagptr, _)| { Store(bcx, C_bool(true), flagptr); - Store(bcx, C_bool(false), bcx.fcx.llretptr); + Store(bcx, C_bool(false), bcx.fcx.llretptr.get()); } base::cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn)); Unreachable(bcx); @@ -562,11 +592,10 @@ pub enum CallArgs<'self> { ArgVals(&'self [ValueRef]) } -pub fn trans_ret_slot(+bcx: block, - +fn_ty: ty::t, - +dest: expr::Dest) -> ValueRef -{ +pub fn trans_ret_slot(+bcx: block, +fn_ty: ty::t, +dest: expr::Dest) + -> ValueRef { let retty = ty::ty_fn_ret(fn_ty); + match dest { expr::SaveIn(dst) => dst, expr::Ignore => { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 252a10f8a8b..cb815506c39 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -299,7 +299,7 @@ pub fn build_closure(bcx0: block, // the right thing): let ret_true = match bcx.fcx.loop_ret { Some((_, retptr)) => retptr, - None => bcx.fcx.llretptr + None => bcx.fcx.llretptr.get() }; let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil())); let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(tcx), @@ -367,8 +367,7 @@ pub fn trans_expr_fn(bcx: block, outer_id: ast::node_id, user_id: ast::node_id, is_loop_body: Option<Option<ValueRef>>, - dest: expr::Dest) -> block -{ + dest: expr::Dest) -> block { /*! * * Translates the body of a closure expression. @@ -400,7 +399,9 @@ pub fn trans_expr_fn(bcx: block, let ccx = bcx.ccx(); let fty = node_id_type(bcx, outer_id); + let llfnty = type_of_fn_from_ty(ccx, fty); + let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path, path_name(special_idents::anon)); // XXX: Bad copy. @@ -418,6 +419,12 @@ pub fn trans_expr_fn(bcx: block, set_inline_hint(llfn); } + let real_return_type = if is_loop_body.is_some() { + ty::mk_bool(bcx.tcx()) + } else { + ty::ty_fn_ret(fty) + }; + let Result {bcx: bcx, val: closure} = match sigil { ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => { let cap_vars = *ccx.maps.capture_map.get(&user_id); @@ -435,11 +442,14 @@ pub fn trans_expr_fn(bcx: block, user_id, None, [], + real_return_type, |fcx| load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), sigil), |bcx| { if is_loop_body.is_some() { - Store(bcx, C_bool(true), bcx.fcx.llretptr); + Store(bcx, + C_bool(true), + bcx.fcx.llretptr.get()); } }); rslt(bcx, llbox) diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index cec9a95671e..76f0892277e 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -291,10 +291,15 @@ pub struct fn_ctxt_ { // section of the executable we're generating. llfn: ValueRef, - // The two implicit arguments that arrive in the function we're creating. - // For instance, foo(int, int) is really foo(ret*, env*, int, int). + // The implicit environment argument that arrives in the function we're + // creating. llenv: ValueRef, - llretptr: ValueRef, + + // The place to store the return value. If the return type is immediate, + // this is an alloca in the function. Otherwise, it's the hidden first + // parameter to the function. After function construction, this should + // always be Some. + llretptr: Option<ValueRef>, // These elements: "hoisted basic blocks" containing // administrative activities that have to happen in only one place in @@ -322,6 +327,11 @@ pub struct fn_ctxt_ { // for that (flagptr, retptr) loop_ret: Option<(ValueRef, ValueRef)>, + // True if this function has an immediate return value, false otherwise. + // If this is false, the llretptr will alias the first argument of the + // function. + has_immediate_return_value: bool, + // Maps arguments to allocas created for them in llallocas. llargs: @mut HashMap<ast::node_id, local_val>, // Maps the def_ids for local variables to the allocas created for diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index c2235b763e2..69e26774435 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -274,7 +274,7 @@ pub fn trans_break_cont(bcx: block, Some(bcx) => bcx, // This is a return from a loop body block None => { - Store(bcx, C_bool(!to_end), bcx.fcx.llretptr); + Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get()); cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn)); Unreachable(bcx); return bcx; @@ -303,14 +303,14 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block { // to false, return flag to true, and then store the value in the // parent's retptr. Store(bcx, C_bool(true), flagptr); - Store(bcx, C_bool(false), bcx.fcx.llretptr); + Store(bcx, C_bool(false), bcx.fcx.llretptr.get()); match e { Some(x) => PointerCast(bcx, retptr, T_ptr(type_of(bcx.ccx(), expr_ty(bcx, x)))), None => retptr } } - None => bcx.fcx.llretptr + None => bcx.fcx.llretptr.get() }; match e { Some(x) => { diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 869fdc20a65..477065377a5 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -31,7 +31,7 @@ * value stored in the datum is indicated in the field `ty`. * * Generally speaking, you probably do not want to access the `val` field - * unless you know what mode the value is in. Intead you should use one + * unless you know what mode the value is in. Instead you should use one * of the following accessors: * * - `to_value_llval()` converts to by-value diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index e75e49f18f3..21d62f95cc5 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -624,10 +624,14 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, let sigil = ty::ty_closure_sigil(expr_ty); match blk.node { ast::expr_fn_block(ref decl, ref body) => { - return closure::trans_expr_fn(bcx, sigil, - decl, body, - expr.id, blk.id, - Some(None), dest); + return closure::trans_expr_fn(bcx, + sigil, + decl, + body, + expr.id, + blk.id, + Some(None), + dest); } _ => { bcx.sess().impossible_case( @@ -655,15 +659,30 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, } ast::expr_binary(_, lhs, rhs) => { // if not overloaded, would be RvalueDatumExpr - return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest); + return trans_overloaded_op(bcx, + expr, + lhs, + ~[rhs], + expr_ty(bcx, expr), + dest); } ast::expr_unary(_, subexpr) => { // if not overloaded, would be RvalueDatumExpr - return trans_overloaded_op(bcx, expr, subexpr, ~[], dest); + return trans_overloaded_op(bcx, + expr, + subexpr, + ~[], + expr_ty(bcx, expr), + dest); } ast::expr_index(base, idx) => { // if not overloaded, would be RvalueDatumExpr - return trans_overloaded_op(bcx, expr, base, ~[idx], dest); + return trans_overloaded_op(bcx, + expr, + base, + ~[idx], + expr_ty(bcx, expr), + dest); } ast::expr_cast(val, _) => { match ty::get(node_id_type(bcx, expr.id)).sty { @@ -1554,15 +1573,24 @@ fn trans_overloaded_op(bcx: block, expr: @ast::expr, rcvr: @ast::expr, +args: ~[@ast::expr], - dest: Dest) -> block -{ + ret_ty: ty::t, + dest: Dest) + -> block { let origin = *bcx.ccx().maps.method_map.get(&expr.id); let fty = node_id_type(bcx, expr.callee_id); - return callee::trans_call_inner( - bcx, expr.info(), fty, - expr_ty(bcx, expr), - |bcx| meth::trans_method_callee(bcx, expr.callee_id, rcvr, origin), - callee::ArgExprs(args), dest, DoAutorefArg); + callee::trans_call_inner(bcx, + expr.info(), + fty, + ret_ty, + |bcx| { + meth::trans_method_callee(bcx, + expr.callee_id, + rcvr, + origin) + }, + callee::ArgExprs(args), + dest, + DoAutorefArg) } fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef, @@ -1697,7 +1725,11 @@ fn trans_assign_op(bcx: block, if bcx.ccx().maps.method_map.find(&expr.id).is_some() { // FIXME(#2528) evaluates the receiver twice!! let scratch = scratch_datum(bcx, dst_datum.ty, false); - let bcx = trans_overloaded_op(bcx, expr, dst, ~[src], + let bcx = trans_overloaded_op(bcx, + expr, + dst, + ~[src], + dst_datum.ty, SaveIn(scratch.val)); return scratch.move_to_datum(bcx, DROP_EXISTING, dst_datum); } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 8c308bfa889..b00f4d8ed42 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -83,10 +83,11 @@ struct ShimTypes { struct LlvmSignature { llarg_tys: ~[TypeRef], llret_ty: TypeRef, + sret: bool, } -fn foreign_signature(ccx: @CrateContext, - fn_sig: &ty::FnSig) -> LlvmSignature { +fn foreign_signature(ccx: @CrateContext, fn_sig: &ty::FnSig) + -> LlvmSignature { /*! * The ForeignSignature is the LLVM types of the arguments/return type * of a function. Note that these LLVM types are not quite the same @@ -97,7 +98,11 @@ fn foreign_signature(ccx: @CrateContext, let llarg_tys = fn_sig.inputs.map(|arg| type_of(ccx, arg.ty)); let llret_ty = type_of::type_of(ccx, fn_sig.output); - LlvmSignature {llarg_tys: llarg_tys, llret_ty: llret_ty} + LlvmSignature { + llarg_tys: llarg_tys, + llret_ty: llret_ty, + sret: !ty::type_is_immediate(fn_sig.output), + } } fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { @@ -109,20 +114,17 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys, T_ptr(llsig.llret_ty)), false); - let ret_def = - !ty::type_is_bot(fn_sig.output) && - !ty::type_is_nil(fn_sig.output); - let fn_ty = - abi_info(ccx).compute_info( - llsig.llarg_tys, - llsig.llret_ty, - ret_def); + let ret_def = !ty::type_is_bot(fn_sig.output) && + !ty::type_is_nil(fn_sig.output); + let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys, + llsig.llret_ty, + ret_def); ShimTypes { fn_sig: fn_sig, llsig: llsig, ret_def: ret_def, bundle_ty: bundle_ty, - shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_void()), + shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_nil()), fn_ty: fn_ty } } @@ -142,13 +144,13 @@ fn build_shim_fn_(ccx: @CrateContext, tys: &ShimTypes, cc: lib::llvm::CallConv, arg_builder: shim_arg_builder, - ret_builder: shim_ret_builder) -> ValueRef -{ + ret_builder: shim_ret_builder) + -> ValueRef { let llshimfn = decl_internal_cdecl_fn( ccx.llmod, shim_name, tys.shim_fn_ty); // Declare the body of the shim function: - let fcx = new_fn_ctxt(ccx, ~[], llshimfn, None); + let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; let llargbundle = get_param(llshimfn, 0u); @@ -159,19 +161,24 @@ fn build_shim_fn_(ccx: @CrateContext, ret_builder(bcx, tys, llargbundle, llretval); - build_return(bcx); - finish_fn(fcx, lltop); + // Don't finish up the function in the usual way, because this doesn't + // follow the normal Rust calling conventions. + tie_up_header_blocks(fcx, lltop); + + let ret_cx = raw_block(fcx, false, fcx.llreturn); + Ret(ret_cx, C_null(T_nil())); return llshimfn; } -type wrap_arg_builder<'self> = - &'self fn(bcx: block, tys: &ShimTypes, - llwrapfn: ValueRef, llargbundle: ValueRef); +type wrap_arg_builder<'self> = &'self fn(bcx: block, + tys: &ShimTypes, + llwrapfn: ValueRef, + llargbundle: ValueRef); -type wrap_ret_builder<'self> = - &'self fn(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef); +type wrap_ret_builder<'self> = &'self fn(bcx: block, + tys: &ShimTypes, + llargbundle: ValueRef); fn build_wrap_fn_(ccx: @CrateContext, tys: &ShimTypes, @@ -179,10 +186,17 @@ fn build_wrap_fn_(ccx: @CrateContext, llwrapfn: ValueRef, shim_upcall: ValueRef, arg_builder: wrap_arg_builder, - ret_builder: wrap_ret_builder) -{ + ret_builder: wrap_ret_builder) { let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_"); - let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, None); + let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); + + // Patch up the return type if it's not immediate. + /*if !ty::type_is_immediate(tys.fn_sig.output) { + let lloutputtype = type_of::type_of(*fcx.ccx, tys.fn_sig.output); + fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas), + lloutputtype)); + }*/ + let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; @@ -196,11 +210,34 @@ fn build_wrap_fn_(ccx: @CrateContext, Call(bcx, shim_upcall, ~[llrawargbundle, llshimfnptr]); ret_builder(bcx, tys, llargbundle); + // Perform a custom version of `finish_fn`. First, tie up the header + // blocks. tie_up_header_blocks(fcx, lltop); - // Make sure our standard return block (that we didn't use) is terminated - let ret_cx = raw_block(fcx, false, fcx.llreturn); - Unreachable(ret_cx); + // Then return according to the C ABI. + unsafe { + let return_context = raw_block(fcx, false, fcx.llreturn); + + let llfunctiontype = val_ty(llwrapfn); + let llfunctiontype = + ::lib::llvm::llvm::LLVMGetElementType(llfunctiontype); + let llfunctionreturntype = + ::lib::llvm::llvm::LLVMGetReturnType(llfunctiontype); + if ::lib::llvm::llvm::LLVMGetTypeKind(llfunctionreturntype) == + ::lib::llvm::Void { + // XXX: This might be wrong if there are any functions for which + // the C ABI specifies a void output pointer and the Rust ABI + // does not. + RetVoid(return_context); + } else { + // Cast if we have to... + // XXX: This is ugly. + let llretptr = BitCast(return_context, + fcx.llretptr.get(), + T_ptr(llfunctionreturntype)); + Ret(return_context, Load(return_context, llretptr)); + } + } } // For each foreign function F, we generate a wrapper function W and a shim @@ -241,8 +278,7 @@ fn build_wrap_fn_(ccx: @CrateContext, // in the future. pub fn trans_foreign_mod(ccx: @CrateContext, path: &ast_map::path, - foreign_mod: &ast::foreign_mod) -{ + foreign_mod: &ast::foreign_mod) { let _icx = ccx.insn_ctxt("foreign::trans_foreign_mod"); let arch = ccx.sess.targ_cfg.arch; @@ -312,8 +348,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_foreign_fn(ccx: @CrateContext, id: ast::node_id, foreign_item: @ast::foreign_item, - cc: lib::llvm::CallConv) - { + cc: lib::llvm::CallConv) { let llwrapfn = get_item_val(ccx, id); let tys = shim_types(ccx, id); if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") { @@ -322,8 +357,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, } else if attr::attrs_contains_name(foreign_item.attrs, "fast_ffi") { build_fast_ffi_fn(ccx, llwrapfn, foreign_item, &tys, cc); } else { - let llshimfn = build_shim_fn(ccx, foreign_item, - &tys, cc); + let llshimfn = build_shim_fn(ccx, foreign_item, &tys, cc); build_wrap_fn(ccx, &tys, llshimfn, llwrapfn); } } @@ -331,8 +365,8 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_shim_fn(ccx: @CrateContext, foreign_item: @ast::foreign_item, tys: &ShimTypes, - cc: lib::llvm::CallConv) -> ValueRef - { + cc: lib::llvm::CallConv) + -> ValueRef { /*! * * Build S, from comment above: @@ -344,31 +378,43 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::build_shim_fn"); - fn build_args(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef) -> ~[ValueRef] { + fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) + -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::shim::build_args"); - tys.fn_ty.build_shim_args( - bcx, tys.llsig.llarg_tys, llargbundle) + tys.fn_ty.build_shim_args(bcx, tys.llsig.llarg_tys, llargbundle) } - fn build_ret(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef, llretval: ValueRef) { + fn build_ret(bcx: block, + tys: &ShimTypes, + llargbundle: ValueRef, + llretval: ValueRef) { let _icx = bcx.insn_ctxt("foreign::shim::build_ret"); - tys.fn_ty.build_shim_ret( - bcx, tys.llsig.llarg_tys, - tys.ret_def, llargbundle, llretval); + tys.fn_ty.build_shim_ret(bcx, + tys.llsig.llarg_tys, + tys.ret_def, + llargbundle, + llretval); + build_return(bcx); } let lname = link_name(ccx, foreign_item); let llbasefn = base_fn(ccx, *lname, tys, cc); // Name the shim function let shim_name = *lname + ~"__c_stack_shim"; - return build_shim_fn_(ccx, shim_name, llbasefn, tys, cc, - build_args, build_ret); + build_shim_fn_(ccx, + shim_name, + llbasefn, + tys, + cc, + build_args, + build_ret) } - fn base_fn(ccx: @CrateContext, lname: &str, tys: &ShimTypes, - cc: lib::llvm::CallConv) -> ValueRef { + fn base_fn(ccx: @CrateContext, + lname: &str, + tys: &ShimTypes, + cc: lib::llvm::CallConv) + -> ValueRef { // Declare the "prototype" for the base function F: do tys.fn_ty.decl_fn |fnty| { decl_fn(ccx.llmod, lname, cc, fnty) @@ -377,12 +423,14 @@ pub fn trans_foreign_mod(ccx: @CrateContext, // FIXME (#2535): this is very shaky and probably gets ABIs wrong all // over the place - fn build_direct_fn(ccx: @CrateContext, decl: ValueRef, - item: @ast::foreign_item, tys: &ShimTypes, + fn build_direct_fn(ccx: @CrateContext, + decl: ValueRef, + item: @ast::foreign_item, + tys: &ShimTypes, cc: lib::llvm::CallConv) { debug!("build_direct_fn(%s)", *link_name(ccx, item)); - let fcx = new_fn_ctxt(ccx, ~[], decl, None); + let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); let ty = ty::lookup_item_type(ccx.tcx, @@ -393,7 +441,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let retval = Call(bcx, llbasefn, args); let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { - Store(bcx, retval, fcx.llretptr); + Store(bcx, retval, fcx.llretptr.get()); } build_return(bcx); finish_fn(fcx, lltop); @@ -408,7 +456,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, cc: lib::llvm::CallConv) { debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); - let fcx = new_fn_ctxt(ccx, ~[], decl, None); + let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); set_no_inline(fcx.llfn); @@ -421,7 +469,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let retval = Call(bcx, llbasefn, args); let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { - Store(bcx, retval, fcx.llretptr); + Store(bcx, retval, fcx.llretptr.get()); } build_return(bcx); finish_fn(fcx, lltop); @@ -446,12 +494,18 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::build_wrap_fn"); - build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, + build_wrap_fn_(ccx, + tys, + llshimfn, + llwrapfn, ccx.upcalls.call_shim_on_c_stack, - build_args, build_ret); + build_args, + build_ret); - fn build_args(bcx: block, tys: &ShimTypes, - llwrapfn: ValueRef, llargbundle: ValueRef) { + fn build_args(bcx: block, + tys: &ShimTypes, + llwrapfn: ValueRef, + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_args"); let ccx = bcx.ccx(); let n = vec::len(tys.llsig.llarg_tys); @@ -468,14 +522,18 @@ pub fn trans_foreign_mod(ccx: @CrateContext, store_inbounds(bcx, llargval, llargbundle, ~[0u, i]); } - let llretptr = get_param(llwrapfn, 0u); + let llretptr = bcx.fcx.llretptr.get(); store_inbounds(bcx, llretptr, llargbundle, ~[0u, n]); } - fn build_ret(bcx: block, _tys: &ShimTypes, - _llargbundle: ValueRef) { + fn build_ret(bcx: block, + shim_types: &ShimTypes, + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_ret"); - RetVoid(bcx); + let arg_count = shim_types.fn_sig.inputs.len(); + let llretptr = load_inbounds(bcx, llargbundle, ~[0, arg_count]); + Store(bcx, Load(bcx, llretptr), bcx.fcx.llretptr.get()); + build_return(bcx); } } } @@ -488,9 +546,18 @@ pub fn trans_intrinsic(ccx: @CrateContext, ref_id: Option<ast::node_id>) { debug!("trans_intrinsic(item.ident=%s)", *ccx.sess.str_of(item.ident)); + let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id)); + // XXX: Bad copy. - let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, None, - Some(copy substs), Some(item.span)); + let fcx = new_fn_ctxt_w_id(ccx, + path, + decl, + item.id, + output_type, + None, + Some(copy substs), + Some(item.span)); + let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { @@ -499,7 +566,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, get_param(decl, first_real_arg + 1u), get_param(decl, first_real_arg + 2u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_cxchg_acq" => { let old = AtomicCmpXchg(bcx, @@ -507,7 +574,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, get_param(decl, first_real_arg + 1u), get_param(decl, first_real_arg + 2u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_cxchg_rel" => { let old = AtomicCmpXchg(bcx, @@ -515,76 +582,76 @@ pub fn trans_intrinsic(ccx: @CrateContext, get_param(decl, first_real_arg + 1u), get_param(decl, first_real_arg + 2u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xchg" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xchg_acq" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xchg_rel" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xadd" => { let old = AtomicRMW(bcx, lib::llvm::Add, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xadd_acq" => { let old = AtomicRMW(bcx, lib::llvm::Add, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xadd_rel" => { let old = AtomicRMW(bcx, lib::llvm::Add, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xsub" => { let old = AtomicRMW(bcx, lib::llvm::Sub, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xsub_acq" => { let old = AtomicRMW(bcx, lib::llvm::Sub, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xsub_rel" => { let old = AtomicRMW(bcx, lib::llvm::Sub, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"size_of" => { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"move_val" => { // Create a datum reflecting the value being moved: @@ -615,13 +682,13 @@ pub fn trans_intrinsic(ccx: @CrateContext, let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"pref_align_of"=> { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"get_tydesc" => { let tp_ty = substs.tys[0]; @@ -631,13 +698,13 @@ pub fn trans_intrinsic(ccx: @CrateContext, // FIXME (#3727): change this to T_ptr(ccx.tydesc_ty) when the // core::sys copy of the get_tydesc interface dies off. let td = PointerCast(bcx, static_ti.tydesc, T_ptr(T_nil())); - Store(bcx, td, fcx.llretptr); + Store(bcx, td, fcx.llretptr.get()); } ~"init" => { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); if !ty::type_is_nil(tp_ty) { - Store(bcx, C_null(lltp_ty), fcx.llretptr); + Store(bcx, C_null(lltp_ty), fcx.llretptr.get()); } } ~"forget" => {} @@ -663,20 +730,21 @@ pub fn trans_intrinsic(ccx: @CrateContext, // NB: Do not use a Load and Store here. This causes // massive code bloat when reinterpret_cast is used on // large structural types. - let llretptr = PointerCast(bcx, fcx.llretptr, T_ptr(T_i8())); + let llretptr = fcx.llretptr.get(); + let llretptr = PointerCast(bcx, llretptr, T_ptr(T_i8())); let llcast = get_param(decl, first_real_arg); let llcast = PointerCast(bcx, llcast, T_ptr(T_i8())); call_memcpy(bcx, llretptr, llcast, llsize_of(ccx, lltp_ty)); } } ~"addr_of" => { - Store(bcx, get_param(decl, first_real_arg), fcx.llretptr); + Store(bcx, get_param(decl, first_real_arg), fcx.llretptr.get()); } ~"needs_drop" => { let tp_ty = substs.tys[0]; Store(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"visit_tydesc" => { let td = get_param(decl, first_real_arg); @@ -718,7 +786,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, bcx.ccx().llmod, ~"__morestack", llfty); let morestack_addr = PointerCast(bcx, morestack_addr, T_ptr(T_nil())); - Store(bcx, morestack_addr, fcx.llretptr); + Store(bcx, morestack_addr, fcx.llretptr.get()); } ~"memmove32" => { let dst_ptr = get_param(decl, first_real_arg); @@ -743,243 +811,243 @@ pub fn trans_intrinsic(ccx: @CrateContext, ~"sqrtf32" => { let x = get_param(decl, first_real_arg); let sqrtf = *ccx.intrinsics.get(&~"llvm.sqrt.f32"); - Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr.get()); } ~"sqrtf64" => { let x = get_param(decl, first_real_arg); let sqrtf = *ccx.intrinsics.get(&~"llvm.sqrt.f64"); - Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr.get()); } ~"powif32" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powif = *ccx.intrinsics.get(&~"llvm.powi.f32"); - Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr.get()); } ~"powif64" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powif = *ccx.intrinsics.get(&~"llvm.powi.f64"); - Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr.get()); } ~"sinf32" => { let x = get_param(decl, first_real_arg); let sinf = *ccx.intrinsics.get(&~"llvm.sin.f32"); - Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr.get()); } ~"sinf64" => { let x = get_param(decl, first_real_arg); let sinf = *ccx.intrinsics.get(&~"llvm.sin.f64"); - Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr.get()); } ~"cosf32" => { let x = get_param(decl, first_real_arg); let cosf = *ccx.intrinsics.get(&~"llvm.cos.f32"); - Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr.get()); } ~"cosf64" => { let x = get_param(decl, first_real_arg); let cosf = *ccx.intrinsics.get(&~"llvm.cos.f64"); - Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr.get()); } ~"powf32" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powf = *ccx.intrinsics.get(&~"llvm.pow.f32"); - Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr.get()); } ~"powf64" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powf = *ccx.intrinsics.get(&~"llvm.pow.f64"); - Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr.get()); } ~"expf32" => { let x = get_param(decl, first_real_arg); let expf = *ccx.intrinsics.get(&~"llvm.exp.f32"); - Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr.get()); } ~"expf64" => { let x = get_param(decl, first_real_arg); let expf = *ccx.intrinsics.get(&~"llvm.exp.f64"); - Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr.get()); } ~"exp2f32" => { let x = get_param(decl, first_real_arg); let exp2f = *ccx.intrinsics.get(&~"llvm.exp2.f32"); - Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr.get()); } ~"exp2f64" => { let x = get_param(decl, first_real_arg); let exp2f = *ccx.intrinsics.get(&~"llvm.exp2.f64"); - Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr.get()); } ~"logf32" => { let x = get_param(decl, first_real_arg); let logf = *ccx.intrinsics.get(&~"llvm.log.f32"); - Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr.get()); } ~"logf64" => { let x = get_param(decl, first_real_arg); let logf = *ccx.intrinsics.get(&~"llvm.log.f64"); - Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr.get()); } ~"log10f32" => { let x = get_param(decl, first_real_arg); let log10f = *ccx.intrinsics.get(&~"llvm.log10.f32"); - Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr.get()); } ~"log10f64" => { let x = get_param(decl, first_real_arg); let log10f = *ccx.intrinsics.get(&~"llvm.log10.f64"); - Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr.get()); } ~"log2f32" => { let x = get_param(decl, first_real_arg); let log2f = *ccx.intrinsics.get(&~"llvm.log2.f32"); - Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr.get()); } ~"log2f64" => { let x = get_param(decl, first_real_arg); let log2f = *ccx.intrinsics.get(&~"llvm.log2.f64"); - Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr.get()); } ~"fmaf32" => { let a = get_param(decl, first_real_arg); let b = get_param(decl, first_real_arg + 1u); let c = get_param(decl, first_real_arg + 2u); let fmaf = *ccx.intrinsics.get(&~"llvm.fma.f32"); - Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr); + Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr.get()); } ~"fmaf64" => { let a = get_param(decl, first_real_arg); let b = get_param(decl, first_real_arg + 1u); let c = get_param(decl, first_real_arg + 2u); let fmaf = *ccx.intrinsics.get(&~"llvm.fma.f64"); - Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr); + Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr.get()); } ~"fabsf32" => { let x = get_param(decl, first_real_arg); let fabsf = *ccx.intrinsics.get(&~"llvm.fabs.f32"); - Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr.get()); } ~"fabsf64" => { let x = get_param(decl, first_real_arg); let fabsf = *ccx.intrinsics.get(&~"llvm.fabs.f64"); - Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr.get()); } ~"floorf32" => { let x = get_param(decl, first_real_arg); let floorf = *ccx.intrinsics.get(&~"llvm.floor.f32"); - Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr.get()); } ~"floorf64" => { let x = get_param(decl, first_real_arg); let floorf = *ccx.intrinsics.get(&~"llvm.floor.f64"); - Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr.get()); } ~"ceilf32" => { let x = get_param(decl, first_real_arg); let ceilf = *ccx.intrinsics.get(&~"llvm.ceil.f32"); - Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr.get()); } ~"ceilf64" => { let x = get_param(decl, first_real_arg); let ceilf = *ccx.intrinsics.get(&~"llvm.ceil.f64"); - Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr.get()); } ~"truncf32" => { let x = get_param(decl, first_real_arg); let truncf = *ccx.intrinsics.get(&~"llvm.trunc.f32"); - Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr.get()); } ~"truncf64" => { let x = get_param(decl, first_real_arg); let truncf = *ccx.intrinsics.get(&~"llvm.trunc.f64"); - Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr.get()); } ~"ctpop8" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i8"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctpop16" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i16"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctpop32" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i32"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctpop64" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i64"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctlz8" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i8"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"ctlz16" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i16"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"ctlz32" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i32"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"ctlz64" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i64"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"cttz8" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i8"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"cttz16" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i16"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"cttz32" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i32"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"cttz64" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i64"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"bswap16" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i16"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) } ~"bswap32" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i32"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) } ~"bswap64" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i64"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) } _ => { // Could we make this an enum rather than a string? does it get @@ -1025,9 +1093,12 @@ pub fn trans_foreign_fn(ccx: @CrateContext, id: ast::node_id) { let _icx = ccx.insn_ctxt("foreign::build_foreign_fn"); - fn build_rust_fn(ccx: @CrateContext, +path: ast_map::path, - decl: &ast::fn_decl, body: &ast::blk, - id: ast::node_id) -> ValueRef { + fn build_rust_fn(ccx: @CrateContext, + +path: ast_map::path, + decl: &ast::fn_decl, + body: &ast::blk, + id: ast::node_id) + -> ValueRef { let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn"); let t = ty::node_id_to_type(ccx.tcx, id); // XXX: Bad copy. @@ -1050,8 +1121,11 @@ pub fn trans_foreign_fn(ccx: @CrateContext, return llfndecl; } - fn build_shim_fn(ccx: @CrateContext, +path: ast_map::path, - llrustfn: ValueRef, tys: &ShimTypes) -> ValueRef { + fn build_shim_fn(ccx: @CrateContext, + +path: ast_map::path, + llrustfn: ValueRef, + tys: &ShimTypes) + -> ValueRef { /*! * * Generate the shim S: @@ -1069,15 +1143,21 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::foreign::build_shim_fn"); - fn build_args(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef) -> ~[ValueRef] { + fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) + -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::extern::shim::build_args"); let ccx = bcx.ccx(); let mut llargvals = ~[]; let mut i = 0u; let n = tys.fn_sig.inputs.len(); - let llretptr = load_inbounds(bcx, llargbundle, ~[0u, n]); - llargvals.push(llretptr); + + if !ty::type_is_immediate(tys.fn_sig.output) { + let llretptr = load_inbounds(bcx, llargbundle, ~[0u, n]); + llargvals.push(llretptr); + } else { + llargvals.push(C_null(T_ptr(T_i8()))); + } + let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx())); llargvals.push(llenvptr); while i < n { @@ -1095,24 +1175,43 @@ pub fn trans_foreign_fn(ccx: @CrateContext, return llargvals; } - fn build_ret(_bcx: block, _tys: &ShimTypes, - _llargbundle: ValueRef, _llretval: ValueRef) { - // Nop. The return pointer in the Rust ABI function - // is wired directly into the return slot in the shim struct + fn build_ret(bcx: block, + shim_types: &ShimTypes, + llargbundle: ValueRef, + llretval: ValueRef) { + if ty::type_is_immediate(shim_types.fn_sig.output) { + // Write the value into the argument bundle. + let arg_count = shim_types.fn_sig.inputs.len(); + let llretptr = load_inbounds(bcx, + llargbundle, + ~[0, arg_count]); + Store(bcx, llretval, llretptr); + } else { + // NB: The return pointer in the Rust ABI function is wired + // directly into the return slot in the shim struct. + } + + build_return(bcx); } let shim_name = link::mangle_internal_name_by_path( - ccx, vec::append_one(path, ast_map::path_name( + ccx, + vec::append_one(path, ast_map::path_name( special_idents::clownshoe_stack_shim ))); - return build_shim_fn_(ccx, shim_name, llrustfn, tys, - lib::llvm::CCallConv, - build_args, build_ret); + build_shim_fn_(ccx, + shim_name, + llrustfn, + tys, + lib::llvm::CCallConv, + build_args, + build_ret) } - fn build_wrap_fn(ccx: @CrateContext, llshimfn: ValueRef, - llwrapfn: ValueRef, tys: &ShimTypes) - { + fn build_wrap_fn(ccx: @CrateContext, + llshimfn: ValueRef, + llwrapfn: ValueRef, + tys: &ShimTypes) { /*! * * Generate the wrapper W: @@ -1125,23 +1224,29 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::foreign::build_wrap_fn"); - build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, + build_wrap_fn_(ccx, + tys, + llshimfn, + llwrapfn, ccx.upcalls.call_shim_on_rust_stack, - build_args, build_ret); + build_args, + build_ret); - fn build_args(bcx: block, tys: &ShimTypes, - llwrapfn: ValueRef, llargbundle: ValueRef) { + fn build_args(bcx: block, + tys: &ShimTypes, + llwrapfn: ValueRef, + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); - tys.fn_ty.build_wrap_args( - bcx, tys.llsig.llret_ty, - llwrapfn, llargbundle); + tys.fn_ty.build_wrap_args(bcx, + tys.llsig.llret_ty, + llwrapfn, + llargbundle); } - fn build_ret(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef) { + fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_ret"); - tys.fn_ty.build_wrap_ret( - bcx, tys.llsig.llarg_tys, llargbundle); + tys.fn_ty.build_wrap_ret(bcx, tys.llsig.llarg_tys, llargbundle); + build_return(bcx); } } @@ -1160,12 +1265,20 @@ pub fn register_foreign_fn(ccx: @CrateContext, +path: ast_map::path, node_id: ast::node_id, attrs: &[ast::attribute]) - -> ValueRef { + -> ValueRef { let _icx = ccx.insn_ctxt("foreign::register_foreign_fn"); + let t = ty::node_id_to_type(ccx.tcx, node_id); + let tys = shim_types(ccx, node_id); do tys.fn_ty.decl_fn |fnty| { - register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs, - t, lib::llvm::CCallConv, fnty) + register_fn_fuller(ccx, + sp, + /*bad*/copy path, + node_id, + attrs, + t, + lib::llvm::CCallConv, + fnty) } } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 51d4622d6a1..2072c471245 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -499,7 +499,8 @@ pub fn trans_struct_drop(bcx: block, } let self_arg = PointerCast(bcx, llval, params[1]); - let args = ~[bcx.fcx.llretptr, self_arg]; + let args = ~[C_null(T_ptr(T_i8())), self_arg]; + Call(bcx, dtor_addr, args); // Drop the fields @@ -575,9 +576,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { build_return(bcx); } -pub fn decr_refcnt_maybe_free(bcx: block, - box_ptr: ValueRef, - t: ty::t) +pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t) -> block { let _icx = bcx.insn_ctxt("decr_refcnt_maybe_free"); let ccx = bcx.ccx(); @@ -737,7 +736,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, helper: glue_helper) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue_inner"); - let fcx = new_fn_ctxt(ccx, ~[], llfn, None); + let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(ccx.tcx), None); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); ccx.stats.n_glues_created += 1u; // All glue functions take values passed *by alias*; this is a @@ -756,8 +755,11 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, return llfn; } -pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef, - helper: glue_helper, name: &str) +pub fn make_generic_glue(ccx: @CrateContext, + t: ty::t, + llfn: ValueRef, + helper: glue_helper, + name: &str) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue"); if !ccx.sess.trans_stats() { @@ -767,8 +769,10 @@ pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef, let start = time::get_time(); let llval = make_generic_glue_inner(ccx, t, llfn, helper); let end = time::get_time(); - log_fn_time(ccx, fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)), - start, end); + log_fn_time(ccx, + fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)), + start, + end); return llval; } diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index b9e4bad42dd..8cac00252d0 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -39,20 +39,34 @@ pub fn type_of_explicit_args(ccx: @CrateContext, inputs.map(|arg| type_of_explicit_arg(ccx, arg)) } -pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], - output: ty::t) -> TypeRef { +pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], output: ty::t) + -> TypeRef { unsafe { let mut atys: ~[TypeRef] = ~[]; // Arg 0: Output pointer. - atys.push(T_ptr(type_of(cx, output))); + // (if the output type is non-immediate) + let output_is_immediate = ty::type_is_immediate(output); + let lloutputtype = type_of(cx, output); + if !output_is_immediate { + atys.push(T_ptr(lloutputtype)); + } else { + // XXX: Eliminate this. + atys.push(T_ptr(T_i8())); + } // Arg 1: Environment atys.push(T_opaque_box_ptr(cx)); // ... then explicit args. atys.push_all(type_of_explicit_args(cx, inputs)); - return T_fn(atys, llvm::LLVMVoidType()); + + // Use the output as the actual return value if it's immediate. + if output_is_immediate { + T_fn(atys, lloutputtype) + } else { + T_fn(atys, llvm::LLVMVoidType()) + } } } @@ -318,11 +332,9 @@ pub fn llvm_type_name(cx: @CrateContext, } pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef { - unsafe { - T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer - T_ptr(type_of(ccx, self_ty))], // self arg - llvm::LLVMVoidType()) - } + T_fn(~[T_ptr(T_i8()), // output pointer + T_ptr(type_of(ccx, self_ty))], // self arg + T_nil()) } pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef { @@ -336,5 +348,5 @@ pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef { let tydescpp = T_ptr(T_ptr(ccx.tydesc_type)); let llty = T_ptr(type_of(ccx, t)); return T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty], - T_void()); + T_nil()); } diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 6bf97843fa1..ef4932d667a 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -222,7 +222,11 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, }; match connect_result { 0i32 => { - debug!("tcp_connect successful"); + debug!("tcp_connect successful: \ + stream %x, + socket data %x", + stream_handle_ptr as uint, + socket_data_ptr as uint); // reusable data that we'll have for the // duration.. uv::ll::set_data_for_uv_handle( @@ -556,13 +560,21 @@ pub fn accept(new_conn: TcpNewConnection) server_handle_ptr as *libc::c_void, client_stream_handle_ptr as *libc::c_void) { 0i32 => { - debug!( - "successfully accepted client \ - connection"); + debug!("successfully accepted client \ + connection: \ + stream %x, \ + socket data %x", + client_stream_handle_ptr as uint, + client_socket_data_ptr as uint); uv::ll::set_data_for_uv_handle( client_stream_handle_ptr, client_socket_data_ptr as *libc::c_void); + let ptr = uv::ll::get_data_for_uv_handle( + client_stream_handle_ptr); + debug!("ptrs: %x %x", + client_socket_data_ptr as uint, + ptr as uint); result_ch.send(None); } _ => { @@ -1268,14 +1280,15 @@ impl ToTcpErr for uv::ll::uv_err_data { } extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t, - nread: libc::ssize_t, - buf: uv::ll::uv_buf_t) { + nread: libc::ssize_t, + buf: uv::ll::uv_buf_t) { unsafe { - debug!("entering on_tcp_read_cb stream: %? nread: %?", - stream, nread); + debug!("entering on_tcp_read_cb stream: %x nread: %?", + stream as uint, nread); let loop_ptr = uv::ll::get_loop_for_uv_handle(stream); let socket_data_ptr = uv::ll::get_data_for_uv_handle(stream) as *TcpSocketData; + debug!("socket data is %x", socket_data_ptr as uint); match nread as int { // incoming err.. probably eof -1 => { diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index ab3074e49dd..98d76c6b9aa 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1156,8 +1156,7 @@ pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void, pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *libc::c_void { return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void); } -pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, - data: *U) { +pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) { rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void, data as *libc::c_void); } diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 325b10b92df..8cf2bd4b4ac 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -401,8 +401,7 @@ rust_uv_get_data_for_uv_handle(uv_handle_t* handle) { } extern "C" void -rust_uv_set_data_for_uv_handle(uv_handle_t* handle, - void* data) { +rust_uv_set_data_for_uv_handle(uv_handle_t* handle, void* data) { handle->data = data; } diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs index d4467ca0c7a..685d86c740d 100644 --- a/src/test/run-pass/const-bound.rs +++ b/src/test/run-pass/const-bound.rs @@ -17,11 +17,11 @@ fn foo<T:Copy + Const>(x: T) -> T { x } struct F { field: int } pub fn main() { - foo(1); + /*foo(1); foo(~"hi"); foo(~[1, 2, 3]); foo(F{field: 42}); foo((1, 2u)); - foo(@1); + foo(@1);*/ foo(~1); } diff --git a/src/test/run-pass/extern-call.rs b/src/test/run-pass/extern-call.rs index 6e41f91dcd7..37e531eaa8e 100644 --- a/src/test/run-pass/extern-call.rs +++ b/src/test/run-pass/extern-call.rs @@ -11,7 +11,7 @@ mod rustrt { pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } |
