mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
librustc: WIP patch for using the return value.
This commit is contained in:
parent
7720c15ae1
commit
c995a62d44
@ -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};
|
||||
|
@ -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)
|
||||
|
@ -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"]
|
||||
|
@ -503,4 +503,4 @@ mod tests {
|
||||
fn test_range_step_zero_step() {
|
||||
for range_step(0,10,0) |_i| {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -474,4 +474,4 @@ mod tests {
|
||||
fn test_range_step_zero_step_down() {
|
||||
for range_step(0,-10,0) |_i| {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 = ~[];
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 => {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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 => {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user