提交 c995a62d 编写于 作者: P Patrick Walton

librustc: WIP patch for using the return value.

上级 7720c15a
......@@ -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 @@ fn bucket_for_key(&self, k: &K) -> SearchResult {
}
#[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 @@ fn search(&self, hash: uint,
}
}
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 @@ fn len(&const self) -> uint { self.size }
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 @@ fn clear(&mut self) {
}
}
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 @@ fn remove(&mut self, k: &K) -> bool {
}
}
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 @@ fn get<'a>(&'a self, k: &K) -> &'a 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 @@ fn contains_key_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, key: &Q)
/// 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 @@ fn find_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, k: &Q)
#[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 @@ fn find_equiv<'a, Q:Hash + IterBytes + Equiv<K>>(
}
}
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 @@ fn len(&const self) -> uint { self.map.len() }
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 @@ fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) {
}
}
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 @@ unsafe fn setvbuf(stream: *FILE, buffer: *c_char,
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 stdio {
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 @@ fn test_ranges() {
fn test_range_step_zero_step() {
for range_step(0,10,0) |_i| {}
}
}
\ No newline at end of file
}
......@@ -474,4 +474,4 @@ fn test_range_step_zero_step_up() {
fn test_range_step_zero_step_down() {
for range_step(0,-10,0) |_i| {}
}
}
\ No newline at end of file
}
......@@ -46,7 +46,7 @@
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 @@ fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U] {
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 @@ fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[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 @@ fn dedup(&mut self) {
}
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 fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
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(); }
......
此差异已折叠。
......@@ -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::build::*;
use middle::trans::common::*;
use core::io::println;
use core::libc::c_uint;
use core::option;
use core::vec;
......@@ -92,16 +93,19 @@ fn build_shim_args(&self, bcx: block,
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 @@ fn build_shim_ret(&self, bcx: block,
};
}
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 @@ fn build_wrap_args(&self, bcx: block, ret_ty: TypeRef,
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);
}
......
......@@ -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 @@ fn to_tcp_err(&self) -> TcpErrData {
}
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;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册