librustc: WIP patch for using the return value.

This commit is contained in:
Patrick Walton 2013-04-18 15:53:29 -07:00
parent 7720c15ae1
commit c995a62d44
26 changed files with 779 additions and 407 deletions

View File

@ -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};

View File

@ -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)

View File

@ -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"]

View File

@ -503,4 +503,4 @@ mod tests {
fn test_range_step_zero_step() {
for range_step(0,10,0) |_i| {}
}
}
}

View File

@ -474,4 +474,4 @@ mod tests {
fn test_range_step_zero_step_down() {
for range_step(0,-10,0) |_i| {}
}
}
}

View File

@ -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 */

View File

@ -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 = ~[];

View File

@ -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;
}
}

View File

@ -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(); }

View File

@ -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,21 +2045,6 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
}
};
let fcx = new_fn_ctxt_w_id(ccx,
~[],
llfndecl,
ctor_id,
None,
param_substs,
None);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
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 }
@ -1992,10 +2058,31 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
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);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
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);
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());
let retptr = llvm::LLVMBuildAlloca(bld, 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 crate_map = ccx.crate_map;
let opaque_crate_map = llvm::LLVMBuildPointerCast(bld,
crate_map,
T_ptr(T_i8()),
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)
};
(rust_main, args)
};
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 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);

View File

@ -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())
}
}

View File

@ -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);
}
}

View File

@ -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 => {

View File

@ -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)

View File

@ -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

View File

@ -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) => {

View File

@ -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

View File

@ -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);
}

View File

@ -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)
}
}

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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 => {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}
}