Use the right type for self in methods and remove obsoleted items.
Fixes #7411, #10615.
This commit is contained in:
parent
7a305f9e83
commit
08ac616d37
@ -410,7 +410,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
||||
let inner = parse_ty(st, |x,y| conv(x,y));
|
||||
inner
|
||||
}
|
||||
'B' => ty::mk_opaque_box(st.tcx),
|
||||
'a' => {
|
||||
assert_eq!(next(st), '[');
|
||||
let did = parse_def(st, NominalType, |x,y| conv(x,y));
|
||||
|
@ -331,7 +331,6 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
|
||||
mywrite!(w, "C&");
|
||||
enc_sigil(w, p);
|
||||
}
|
||||
ty::ty_opaque_box => mywrite!(w, "B"),
|
||||
ty::ty_struct(def, ref substs) => {
|
||||
mywrite!(w, "a[{}|", (cx.ds)(def));
|
||||
enc_substs(w, cx, substs);
|
||||
|
@ -578,9 +578,6 @@ fn encode_method_map_entry(ecx: &e::EncodeContext,
|
||||
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
|
||||
mme.origin.encode(ebml_w);
|
||||
});
|
||||
ebml_w.emit_struct_field("self_mode", 3, |ebml_w| {
|
||||
mme.self_mode.encode(ebml_w);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@ -602,11 +599,7 @@ impl<'a> read_method_map_entry_helper for reader::Decoder<'a> {
|
||||
let method_origin: method_origin =
|
||||
Decodable::decode(this);
|
||||
method_origin.tr(xcx)
|
||||
}),
|
||||
self_mode: this.read_struct_field("self_mode", 3, |this| {
|
||||
let self_mode: ty::SelfMode = Decodable::decode(this);
|
||||
self_mode
|
||||
}),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1392,37 +1392,41 @@ fn insert_lllocals<'a>(
|
||||
let llval = match binding_info.trmode {
|
||||
// By value bindings: use the stack slot that we
|
||||
// copied/moved the value into
|
||||
TrByValue(lldest) => {
|
||||
if add_cleans {
|
||||
add_clean(bcx, lldest, binding_info.ty);
|
||||
}
|
||||
|
||||
lldest
|
||||
}
|
||||
|
||||
TrByValue(lldest) => lldest,
|
||||
// By ref binding: use the ptr into the matched value
|
||||
TrByRef => {
|
||||
binding_info.llmatch
|
||||
}
|
||||
TrByRef => binding_info.llmatch
|
||||
};
|
||||
|
||||
let datum = Datum {
|
||||
val: llval,
|
||||
ty: binding_info.ty,
|
||||
mode: ByRef(ZeroMem)
|
||||
};
|
||||
|
||||
if add_cleans {
|
||||
match binding_info.trmode {
|
||||
TrByValue(_) => datum.add_clean(bcx),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
debug!("binding {:?} to {}",
|
||||
binding_info.id,
|
||||
bcx.val_to_str(llval));
|
||||
let mut llmap = bcx.fcx.lllocals.borrow_mut();
|
||||
llmap.get().insert(binding_info.id, llval);
|
||||
llmap.get().insert(binding_info.id, datum);
|
||||
}
|
||||
|
||||
if bcx.sess().opts.extra_debuginfo {
|
||||
debuginfo::create_match_binding_metadata(bcx,
|
||||
ident,
|
||||
binding_info.id,
|
||||
binding_info.ty,
|
||||
binding_info.span);
|
||||
binding_info.span,
|
||||
datum);
|
||||
}
|
||||
}
|
||||
return bcx;
|
||||
bcx
|
||||
}
|
||||
|
||||
fn compile_guard<'r,
|
||||
@ -2032,8 +2036,7 @@ pub fn store_local<'a>(
|
||||
Some(path) => {
|
||||
return mk_binding_alloca(
|
||||
bcx, pat.id, path, BindLocal,
|
||||
|bcx, _, llval| expr::trans_into(bcx, init_expr,
|
||||
expr::SaveIn(llval)));
|
||||
|bcx, datum| expr::trans_into(bcx, init_expr, expr::SaveIn(datum.val)));
|
||||
}
|
||||
|
||||
None => {}
|
||||
@ -2067,13 +2070,13 @@ pub fn store_local<'a>(
|
||||
pat_bindings(tcx.def_map, pat, |_, p_id, _, path| {
|
||||
bcx = mk_binding_alloca(
|
||||
bcx, p_id, path, BindLocal,
|
||||
|bcx, var_ty, llval| { zero_mem(bcx, llval, var_ty); bcx });
|
||||
|bcx, datum| { datum.cancel_clean(bcx); bcx });
|
||||
});
|
||||
bcx
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
|
||||
pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, arg: Datum)
|
||||
-> &'a Block<'a> {
|
||||
/*!
|
||||
* Generates code for argument patterns like `fn foo(<pat>: T)`.
|
||||
@ -2093,13 +2096,12 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
|
||||
// Note that we cannot do it before for fear of a fn like
|
||||
// fn getaddr(~ref x: ~uint) -> *uint {....}
|
||||
// (From test `run-pass/func-arg-ref-pattern.rs`)
|
||||
let arg_ty = node_id_type(bcx, pat.id);
|
||||
add_clean(bcx, llval, arg_ty);
|
||||
arg.add_clean(bcx);
|
||||
|
||||
// Debug information (the llvm.dbg.declare intrinsic to be precise) always expects to get an
|
||||
// alloca, which only is the case on the general path, so lets disable the optimized path when
|
||||
// debug info is enabled.
|
||||
let arg_is_alloca = unsafe { llvm::LLVMIsAAllocaInst(llval) != ptr::null() };
|
||||
let arg_is_alloca = unsafe { llvm::LLVMIsAAllocaInst(arg.val) != ptr::null() };
|
||||
|
||||
let fast_path = (arg_is_alloca || !bcx.ccx().sess.opts.extra_debuginfo)
|
||||
&& simple_identifier(pat).is_some();
|
||||
@ -2109,37 +2111,42 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
|
||||
// `llval` wholesale as the pointer for `x`, avoiding the
|
||||
// general logic which may copy out of `llval`.
|
||||
let mut llargs = bcx.fcx.llargs.borrow_mut();
|
||||
llargs.get().insert(pat.id, llval);
|
||||
llargs.get().insert(pat.id, arg);
|
||||
} else {
|
||||
// General path. Copy out the values that are used in the
|
||||
// pattern.
|
||||
bcx = bind_irrefutable_pat(bcx, pat, llval, BindArgument);
|
||||
let llptr = arg.to_ref_llval(bcx);
|
||||
bcx = bind_irrefutable_pat(bcx, pat, llptr, BindArgument);
|
||||
}
|
||||
|
||||
return bcx;
|
||||
}
|
||||
|
||||
fn mk_binding_alloca<'a>(
|
||||
mut bcx: &'a Block<'a>,
|
||||
bcx: &'a Block<'a>,
|
||||
p_id: ast::NodeId,
|
||||
path: &ast::Path,
|
||||
binding_mode: IrrefutablePatternBindingMode,
|
||||
populate: |&'a Block<'a>,
|
||||
ty::t,
|
||||
ValueRef|
|
||||
-> &'a Block<'a>)
|
||||
populate: |&'a Block<'a>, Datum| -> &'a Block<'a>)
|
||||
-> &'a Block<'a> {
|
||||
let var_ty = node_id_type(bcx, p_id);
|
||||
let ident = ast_util::path_to_ident(path);
|
||||
let llval = alloc_ty(bcx, var_ty, bcx.ident(ident));
|
||||
bcx = populate(bcx, var_ty, llval);
|
||||
let mut llmap = match binding_mode {
|
||||
BindLocal => bcx.fcx.lllocals.borrow_mut(),
|
||||
BindArgument => bcx.fcx.llargs.borrow_mut(),
|
||||
let datum = Datum {
|
||||
val: llval,
|
||||
ty: var_ty,
|
||||
mode: ByRef(ZeroMem)
|
||||
};
|
||||
llmap.get().insert(p_id, llval);
|
||||
add_clean(bcx, llval, var_ty);
|
||||
return bcx;
|
||||
{
|
||||
let mut llmap = match binding_mode {
|
||||
BindLocal => bcx.fcx.lllocals.borrow_mut(),
|
||||
BindArgument => bcx.fcx.llargs.borrow_mut()
|
||||
};
|
||||
llmap.get().insert(p_id, datum);
|
||||
}
|
||||
let bcx = populate(bcx, datum);
|
||||
datum.add_clean(bcx);
|
||||
bcx
|
||||
}
|
||||
|
||||
fn bind_irrefutable_pat<'a>(
|
||||
@ -2179,7 +2186,7 @@ fn bind_irrefutable_pat<'a>(
|
||||
|
||||
let _indenter = indenter();
|
||||
|
||||
let _icx = push_ctxt("alt::bind_irrefutable_pat");
|
||||
let _icx = push_ctxt("match::bind_irrefutable_pat");
|
||||
let mut bcx = bcx;
|
||||
let tcx = bcx.tcx();
|
||||
let ccx = bcx.ccx();
|
||||
@ -2191,21 +2198,23 @@ fn bind_irrefutable_pat<'a>(
|
||||
// map.
|
||||
bcx = mk_binding_alloca(
|
||||
bcx, pat.id, path, binding_mode,
|
||||
|bcx, variable_ty, llvariable_val| {
|
||||
|bcx, var_datum| {
|
||||
match pat_binding_mode {
|
||||
ast::BindByValue(_) => {
|
||||
// By value binding: move the value that `val`
|
||||
// points at into the binding's stack slot.
|
||||
let datum = Datum {val: val,
|
||||
ty: variable_ty,
|
||||
mode: ByRef(ZeroMem)};
|
||||
datum.store_to(bcx, INIT, llvariable_val)
|
||||
let datum = Datum {
|
||||
val: val,
|
||||
ty: var_datum.ty,
|
||||
mode: ByRef(ZeroMem)
|
||||
};
|
||||
datum.store_to(bcx, INIT, var_datum.val)
|
||||
}
|
||||
|
||||
ast::BindByRef(_) => {
|
||||
// By ref binding: the value of the variable
|
||||
// is the pointer `val` itself.
|
||||
Store(bcx, val, llvariable_val);
|
||||
Store(bcx, val, var_datum.val);
|
||||
bcx
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ use middle::trans::callee;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::expr::*;
|
||||
use middle::trans::type_of::*;
|
||||
use middle::ty;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
@ -56,7 +55,6 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
|
||||
unpack_result!(bcx, {
|
||||
callee::trans_arg_expr(bcx,
|
||||
expr_ty(bcx, input),
|
||||
ty::ByCopy,
|
||||
input,
|
||||
&mut cleanups,
|
||||
callee::DontAutorefArg)
|
||||
|
@ -53,12 +53,12 @@ use middle::trans::expr;
|
||||
use middle::trans::foreign;
|
||||
use middle::trans::glue;
|
||||
use middle::trans::inline;
|
||||
use middle::trans::llrepr::LlvmRepr;
|
||||
use middle::trans::machine;
|
||||
use middle::trans::machine::{llalign_of_min, llsize_of};
|
||||
use middle::trans::meth;
|
||||
use middle::trans::monomorphize;
|
||||
use middle::trans::tvec;
|
||||
use middle::trans::type_::Type;
|
||||
use middle::trans::type_of;
|
||||
use middle::trans::type_of::*;
|
||||
use middle::trans::value::Value;
|
||||
@ -66,7 +66,6 @@ use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::{Repr, ty_to_str};
|
||||
use util::sha2::Sha256;
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use extra::arena::TypedArena;
|
||||
use extra::time;
|
||||
@ -218,7 +217,7 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
}
|
||||
}
|
||||
|
||||
let f = decl_rust_fn(ccx, inputs, output, name);
|
||||
let f = decl_rust_fn(ccx, None, inputs, output, name);
|
||||
csearch::get_item_attrs(ccx.tcx.cstore, did, |meta_items| {
|
||||
set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).to_owned_vec(), f)
|
||||
});
|
||||
@ -228,8 +227,12 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
f
|
||||
}
|
||||
|
||||
fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str) -> ValueRef {
|
||||
let llfty = type_of_rust_fn(ccx, inputs, output);
|
||||
fn decl_rust_fn(ccx: &CrateContext,
|
||||
self_ty: Option<ty::t>,
|
||||
inputs: &[ty::t],
|
||||
output: ty::t,
|
||||
name: &str) -> ValueRef {
|
||||
let llfty = type_of_rust_fn(ccx, self_ty, inputs, output);
|
||||
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
|
||||
|
||||
match ty::get(output).sty {
|
||||
@ -263,7 +266,7 @@ fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str)
|
||||
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,9 +284,10 @@ fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str)
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn decl_internal_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
name: &str) -> ValueRef {
|
||||
let llfn = decl_rust_fn(ccx, inputs, output, name);
|
||||
pub fn decl_internal_rust_fn(ccx: &CrateContext,
|
||||
self_ty: Option<ty::t>, inputs: &[ty::t],
|
||||
output: ty::t, name: &str) -> ValueRef {
|
||||
let llfn = decl_rust_fn(ccx, self_ty, inputs, output, name);
|
||||
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
|
||||
llfn
|
||||
}
|
||||
@ -913,7 +917,7 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
|
||||
Some(..) | None => {
|
||||
let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
|
||||
let cconv = c.unwrap_or(lib::llvm::CCallConv);
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
let llty = type_of_fn_from_ty(ccx, None, t);
|
||||
let mut externs = ccx.externs.borrow_mut();
|
||||
get_extern_fn(externs.get(), ccx.llmod, name, cconv, llty)
|
||||
}
|
||||
@ -1013,7 +1017,7 @@ pub fn need_invoke(bcx: &Block) -> bool {
|
||||
let cleanups = inf.cleanups.borrow();
|
||||
for cleanup in cleanups.get().iter() {
|
||||
match *cleanup {
|
||||
clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => {
|
||||
Clean(_, cleanup_type) | CleanTemp(_, _, cleanup_type) => {
|
||||
if cleanup_type == normal_exit_and_unwind {
|
||||
return true;
|
||||
}
|
||||
@ -1365,7 +1369,7 @@ pub fn trans_block_cleanups_<'a>(
|
||||
let mut bcx = bcx;
|
||||
for cu in cleanups.rev_iter() {
|
||||
match *cu {
|
||||
clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => {
|
||||
Clean(cfn, cleanup_type) | CleanTemp(_, cfn, cleanup_type) => {
|
||||
// Some types don't need to be cleaned up during
|
||||
// landing pads because they can be freed en mass later
|
||||
if cleanup_type == normal_exit_and_unwind || !is_lpad {
|
||||
@ -1639,7 +1643,7 @@ pub fn zero_mem(cx: &Block, llptr: ValueRef, t: ty::t) {
|
||||
// allocation for large data structures, and the generated code will be
|
||||
// awful. (A telltale sign of this is large quantities of
|
||||
// `mov [byte ptr foo],0` in the generated code.)
|
||||
pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
|
||||
fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
|
||||
let _icx = push_ctxt("memzero");
|
||||
let ccx = b.ccx;
|
||||
|
||||
@ -1865,69 +1869,116 @@ pub fn new_fn_ctxt(ccx: @CrateContext,
|
||||
// spaces that have been created for them (by code in the llallocas field of
|
||||
// the function's fn_ctxt). create_llargs_for_fn_args populates the llargs
|
||||
// field of the fn_ctxt with
|
||||
pub fn create_llargs_for_fn_args(cx: &FunctionContext,
|
||||
self_arg: self_arg,
|
||||
args: &[ast::Arg])
|
||||
-> ~[ValueRef] {
|
||||
fn create_llargs_for_fn_args(cx: &FunctionContext,
|
||||
self_arg: Option<ty::t>,
|
||||
arg_tys: &[ty::t])
|
||||
-> ~[datum::Datum] {
|
||||
let _icx = push_ctxt("create_llargs_for_fn_args");
|
||||
|
||||
match self_arg {
|
||||
impl_self(tt, self_mode) => {
|
||||
cx.llself.set(Some(ValSelfData {
|
||||
v: cx.llenv.get(),
|
||||
t: tt,
|
||||
is_copy: self_mode == ty::ByCopy
|
||||
}));
|
||||
}
|
||||
no_self => ()
|
||||
Some(t) => {
|
||||
cx.llself.set(Some(datum::Datum {
|
||||
val: cx.llenv.get(),
|
||||
ty: t,
|
||||
mode: if arg_is_indirect(cx.ccx, t) {
|
||||
datum::ByRef(datum::ZeroMem)
|
||||
} else {
|
||||
datum::ByValue
|
||||
}
|
||||
}));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
// Return an array containing the ValueRefs that we get from
|
||||
// llvm::LLVMGetParam for each argument.
|
||||
vec::from_fn(args.len(), |i| {
|
||||
unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) }
|
||||
})
|
||||
// Return an array wrapping the ValueRefs that we get from
|
||||
// llvm::LLVMGetParam for each argument into datums.
|
||||
arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
|
||||
let llarg = unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) };
|
||||
datum::Datum {
|
||||
val: llarg,
|
||||
ty: arg_ty,
|
||||
mode: if arg_is_indirect(cx.ccx, arg_ty) {
|
||||
datum::ByRef(datum::ZeroMem)
|
||||
} else {
|
||||
datum::ByValue
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn copy_args_to_allocas<'a>(
|
||||
fcx: &FunctionContext<'a>,
|
||||
fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
|
||||
bcx: &'a Block<'a>,
|
||||
args: &[ast::Arg],
|
||||
raw_llargs: &[ValueRef],
|
||||
arg_tys: &[ty::t])
|
||||
method: Option<&ast::Method>,
|
||||
raw_llargs: &[datum::Datum])
|
||||
-> &'a Block<'a> {
|
||||
debug!("copy_args_to_allocas: raw_llargs={} arg_tys={}",
|
||||
raw_llargs.llrepr(fcx.ccx),
|
||||
arg_tys.repr(fcx.ccx.tcx));
|
||||
debug!("copy_args_to_allocas: args=[{}]",
|
||||
raw_llargs.map(|d| d.to_str(fcx.ccx)).connect(", "));
|
||||
|
||||
let _icx = push_ctxt("copy_args_to_allocas");
|
||||
let mut bcx = bcx;
|
||||
|
||||
match fcx.llself.get() {
|
||||
Some(slf) => {
|
||||
let self_val = if slf.is_copy
|
||||
&& datum::appropriate_mode(bcx.ccx(), slf.t).is_by_value() {
|
||||
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
|
||||
let alloc = alloc_ty(bcx, slf.t, "__self");
|
||||
Store(bcx, tmp, alloc);
|
||||
alloc
|
||||
let needs_indirection = if slf.mode.is_by_value() {
|
||||
// FIXME(eddyb) #11445 Always needs indirection because of cleanup.
|
||||
if true {
|
||||
true
|
||||
} else {
|
||||
match method {
|
||||
Some(method) => {
|
||||
match method.explicit_self.node {
|
||||
ast::SelfValue(ast::MutMutable) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
None => true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to())
|
||||
false
|
||||
};
|
||||
let slf = if needs_indirection {
|
||||
// HACK(eddyb) this is just slf.to_ref_datum(bcx) with a named alloca.
|
||||
let alloc = alloc_ty(bcx, slf.ty, "__self");
|
||||
Store(bcx, slf.val, alloc);
|
||||
datum::Datum {
|
||||
val: alloc,
|
||||
ty: slf.ty,
|
||||
mode: datum::ByRef(datum::ZeroMem)
|
||||
}
|
||||
} else {
|
||||
slf
|
||||
};
|
||||
|
||||
fcx.llself.set(Some(ValSelfData {v: self_val, ..slf}));
|
||||
add_clean(bcx, self_val, slf.t);
|
||||
fcx.llself.set(Some(slf));
|
||||
slf.add_clean(bcx);
|
||||
|
||||
if fcx.ccx.sess.opts.extra_debuginfo {
|
||||
debuginfo::create_self_argument_metadata(bcx, slf.t, self_val);
|
||||
debuginfo::create_self_argument_metadata(bcx, slf.ty, slf.val);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
for (arg_n, &arg_ty) in arg_tys.iter().enumerate() {
|
||||
let raw_llarg = raw_llargs[arg_n];
|
||||
|
||||
for (i, &arg) in raw_llargs.iter().enumerate() {
|
||||
let needs_indirection = if arg.mode.is_by_value() {
|
||||
if fcx.ccx.sess.opts.extra_debuginfo {
|
||||
true
|
||||
} else {
|
||||
// FIXME(eddyb) #11445 Always needs indirection because of cleanup.
|
||||
if true {
|
||||
true
|
||||
} else {
|
||||
match args[i].pat.node {
|
||||
ast::PatIdent(ast::BindByValue(ast::MutMutable), _, _) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// For certain mode/type combinations, the raw llarg values are passed
|
||||
// by value. However, within the fn body itself, we want to always
|
||||
// have all locals and arguments be by-ref so that we can cancel the
|
||||
@ -1935,18 +1986,28 @@ pub fn copy_args_to_allocas<'a>(
|
||||
// the argument would be passed by value, we store it into an alloca.
|
||||
// This alloca should be optimized away by LLVM's mem-to-reg pass in
|
||||
// the event it's not truly needed.
|
||||
// only by value if immediate:
|
||||
let llarg = if datum::appropriate_mode(bcx.ccx(), arg_ty).is_by_value() {
|
||||
let alloc = alloc_ty(bcx, arg_ty, "__arg");
|
||||
Store(bcx, raw_llarg, alloc);
|
||||
alloc
|
||||
let arg = if needs_indirection {
|
||||
// HACK(eddyb) this is just arg.to_ref_datum(bcx) with a named alloca.
|
||||
let alloc = match args[i].pat.node {
|
||||
ast::PatIdent(_, ref path, _) => {
|
||||
let name = ast_util::path_to_ident(path).name;
|
||||
alloc_ty(bcx, arg.ty, token::interner_get(name))
|
||||
}
|
||||
_ => alloc_ty(bcx, arg.ty, "__arg")
|
||||
};
|
||||
Store(bcx, arg.val, alloc);
|
||||
datum::Datum {
|
||||
val: alloc,
|
||||
ty: arg.ty,
|
||||
mode: datum::ByRef(datum::ZeroMem)
|
||||
}
|
||||
} else {
|
||||
raw_llarg
|
||||
arg
|
||||
};
|
||||
bcx = _match::store_arg(bcx, args[arg_n].pat, llarg);
|
||||
bcx = _match::store_arg(bcx, args[i].pat, arg);
|
||||
|
||||
if fcx.ccx.sess.opts.extra_debuginfo {
|
||||
debuginfo::create_argument_metadata(bcx, &args[arg_n]);
|
||||
debuginfo::create_argument_metadata(bcx, &args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2001,8 +2062,6 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
|
||||
Ret(ret_cx, retval);
|
||||
}
|
||||
|
||||
pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
|
||||
|
||||
// trans_closure: Builds an LLVM function out of a source function.
|
||||
// If the function closes over its environment a closure will be
|
||||
// returned.
|
||||
@ -2011,9 +2070,10 @@ pub fn trans_closure(ccx: @CrateContext,
|
||||
decl: &ast::FnDecl,
|
||||
body: &ast::Block,
|
||||
llfndecl: ValueRef,
|
||||
self_arg: self_arg,
|
||||
self_arg: Option<ty::t>,
|
||||
param_substs: Option<@param_substs>,
|
||||
id: ast::NodeId,
|
||||
method: Option<&ast::Method>,
|
||||
_attributes: &[ast::Attribute],
|
||||
output_type: ty::t,
|
||||
maybe_load_env: |&FunctionContext|) {
|
||||
@ -2042,9 +2102,9 @@ pub fn trans_closure(ccx: @CrateContext,
|
||||
|
||||
// Set up arguments to the function.
|
||||
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
|
||||
let raw_llargs = create_llargs_for_fn_args(&fcx, self_arg, decl.inputs);
|
||||
let raw_llargs = create_llargs_for_fn_args(&fcx, self_arg, arg_tys);
|
||||
|
||||
bcx = copy_args_to_allocas(&fcx, bcx, decl.inputs, raw_llargs, arg_tys);
|
||||
bcx = copy_args_to_allocas(&fcx, bcx, decl.inputs, method, raw_llargs);
|
||||
|
||||
maybe_load_env(&fcx);
|
||||
|
||||
@ -2089,9 +2149,10 @@ pub fn trans_fn(ccx: @CrateContext,
|
||||
decl: &ast::FnDecl,
|
||||
body: &ast::Block,
|
||||
llfndecl: ValueRef,
|
||||
self_arg: self_arg,
|
||||
self_arg: Option<ty::t>,
|
||||
param_substs: Option<@param_substs>,
|
||||
id: ast::NodeId,
|
||||
method: Option<&ast::Method>,
|
||||
attrs: &[ast::Attribute]) {
|
||||
|
||||
let the_path_str = path_str(ccx.sess, path);
|
||||
@ -2109,6 +2170,7 @@ pub fn trans_fn(ccx: @CrateContext,
|
||||
self_arg,
|
||||
param_substs,
|
||||
id,
|
||||
method,
|
||||
attrs,
|
||||
output_type,
|
||||
|_fcx| { });
|
||||
@ -2191,14 +2253,13 @@ impl IdAndTy for ast::StructField {
|
||||
fn ty(&self) -> ast::P<ast::Ty> { self.node.ty }
|
||||
}
|
||||
|
||||
pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
ccx: @CrateContext,
|
||||
ctor_id: ast::NodeId,
|
||||
args: &[A],
|
||||
disr: ty::Disr,
|
||||
param_substs: Option<@param_substs>,
|
||||
llfndecl: ValueRef)
|
||||
{
|
||||
llfndecl: ValueRef) {
|
||||
// Translate variant arguments to function arguments.
|
||||
let fn_args = args.map(|varg| {
|
||||
ast::Arg {
|
||||
@ -2247,12 +2308,12 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
|
||||
let arg_tys = ty::ty_fn_args(ctor_ty);
|
||||
|
||||
let raw_llargs = create_llargs_for_fn_args(&fcx, no_self, fn_args);
|
||||
let raw_llargs = create_llargs_for_fn_args(&fcx, None, arg_tys);
|
||||
|
||||
let bcx = fcx.entry_bcx.get().unwrap();
|
||||
|
||||
insert_synthetic_type_entries(bcx, fn_args, arg_tys);
|
||||
let bcx = copy_args_to_allocas(&fcx, bcx, fn_args, raw_llargs, arg_tys);
|
||||
let bcx = copy_args_to_allocas(&fcx, bcx, fn_args, None, raw_llargs);
|
||||
|
||||
let repr = adt::represent_type(ccx, result_ty);
|
||||
adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
|
||||
@ -2266,8 +2327,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
let llargs = fcx.llargs.borrow();
|
||||
llargs.get().get_copy(&fn_arg.pat.id)
|
||||
};
|
||||
let arg_ty = arg_tys[i];
|
||||
memcpy_ty(bcx, lldestptr, llarg, arg_ty);
|
||||
llarg.move_to(bcx, datum::INIT, lldestptr);
|
||||
}
|
||||
finish_fn(&fcx, bcx);
|
||||
}
|
||||
@ -2334,9 +2394,10 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
|
||||
decl,
|
||||
body,
|
||||
llfndecl,
|
||||
no_self,
|
||||
None,
|
||||
None,
|
||||
item.id,
|
||||
None,
|
||||
item.attrs);
|
||||
} else {
|
||||
// Be sure to travel more than just one layer deep to catch nested
|
||||
@ -2448,12 +2509,13 @@ fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::Nod
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_fn(ccx: @CrateContext,
|
||||
sp: Span,
|
||||
sym: ~str,
|
||||
node_id: ast::NodeId,
|
||||
node_type: ty::t)
|
||||
-> ValueRef {
|
||||
fn register_fn(ccx: @CrateContext,
|
||||
sp: Span,
|
||||
sym: ~str,
|
||||
node_id: ast::NodeId,
|
||||
node_type: ty::t,
|
||||
self_ty: Option<ty::t>)
|
||||
-> ValueRef {
|
||||
let f = match ty::get(node_type).sty {
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
assert!(f.abis.is_rust() || f.abis.is_intrinsic());
|
||||
@ -2462,7 +2524,7 @@ pub fn register_fn(ccx: @CrateContext,
|
||||
_ => fail!("expected bare rust fn or an intrinsic")
|
||||
};
|
||||
|
||||
let llfn = decl_rust_fn(ccx, f.sig.inputs, f.sig.output, sym);
|
||||
let llfn = decl_rust_fn(ccx, self_ty, f.sig.inputs, f.sig.output, sym);
|
||||
finish_register_fn(ccx, sp, sym, node_id, llfn);
|
||||
llfn
|
||||
}
|
||||
@ -2722,7 +2784,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
|
||||
ast::ItemFn(_, purity, _, _, _) => {
|
||||
let llfn = if purity != ast::ExternFn {
|
||||
register_fn(ccx, i.span, sym, i.id, ty)
|
||||
register_fn(ccx, i.span, sym, i.id, ty, None)
|
||||
} else {
|
||||
foreign::register_rust_fn_with_foreign_abi(ccx,
|
||||
i.span,
|
||||
@ -2826,7 +2888,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
|
||||
llfn = match enm.node {
|
||||
ast::ItemEnum(_, _) => {
|
||||
register_fn(ccx, (*v).span, sym, id, ty)
|
||||
register_fn(ccx, (*v).span, sym, id, ty, None)
|
||||
}
|
||||
_ => fail!("NodeVariant, shouldn't happen")
|
||||
};
|
||||
@ -2851,7 +2913,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
let sym = exported_name(ccx, (*struct_path).clone(), ty,
|
||||
struct_item.attrs);
|
||||
let llfn = register_fn(ccx, struct_item.span,
|
||||
sym, ctor_id, ty);
|
||||
sym, ctor_id, ty, None);
|
||||
set_inline_hint(llfn);
|
||||
llfn
|
||||
}
|
||||
@ -2881,10 +2943,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_method(ccx: @CrateContext,
|
||||
id: ast::NodeId,
|
||||
path: @ast_map::Path,
|
||||
m: @ast::Method) -> ValueRef {
|
||||
fn register_method(ccx: @CrateContext,
|
||||
id: ast::NodeId,
|
||||
path: @ast_map::Path,
|
||||
m: &ast::Method) -> ValueRef {
|
||||
let mty = ty::node_id_to_type(ccx.tcx, id);
|
||||
|
||||
let mut path = (*path).clone();
|
||||
@ -2892,7 +2954,11 @@ pub fn register_method(ccx: @CrateContext,
|
||||
|
||||
let sym = exported_name(ccx, path, mty, m.attrs);
|
||||
|
||||
let llfn = register_fn(ccx, m.span, sym, id, mty);
|
||||
let self_ty = match m.explicit_self.node {
|
||||
ast::SelfStatic => None,
|
||||
_ => Some(ty::node_id_to_type(ccx.tcx, m.self_id))
|
||||
};
|
||||
let llfn = register_fn(ccx, m.span, sym, id, mty, self_ty);
|
||||
set_llvm_fn_attrs(m.attrs, llfn);
|
||||
llfn
|
||||
}
|
||||
|
@ -60,8 +60,7 @@ pub struct FnData {
|
||||
pub struct MethodData {
|
||||
llfn: ValueRef,
|
||||
llself: ValueRef,
|
||||
temp_cleanup: Option<ValueRef>,
|
||||
self_mode: ty::SelfMode,
|
||||
temp_cleanup: Option<ValueRef>
|
||||
}
|
||||
|
||||
pub enum CalleeData {
|
||||
@ -398,7 +397,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
let ref_ty = common::node_id_type(bcx, ref_id);
|
||||
|
||||
val = PointerCast(
|
||||
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
|
||||
bcx, val, type_of::type_of_fn_from_ty(ccx, None, ref_ty).ptr_to());
|
||||
}
|
||||
return FnData {llfn: val};
|
||||
}
|
||||
@ -437,7 +436,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
// This can occur on either a crate-local or crate-external
|
||||
// reference. It also occurs when testing libcore and in some
|
||||
// other weird situations. Annoying.
|
||||
let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty);
|
||||
let llty = type_of::type_of_fn_from_ty(ccx, None, fn_tpt.ty);
|
||||
let llptrty = llty.ptr_to();
|
||||
if val_ty(val) != llptrty {
|
||||
val = BitCast(bcx, val, llptrty);
|
||||
@ -496,10 +495,7 @@ pub fn trans_method_call<'a>(
|
||||
call_ex.repr(in_cx.tcx()),
|
||||
origin.repr(in_cx.tcx()));
|
||||
|
||||
meth::trans_method_callee(cx,
|
||||
callee_id,
|
||||
rcvr,
|
||||
origin)
|
||||
meth::trans_method_callee(cx, callee_id, rcvr, origin)
|
||||
}
|
||||
None => {
|
||||
cx.tcx().sess.span_bug(call_ex.span, "method call expr wasn't in method map")
|
||||
@ -799,7 +795,6 @@ pub fn trans_args<'a>(
|
||||
let arg_val = unpack_result!(bcx, {
|
||||
trans_arg_expr(bcx,
|
||||
arg_ty,
|
||||
ty::ByCopy,
|
||||
*arg_expr,
|
||||
&mut temp_cleanups,
|
||||
autoref_arg)
|
||||
@ -832,7 +827,6 @@ pub enum AutorefArg {
|
||||
pub fn trans_arg_expr<'a>(
|
||||
bcx: &'a Block<'a>,
|
||||
formal_arg_ty: ty::t,
|
||||
self_mode: ty::SelfMode,
|
||||
arg_expr: &ast::Expr,
|
||||
temp_cleanups: &mut ~[ValueRef],
|
||||
autoref_arg: AutorefArg)
|
||||
@ -840,9 +834,8 @@ pub fn trans_arg_expr<'a>(
|
||||
let _icx = push_ctxt("trans_arg_expr");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
debug!("trans_arg_expr(formal_arg_ty=({}), self_mode={:?}, arg_expr={})",
|
||||
debug!("trans_arg_expr(formal_arg_ty=({}), arg_expr={})",
|
||||
formal_arg_ty.repr(bcx.tcx()),
|
||||
self_mode,
|
||||
arg_expr.repr(bcx.tcx()));
|
||||
|
||||
// translate the arg expr to a datum
|
||||
@ -888,16 +881,8 @@ pub fn trans_arg_expr<'a>(
|
||||
arg_datum
|
||||
};
|
||||
|
||||
val = match self_mode {
|
||||
ty::ByRef => {
|
||||
debug!("by ref arg with type {}", bcx.ty_to_str(arg_datum.ty));
|
||||
arg_datum.to_ref_llval(bcx)
|
||||
}
|
||||
ty::ByCopy => {
|
||||
debug!("by copy arg with type {}", bcx.ty_to_str(arg_datum.ty));
|
||||
arg_datum.to_appropriate_llval(bcx)
|
||||
}
|
||||
}
|
||||
debug!("by copy arg with type {}", bcx.ty_to_str(arg_datum.ty));
|
||||
val = arg_datum.to_appropriate_llval(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,7 +405,7 @@ pub fn trans_expr_fn<'a>(
|
||||
let s = mangle_internal_name_by_path_and_seq(ccx,
|
||||
sub_path.clone(),
|
||||
"expr_fn");
|
||||
let llfn = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
|
||||
let llfn = decl_internal_rust_fn(ccx, None, f.sig.inputs, f.sig.output, s);
|
||||
|
||||
// set an inline hint for all closures
|
||||
set_inline_hint(llfn);
|
||||
@ -423,9 +423,10 @@ pub fn trans_expr_fn<'a>(
|
||||
decl,
|
||||
body,
|
||||
llfn,
|
||||
no_self,
|
||||
None,
|
||||
bcx.fcx.param_substs,
|
||||
user_id,
|
||||
None,
|
||||
[],
|
||||
ty::ty_fn_ret(fty),
|
||||
|fcx| load_environment(fcx, cdata_ty, cap_vars, sigil));
|
||||
|
@ -158,13 +158,6 @@ pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
|
||||
|
||||
pub type ExternMap = HashMap<~str, ValueRef>;
|
||||
|
||||
// Types used for llself.
|
||||
pub struct ValSelfData {
|
||||
v: ValueRef,
|
||||
t: ty::t,
|
||||
is_copy: bool,
|
||||
}
|
||||
|
||||
// Here `self_ty` is the real type of the self parameter to this method. It
|
||||
// will only be set in the case of default methods.
|
||||
pub struct param_substs {
|
||||
@ -227,7 +220,7 @@ pub struct FunctionContext<'a> {
|
||||
// NB: This is the type of the self *variable*, not the self *type*. The
|
||||
// self type is set only for default methods, while the self variable is
|
||||
// set for all methods.
|
||||
llself: Cell<Option<ValSelfData>>,
|
||||
llself: Cell<Option<datum::Datum>>,
|
||||
// The a value alloca'd for calls to upcalls.rust_personality. Used when
|
||||
// outputting the resume instruction.
|
||||
personality: Cell<Option<ValueRef>>,
|
||||
@ -238,10 +231,10 @@ pub struct FunctionContext<'a> {
|
||||
caller_expects_out_pointer: bool,
|
||||
|
||||
// Maps arguments to allocas created for them in llallocas.
|
||||
llargs: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
llargs: RefCell<HashMap<ast::NodeId, datum::Datum>>,
|
||||
// Maps the def_ids for local variables to the allocas created for
|
||||
// them in llallocas.
|
||||
lllocals: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
lllocals: RefCell<HashMap<ast::NodeId, datum::Datum>>,
|
||||
// Same as above, but for closure upvars
|
||||
llupvars: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
|
||||
@ -342,28 +335,14 @@ pub trait CleanupFunction {
|
||||
}
|
||||
|
||||
/// A cleanup function that calls the "drop glue" (destructor function) on
|
||||
/// a typed value.
|
||||
pub struct TypeDroppingCleanupFunction {
|
||||
val: ValueRef,
|
||||
t: ty::t,
|
||||
/// a datum.
|
||||
struct DatumDroppingCleanupFunction {
|
||||
datum: datum::Datum
|
||||
}
|
||||
|
||||
impl CleanupFunction for TypeDroppingCleanupFunction {
|
||||
impl CleanupFunction for DatumDroppingCleanupFunction {
|
||||
fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
|
||||
glue::drop_ty(block, self.val, self.t)
|
||||
}
|
||||
}
|
||||
|
||||
/// A cleanup function that calls the "drop glue" (destructor function) on
|
||||
/// an immediate typed value.
|
||||
pub struct ImmediateTypeDroppingCleanupFunction {
|
||||
val: ValueRef,
|
||||
t: ty::t,
|
||||
}
|
||||
|
||||
impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
|
||||
fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
|
||||
glue::drop_ty_immediate(block, self.val, self.t)
|
||||
self.datum.drop_val(block)
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,16 +369,16 @@ impl CleanupFunction for ExchangeHeapFreeingCleanupFunction {
|
||||
}
|
||||
|
||||
pub enum cleanup {
|
||||
clean(@CleanupFunction, cleantype),
|
||||
clean_temp(ValueRef, @CleanupFunction, cleantype),
|
||||
Clean(@CleanupFunction, cleantype),
|
||||
CleanTemp(ValueRef, @CleanupFunction, cleantype),
|
||||
}
|
||||
|
||||
// Can't use deriving(Clone) because of the managed closure.
|
||||
impl Clone for cleanup {
|
||||
fn clone(&self) -> cleanup {
|
||||
match *self {
|
||||
clean(f, ct) => clean(f, ct),
|
||||
clean_temp(v, f, ct) => clean_temp(v, f, ct),
|
||||
Clean(f, ct) => Clean(f, ct),
|
||||
CleanTemp(v, f, ct) => CleanTemp(v, f, ct),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -438,20 +417,21 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clean(bcx: &Block, val: ValueRef, t: ty::t) {
|
||||
if !ty::type_needs_drop(bcx.tcx(), t) {
|
||||
return
|
||||
}
|
||||
pub fn add_clean(bcx: &Block, val: ValueRef, ty: ty::t) {
|
||||
if !ty::type_needs_drop(bcx.tcx(), ty) { return; }
|
||||
|
||||
debug!("add_clean({}, {}, {})", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
|
||||
debug!("add_clean({}, {}, {})", bcx.to_str(), bcx.val_to_str(val), ty.repr(bcx.tcx()));
|
||||
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), ty);
|
||||
in_scope_cx(bcx, None, |scope_info| {
|
||||
{
|
||||
let mut cleanups = scope_info.cleanups.borrow_mut();
|
||||
cleanups.get().push(clean(@TypeDroppingCleanupFunction {
|
||||
val: val,
|
||||
t: t,
|
||||
cleanups.get().push(Clean(@DatumDroppingCleanupFunction {
|
||||
datum: datum::Datum {
|
||||
val: val,
|
||||
ty: ty,
|
||||
mode: datum::ByRef(datum::ZeroMem)
|
||||
}
|
||||
} as @CleanupFunction,
|
||||
cleanup_type));
|
||||
}
|
||||
@ -459,21 +439,24 @@ pub fn add_clean(bcx: &Block, val: ValueRef, t: ty::t) {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_clean_temp_immediate(cx: &Block, val: ValueRef, ty: ty::t) {
|
||||
if !ty::type_needs_drop(cx.tcx(), ty) { return; }
|
||||
pub fn add_clean_temp_immediate(bcx: &Block, val: ValueRef, ty: ty::t) {
|
||||
if !ty::type_needs_drop(bcx.tcx(), ty) { return; }
|
||||
|
||||
debug!("add_clean_temp_immediate({}, {}, {})",
|
||||
cx.to_str(), cx.val_to_str(val),
|
||||
ty.repr(cx.tcx()));
|
||||
let cleanup_type = cleanup_type(cx.tcx(), ty);
|
||||
in_scope_cx(cx, None, |scope_info| {
|
||||
bcx.to_str(), bcx.val_to_str(val),
|
||||
ty.repr(bcx.tcx()));
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), ty);
|
||||
in_scope_cx(bcx, None, |scope_info| {
|
||||
{
|
||||
let mut cleanups = scope_info.cleanups.borrow_mut();
|
||||
cleanups.get().push(clean_temp(val,
|
||||
@ImmediateTypeDroppingCleanupFunction {
|
||||
cleanups.get().push(CleanTemp(val, @DatumDroppingCleanupFunction {
|
||||
datum: datum::Datum {
|
||||
val: val,
|
||||
t: ty,
|
||||
} as @CleanupFunction,
|
||||
cleanup_type));
|
||||
ty: ty,
|
||||
mode: datum::ByValue
|
||||
}
|
||||
} as @CleanupFunction,
|
||||
cleanup_type));
|
||||
}
|
||||
grow_scope_clean(scope_info);
|
||||
})
|
||||
@ -500,12 +483,14 @@ pub fn add_clean_temp_mem_in_scope_(bcx: &Block, scope_id: Option<ast::NodeId>,
|
||||
in_scope_cx(bcx, scope_id, |scope_info| {
|
||||
{
|
||||
let mut cleanups = scope_info.cleanups.borrow_mut();
|
||||
cleanups.get().push(clean_temp(val,
|
||||
@TypeDroppingCleanupFunction {
|
||||
cleanups.get().push(CleanTemp(val, @DatumDroppingCleanupFunction {
|
||||
datum: datum::Datum {
|
||||
val: val,
|
||||
t: t,
|
||||
} as @CleanupFunction,
|
||||
cleanup_type));
|
||||
ty: t,
|
||||
mode: datum::ByRef(datum::RevokeClean)
|
||||
}
|
||||
} as @CleanupFunction,
|
||||
cleanup_type));
|
||||
}
|
||||
grow_scope_clean(scope_info);
|
||||
})
|
||||
@ -527,7 +512,7 @@ pub fn add_clean_free(cx: &Block, ptr: ValueRef, heap: heap) {
|
||||
in_scope_cx(cx, None, |scope_info| {
|
||||
{
|
||||
let mut cleanups = scope_info.cleanups.borrow_mut();
|
||||
cleanups.get().push(clean_temp(ptr,
|
||||
cleanups.get().push(CleanTemp(ptr,
|
||||
free_fn,
|
||||
normal_exit_and_unwind));
|
||||
}
|
||||
@ -543,22 +528,26 @@ pub fn revoke_clean(cx: &Block, val: ValueRef) {
|
||||
in_scope_cx(cx, None, |scope_info| {
|
||||
let cleanup_pos = {
|
||||
let mut cleanups = scope_info.cleanups.borrow_mut();
|
||||
debug!("revoke_clean({}, {}) revoking {:?} from {:?}",
|
||||
cx.to_str(), cx.val_to_str(val), val, cleanups.get());
|
||||
cleanups.get().iter().position(|cu| {
|
||||
match *cu {
|
||||
clean_temp(v, _, _) if v == val => true,
|
||||
CleanTemp(v, _, _) if v == val => true,
|
||||
_ => false
|
||||
}
|
||||
})
|
||||
};
|
||||
for i in cleanup_pos.iter() {
|
||||
debug!("revoke_clean({}, {}) revoking {:?}",
|
||||
cx.to_str(), cx.val_to_str(val), cleanup_pos);
|
||||
for &i in cleanup_pos.iter() {
|
||||
let new_cleanups = {
|
||||
let cleanups = scope_info.cleanups.borrow();
|
||||
vec::append(cleanups.get().slice(0u, *i).to_owned(),
|
||||
cleanups.get().slice(*i + 1u, cleanups.get()
|
||||
.len()))
|
||||
vec::append(cleanups.get().slice(0u, i).to_owned(),
|
||||
cleanups.get().slice(i + 1u, cleanups.get()
|
||||
.len()))
|
||||
};
|
||||
scope_info.cleanups.set(new_cleanups);
|
||||
shrink_scope_clean(scope_info, *i);
|
||||
shrink_scope_clean(scope_info, i);
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -767,16 +756,16 @@ pub fn in_scope_cx<'a>(
|
||||
Some(inf) => match scope_id {
|
||||
Some(wanted) => match inf.node_info {
|
||||
Some(NodeInfo { id: actual, .. }) if wanted == actual => {
|
||||
debug!("in_scope_cx: selected cur={} (cx={})",
|
||||
cur.to_str(), cx.to_str());
|
||||
debug!("in_scope_cx: selected cur={} (cx={}) info={:?}",
|
||||
cur.to_str(), cx.to_str(), inf.node_info);
|
||||
f(inf);
|
||||
return;
|
||||
},
|
||||
_ => inf.parent,
|
||||
},
|
||||
None => {
|
||||
debug!("in_scope_cx: selected cur={} (cx={})",
|
||||
cur.to_str(), cx.to_str());
|
||||
debug!("in_scope_cx: selected cur={} (cx={}) info={:?}",
|
||||
cur.to_str(), cx.to_str(), inf.node_info);
|
||||
f(inf);
|
||||
return;
|
||||
}
|
||||
@ -1042,8 +1031,7 @@ pub enum MonoDataClass {
|
||||
pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_float(_) => MonoFloat,
|
||||
ty::ty_rptr(..) | ty::ty_uniq(..) |
|
||||
ty::ty_box(..) | ty::ty_opaque_box(..) |
|
||||
ty::ty_rptr(..) | ty::ty_uniq(..) | ty::ty_box(..) |
|
||||
ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) |
|
||||
ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) |
|
||||
ty::ty_bare_fn(..) => MonoNonNull,
|
||||
|
@ -113,6 +113,7 @@ pub enum CopyAction {
|
||||
DROP_EXISTING
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct Datum {
|
||||
/// The llvm value. This is either a pointer to the Rust value or
|
||||
/// the value itself, depending on `mode` below.
|
||||
@ -130,7 +131,7 @@ pub struct DatumBlock<'a> {
|
||||
datum: Datum,
|
||||
}
|
||||
|
||||
#[deriving(Eq, IterBytes)]
|
||||
#[deriving(Clone, Eq, IterBytes)]
|
||||
pub enum DatumMode {
|
||||
/// `val` is a pointer to the actual value (and thus has type *T).
|
||||
/// The argument indicates how to cancel cleanup of this datum if
|
||||
@ -153,7 +154,7 @@ impl DatumMode {
|
||||
}
|
||||
|
||||
/// See `Datum cleanup styles` section at the head of this module.
|
||||
#[deriving(Eq, IterBytes)]
|
||||
#[deriving(Clone, Eq, IterBytes)]
|
||||
pub enum DatumCleanup {
|
||||
RevokeClean,
|
||||
ZeroMem
|
||||
@ -396,8 +397,7 @@ impl Datum {
|
||||
add_clean_temp_mem(bcx, self.val, self.ty);
|
||||
}
|
||||
ByRef(ZeroMem) => {
|
||||
bcx.tcx().sess.bug(
|
||||
format!("Cannot add clean to a 'zero-mem' datum"));
|
||||
add_clean(bcx, self.val, self.ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,7 +413,6 @@ impl Datum {
|
||||
// Lvalues which potentially need to be dropped
|
||||
// must be passed by ref, so that we can zero them
|
||||
// out.
|
||||
assert!(self.mode.is_by_ref());
|
||||
zero_mem(bcx, self.val, self.ty);
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +133,7 @@ use middle::trans::adt;
|
||||
use middle::trans::base;
|
||||
use middle::trans::build;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::datum;
|
||||
use middle::trans::machine;
|
||||
use middle::trans::type_of;
|
||||
use middle::trans::type_::Type;
|
||||
@ -280,12 +281,11 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
|
||||
|
||||
pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
|
||||
let var_ident = ast_util::path_to_ident(path_ref);
|
||||
let var_type = node_id_type(bcx, node_id);
|
||||
|
||||
let llptr = {
|
||||
let datum = {
|
||||
let lllocals = bcx.fcx.lllocals.borrow();
|
||||
match lllocals.get().find_copy(&node_id) {
|
||||
Some(v) => v,
|
||||
Some(datum) => datum,
|
||||
None => {
|
||||
bcx.tcx().sess.span_bug(span,
|
||||
format!("No entry in lllocals table for {:?}",
|
||||
@ -298,9 +298,9 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
|
||||
|
||||
declare_local(bcx,
|
||||
var_ident,
|
||||
var_type,
|
||||
datum.ty,
|
||||
scope_metadata,
|
||||
DirectVariable { alloca: llptr },
|
||||
DirectVariable { alloca: datum.val },
|
||||
LocalVariable,
|
||||
span);
|
||||
})
|
||||
@ -382,33 +382,19 @@ pub fn create_captured_var_metadata(bcx: &Block,
|
||||
pub fn create_match_binding_metadata(bcx: &Block,
|
||||
variable_ident: ast::Ident,
|
||||
node_id: ast::NodeId,
|
||||
variable_type: ty::t,
|
||||
span: Span) {
|
||||
span: Span,
|
||||
datum: datum::Datum) {
|
||||
if fn_should_be_ignored(bcx.fcx) {
|
||||
return;
|
||||
}
|
||||
|
||||
let llptr = {
|
||||
let lllocals = bcx.fcx.lllocals.borrow();
|
||||
match lllocals.get().find_copy(&node_id) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
bcx.tcx()
|
||||
.sess
|
||||
.span_bug(span,
|
||||
format!("No entry in lllocals table for {:?}",
|
||||
node_id));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
|
||||
|
||||
declare_local(bcx,
|
||||
variable_ident,
|
||||
variable_type,
|
||||
datum.ty,
|
||||
scope_metadata,
|
||||
DirectVariable { alloca: llptr },
|
||||
DirectVariable { alloca: datum.val },
|
||||
LocalVariable,
|
||||
span);
|
||||
}
|
||||
@ -506,7 +492,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
|
||||
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
|
||||
|
||||
pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
|
||||
let llptr = {
|
||||
let llarg = {
|
||||
let llargs = bcx.fcx.llargs.borrow();
|
||||
match llargs.get().find_copy(&node_id) {
|
||||
Some(v) => v,
|
||||
@ -518,12 +504,11 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
|
||||
}
|
||||
};
|
||||
|
||||
if unsafe { llvm::LLVMIsAAllocaInst(llptr) } == ptr::null() {
|
||||
if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
|
||||
cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \
|
||||
Referenced variable location is not an alloca!");
|
||||
}
|
||||
|
||||
let argument_type = node_id_type(bcx, node_id);
|
||||
let argument_ident = ast_util::path_to_ident(path_ref);
|
||||
|
||||
let argument_index = {
|
||||
@ -535,9 +520,9 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
|
||||
|
||||
declare_local(bcx,
|
||||
argument_ident,
|
||||
argument_type,
|
||||
llarg.ty,
|
||||
scope_metadata,
|
||||
DirectVariable { alloca: llptr },
|
||||
DirectVariable { alloca: llarg.val },
|
||||
ArgumentVariable(argument_index),
|
||||
span);
|
||||
})
|
||||
@ -2185,9 +2170,6 @@ fn type_metadata(cx: &CrateContext,
|
||||
},
|
||||
ty::ty_tup(ref elements) => {
|
||||
prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
|
||||
},
|
||||
ty::ty_opaque_box => {
|
||||
create_pointer_to_box_metadata(cx, t, ty::mk_nil())
|
||||
}
|
||||
_ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
|
||||
};
|
||||
|
@ -1172,7 +1172,7 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
|
||||
take_local(bcx, lllocals.get(), nid)
|
||||
}
|
||||
ast::DefSelf(nid, _) => {
|
||||
let self_info: ValSelfData = match bcx.fcx.llself.get() {
|
||||
let self_info = match bcx.fcx.llself.get() {
|
||||
Some(self_info) => self_info,
|
||||
None => {
|
||||
bcx.sess().bug(format!(
|
||||
@ -1181,14 +1181,10 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
|
||||
}
|
||||
};
|
||||
|
||||
debug!("def_self() reference, self_info.t={}",
|
||||
self_info.t.repr(bcx.tcx()));
|
||||
debug!("def_self() reference, self_info.ty={}",
|
||||
self_info.ty.repr(bcx.tcx()));
|
||||
|
||||
Datum {
|
||||
val: self_info.v,
|
||||
ty: self_info.t,
|
||||
mode: ByRef(ZeroMem)
|
||||
}
|
||||
self_info
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().unimpl(format!(
|
||||
@ -1197,24 +1193,18 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
|
||||
};
|
||||
|
||||
fn take_local(bcx: &Block,
|
||||
table: &HashMap<ast::NodeId, ValueRef>,
|
||||
nid: ast::NodeId)
|
||||
-> Datum {
|
||||
let v = match table.find(&nid) {
|
||||
table: &HashMap<ast::NodeId, Datum>,
|
||||
nid: ast::NodeId) -> Datum {
|
||||
let datum = match table.find(&nid) {
|
||||
Some(&v) => v,
|
||||
None => {
|
||||
bcx.sess().bug(format!(
|
||||
"trans_local_var: no llval for local/arg {:?} found", nid));
|
||||
"trans_local_var: no datum for local/arg {:?} found", nid));
|
||||
}
|
||||
};
|
||||
let ty = node_id_type(bcx, nid);
|
||||
debug!("take_local(nid={:?}, v={}, ty={})",
|
||||
nid, bcx.val_to_str(v), bcx.ty_to_str(ty));
|
||||
Datum {
|
||||
val: v,
|
||||
ty: ty,
|
||||
mode: ByRef(ZeroMem)
|
||||
}
|
||||
nid, bcx.val_to_str(datum.val), bcx.ty_to_str(datum.ty));
|
||||
datum
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,16 +489,17 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
|
||||
id,
|
||||
t.repr(tcx));
|
||||
|
||||
let llfndecl = base::decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, ps);
|
||||
let llfndecl = base::decl_internal_rust_fn(ccx, None, f.sig.inputs, f.sig.output, ps);
|
||||
base::set_llvm_fn_attrs(attrs, llfndecl);
|
||||
base::trans_fn(ccx,
|
||||
(*path).clone(),
|
||||
decl,
|
||||
body,
|
||||
llfndecl,
|
||||
base::no_self,
|
||||
None,
|
||||
None,
|
||||
id,
|
||||
None,
|
||||
[]);
|
||||
return llfndecl;
|
||||
}
|
||||
|
@ -93,84 +93,67 @@ pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext,
|
||||
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti);
|
||||
}
|
||||
|
||||
pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
|
||||
if (field == abi::tydesc_field_take_glue ||
|
||||
field == abi::tydesc_field_drop_glue) &&
|
||||
! ty::type_needs_drop(tcx, t) {
|
||||
return ty::mk_u32();
|
||||
fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
|
||||
if (field == abi::tydesc_field_take_glue || field == abi::tydesc_field_drop_glue)
|
||||
&& !ty::type_needs_drop(tcx, t) {
|
||||
return ty::mk_nil();
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_unboxed_vec(..) |
|
||||
ty::ty_uniq(..) |
|
||||
ty::ty_str(ty::vstore_uniq) |
|
||||
ty::ty_vec(_, ty::vstore_uniq) => { return ty::mk_u32(); }
|
||||
_ => ()
|
||||
ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) |
|
||||
ty::ty_unboxed_vec(..) | ty::ty_uniq(..) => return ty::mk_nil(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_take_glue &&
|
||||
ty::type_is_boxed(t) {
|
||||
return ty::mk_imm_box(tcx, ty::mk_u32());
|
||||
if field == abi::tydesc_field_take_glue && ty::type_is_boxed(t) {
|
||||
return ty::mk_imm_box(tcx, ty::mk_nil());
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(typ)
|
||||
if ! ty::type_needs_drop(tcx, typ) =>
|
||||
return ty::mk_imm_box(tcx, ty::mk_u32()),
|
||||
ty::ty_box(typ)
|
||||
if !ty::type_needs_drop(tcx, typ) =>
|
||||
return ty::mk_imm_box(tcx, ty::mk_nil()),
|
||||
|
||||
ty::ty_vec(mt, ty::vstore_box)
|
||||
if ! ty::type_needs_drop(tcx, mt.ty) =>
|
||||
return ty::mk_imm_box(tcx, ty::mk_u32()),
|
||||
ty::ty_vec(mt, ty::vstore_box)
|
||||
if !ty::type_needs_drop(tcx, mt.ty) =>
|
||||
return ty::mk_imm_box(tcx, ty::mk_nil()),
|
||||
|
||||
ty::ty_uniq(mt) |
|
||||
ty::ty_vec(mt, ty::vstore_uniq)
|
||||
if ! ty::type_needs_drop(tcx, mt.ty) =>
|
||||
return ty::mk_imm_uniq(tcx, ty::mk_u32()),
|
||||
ty::ty_uniq(mt) | ty::ty_vec(mt, ty::vstore_uniq)
|
||||
if !ty::type_needs_drop(tcx, mt.ty) =>
|
||||
return ty::mk_imm_uniq(tcx, ty::mk_nil()),
|
||||
|
||||
_ => ()
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
t
|
||||
}
|
||||
|
||||
pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext,
|
||||
field: uint,
|
||||
ti: &tydesc_info)
|
||||
-> bool {
|
||||
let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue");
|
||||
fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) {
|
||||
let _icx = push_ctxt("lazily_emit_tydesc_glue");
|
||||
|
||||
let simpl = simplified_glue_type(ccx.tcx, field, ti.ty);
|
||||
if simpl != ti.ty {
|
||||
let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue");
|
||||
let simpl_ti = get_tydesc(ccx, simpl);
|
||||
lazily_emit_tydesc_glue(ccx, field, simpl_ti);
|
||||
{
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
ti.take_glue.set(simpl_ti.take_glue.get());
|
||||
} else if field == abi::tydesc_field_drop_glue {
|
||||
ti.drop_glue.set(simpl_ti.drop_glue.get());
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
ti.visit_glue.set(simpl_ti.visit_glue.get());
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
ti.take_glue.set(simpl_ti.take_glue.get());
|
||||
} else if field == abi::tydesc_field_drop_glue {
|
||||
ti.drop_glue.set(simpl_ti.drop_glue.get());
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
ti.visit_glue.set(simpl_ti.visit_glue.get());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
pub fn lazily_emit_tydesc_glue(ccx: @CrateContext,
|
||||
field: uint,
|
||||
ti: @tydesc_info) {
|
||||
let _icx = push_ctxt("lazily_emit_tydesc_glue");
|
||||
let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
|
||||
|
||||
if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
|
||||
return;
|
||||
}
|
||||
|
||||
let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
|
||||
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
match ti.take_glue.get() {
|
||||
Some(_) => (),
|
||||
@ -271,16 +254,12 @@ pub fn call_tydesc_glue_full(bcx: &Block,
|
||||
}
|
||||
|
||||
// See [Note-arg-mode]
|
||||
pub fn call_tydesc_glue<'a>(
|
||||
cx: &'a Block<'a>,
|
||||
v: ValueRef,
|
||||
t: ty::t,
|
||||
field: uint)
|
||||
-> &'a Block<'a> {
|
||||
fn call_tydesc_glue<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t, field: uint)
|
||||
-> &'a Block<'a> {
|
||||
let _icx = push_ctxt("call_tydesc_glue");
|
||||
let ti = get_tydesc(cx.ccx(), t);
|
||||
call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti));
|
||||
return cx;
|
||||
cx
|
||||
}
|
||||
|
||||
fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
@ -308,7 +287,6 @@ pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("make_free_glue");
|
||||
match ty::get(t).sty {
|
||||
ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_free_glue"),
|
||||
ty::ty_box(body_ty) => {
|
||||
let v = Load(bcx, v);
|
||||
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
|
||||
@ -407,7 +385,6 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
|
||||
let _icx = push_ctxt("make_drop_glue");
|
||||
let ccx = bcx.ccx();
|
||||
match ty::get(t).sty {
|
||||
ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_drop_glue"),
|
||||
ty::ty_box(_) |
|
||||
ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
|
||||
decr_refcnt_maybe_free(bcx, v0, Some(t))
|
||||
@ -509,7 +486,6 @@ fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a
|
||||
let _icx = push_ctxt("make_take_glue");
|
||||
// NB: v is a *pointer* to type t here, not a direct value.
|
||||
match ty::get(t).sty {
|
||||
ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_take_glue"),
|
||||
ty::ty_box(_) |
|
||||
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
|
||||
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
|
||||
@ -610,11 +586,8 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
|
||||
return inf;
|
||||
}
|
||||
|
||||
pub type glue_helper<'a> =
|
||||
'a |&'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>;
|
||||
|
||||
pub fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
|
||||
name: &str) -> ValueRef {
|
||||
fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
|
||||
name: &str) -> ValueRef {
|
||||
let _icx = push_ctxt("declare_generic_glue");
|
||||
let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed();
|
||||
debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
|
||||
@ -623,12 +596,14 @@ pub fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
|
||||
return llfn;
|
||||
}
|
||||
|
||||
pub fn make_generic_glue_inner(ccx: @CrateContext,
|
||||
t: ty::t,
|
||||
llfn: ValueRef,
|
||||
helper: glue_helper)
|
||||
-> ValueRef {
|
||||
let _icx = push_ctxt("make_generic_glue_inner");
|
||||
pub type glue_helper<'a> =
|
||||
'a |&'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>;
|
||||
|
||||
fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef,
|
||||
helper: glue_helper, name: &str) -> ValueRef {
|
||||
let _icx = push_ctxt("make_generic_glue");
|
||||
let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx, t));
|
||||
let _s = StatRecorder::new(ccx, glue_name);
|
||||
|
||||
let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None);
|
||||
init_function(&fcx, false, ty::mk_nil(), None, None);
|
||||
@ -644,25 +619,12 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
|
||||
// type, so we don't need to explicitly cast the function parameter.
|
||||
|
||||
let bcx = fcx.entry_bcx.get().unwrap();
|
||||
let rawptr0_arg = fcx.arg_pos(0u);
|
||||
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
|
||||
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, fcx.arg_pos(0) as c_uint) };
|
||||
let bcx = helper(bcx, llrawptr0, t);
|
||||
|
||||
finish_fn(&fcx, bcx);
|
||||
|
||||
return llfn;
|
||||
}
|
||||
|
||||
pub fn make_generic_glue(ccx: @CrateContext,
|
||||
t: ty::t,
|
||||
llfn: ValueRef,
|
||||
helper: glue_helper,
|
||||
name: &str)
|
||||
-> ValueRef {
|
||||
let _icx = push_ctxt("make_generic_glue");
|
||||
let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx, t));
|
||||
let _s = StatRecorder::new(ccx, glue_name);
|
||||
make_generic_glue_inner(ccx, t, llfn, helper)
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn emit_tydescs(ccx: &CrateContext) {
|
||||
|
@ -11,8 +11,7 @@
|
||||
use lib::llvm::{AvailableExternallyLinkage, SetLinkage};
|
||||
use metadata::csearch;
|
||||
use middle::astencode;
|
||||
use middle::trans::base::{push_ctxt, impl_self, no_self};
|
||||
use middle::trans::base::{trans_item, get_item_val, trans_fn};
|
||||
use middle::trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
|
||||
use middle::trans::common::*;
|
||||
use middle::ty;
|
||||
use util::ppaux::ty_to_str;
|
||||
@ -162,16 +161,13 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
|
||||
let path = vec::append_one(
|
||||
ty::item_path(ccx.tcx, impl_did), PathName(mth.ident));
|
||||
let self_kind = match mth.explicit_self.node {
|
||||
ast::SelfStatic => no_self,
|
||||
ast::SelfStatic => None,
|
||||
_ => {
|
||||
let self_ty = ty::node_id_to_type(ccx.tcx,
|
||||
mth.self_id);
|
||||
debug!("calling inline trans_fn with self_ty {}",
|
||||
ty_to_str(ccx.tcx, self_ty));
|
||||
match mth.explicit_self.node {
|
||||
ast::SelfValue(_) => impl_self(self_ty, ty::ByRef),
|
||||
_ => impl_self(self_ty, ty::ByCopy),
|
||||
}
|
||||
Some(self_ty)
|
||||
}
|
||||
};
|
||||
trans_fn(ccx,
|
||||
@ -182,6 +178,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
|
||||
self_kind,
|
||||
None,
|
||||
mth.id,
|
||||
Some(&*mth),
|
||||
[]);
|
||||
}
|
||||
local_def(mth.id)
|
||||
|
@ -430,7 +430,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
|
||||
// XXX This is a hack to grab the address of this particular
|
||||
// native function. There should be a general in-language
|
||||
// way to do this
|
||||
let llfty = type_of_rust_fn(bcx.ccx(), [], ty::mk_nil());
|
||||
let llfty = type_of_rust_fn(bcx.ccx(), None, [], ty::mk_nil());
|
||||
let morestack_addr = decl_cdecl_fn(
|
||||
bcx.ccx().llmod, "__morestack", llfty);
|
||||
let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
|
||||
|
@ -76,7 +76,7 @@ pub fn trans_impl(ccx: @CrateContext,
|
||||
path,
|
||||
*method,
|
||||
None,
|
||||
llfn);
|
||||
|_| llfn);
|
||||
} else {
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
visit::walk_method_helper(&mut v, *method, ());
|
||||
@ -91,7 +91,7 @@ pub fn trans_impl(ccx: @CrateContext,
|
||||
/// * `method`: the AST node for the method
|
||||
/// * `param_substs`: if this is a generic method, the current values for
|
||||
/// type parameters and so forth, else none
|
||||
/// * `llfn`: the LLVM ValueRef for the method
|
||||
/// * `llfn`: a closure returning the LLVM ValueRef for the method
|
||||
/// * `impl_id`: the node ID of the impl this method is inside
|
||||
///
|
||||
/// XXX(pcwalton) Can we take `path` by reference?
|
||||
@ -99,12 +99,10 @@ pub fn trans_method(ccx: @CrateContext,
|
||||
path: Path,
|
||||
method: &ast::Method,
|
||||
param_substs: Option<@param_substs>,
|
||||
llfn: ValueRef) {
|
||||
llfn_with_self: |Option<ty::t>| -> ValueRef) -> ValueRef {
|
||||
// figure out how self is being passed
|
||||
let self_arg = match method.explicit_self.node {
|
||||
ast::SelfStatic => {
|
||||
no_self
|
||||
}
|
||||
let self_ty = match method.explicit_self.node {
|
||||
ast::SelfStatic => None,
|
||||
_ => {
|
||||
// determine the (monomorphized) type that `self` maps to for
|
||||
// this method
|
||||
@ -115,43 +113,25 @@ pub fn trans_method(ccx: @CrateContext,
|
||||
ty::subst_tps(ccx.tcx, *tys, *self_sub, self_ty)
|
||||
}
|
||||
};
|
||||
debug!("calling trans_fn with self_ty {}",
|
||||
self_ty.repr(ccx.tcx));
|
||||
match method.explicit_self.node {
|
||||
ast::SelfValue(_) => impl_self(self_ty, ty::ByRef),
|
||||
_ => impl_self(self_ty, ty::ByCopy),
|
||||
}
|
||||
debug!("calling trans_fn with self_ty {}", self_ty.repr(ccx.tcx));
|
||||
Some(self_ty)
|
||||
}
|
||||
};
|
||||
|
||||
let llfn = llfn_with_self(self_ty);
|
||||
|
||||
// generate the actual code
|
||||
trans_fn(ccx,
|
||||
path,
|
||||
method.decl,
|
||||
method.body,
|
||||
llfn,
|
||||
self_arg,
|
||||
self_ty,
|
||||
param_substs,
|
||||
method.id,
|
||||
Some(method),
|
||||
[]);
|
||||
}
|
||||
|
||||
pub fn trans_self_arg<'a>(
|
||||
bcx: &'a Block<'a>,
|
||||
base: &ast::Expr,
|
||||
temp_cleanups: &mut ~[ValueRef],
|
||||
mentry: typeck::method_map_entry)
|
||||
-> Result<'a> {
|
||||
let _icx = push_ctxt("impl::trans_self_arg");
|
||||
|
||||
// self is passed as an opaque box in the environment slot
|
||||
let self_ty = ty::mk_opaque_box(bcx.tcx());
|
||||
trans_arg_expr(bcx,
|
||||
self_ty,
|
||||
mentry.self_mode,
|
||||
base,
|
||||
temp_cleanups,
|
||||
DontAutorefArg)
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn trans_method_callee<'a>(
|
||||
@ -169,16 +149,23 @@ pub fn trans_method_callee<'a>(
|
||||
|
||||
match mentry.origin {
|
||||
typeck::method_static(did) => {
|
||||
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
|
||||
let self_ty = monomorphize_type(bcx, mentry.self_ty);
|
||||
let mut temp_cleanups = ~[];
|
||||
let Result {bcx, val} = trans_self_arg(bcx, this, &mut temp_cleanups, mentry);
|
||||
let Result {bcx, val} = trans_arg_expr(bcx, self_ty, this,
|
||||
&mut temp_cleanups,
|
||||
DontAutorefArg);
|
||||
// HACK should not need the pointer cast, eventually trans_fn_ref
|
||||
// should return a function type with the right type for self.
|
||||
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
|
||||
let fn_ty = node_id_type(bcx, callee_id);
|
||||
let llfn_ty = type_of_fn_from_ty(bcx.ccx(), Some(self_ty), fn_ty).ptr_to();
|
||||
let llfn_val = PointerCast(bcx, callee_fn.llfn, llfn_ty);
|
||||
Callee {
|
||||
bcx: bcx,
|
||||
data: Method(MethodData {
|
||||
llfn: callee_fn.llfn,
|
||||
llfn: llfn_val,
|
||||
llself: val,
|
||||
temp_cleanup: temp_cleanups.head_opt().map(|v| *v),
|
||||
self_mode: mentry.self_mode,
|
||||
temp_cleanup: temp_cleanups.head_opt().map(|v| *v)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -194,8 +181,7 @@ pub fn trans_method_callee<'a>(
|
||||
bcx.tcx(),
|
||||
trait_id);
|
||||
|
||||
let vtbl = find_vtable(bcx.tcx(), substs,
|
||||
p, b);
|
||||
let vtbl = find_vtable(bcx.tcx(), substs, p, b);
|
||||
trans_monomorphized_callee(bcx, callee_id, this, mentry,
|
||||
trait_id, off, vtbl)
|
||||
}
|
||||
@ -276,7 +262,7 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||
assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
|
||||
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
|
||||
let mth_id = method_with_name(ccx, impl_did, mname.name);
|
||||
let (callee_substs, callee_origins) =
|
||||
combine_impl_and_methods_tps(
|
||||
bcx, mth_id, callee_id,
|
||||
@ -290,7 +276,7 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
Some(callee_origins));
|
||||
|
||||
let callee_ty = node_id_type(bcx, callee_id);
|
||||
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
|
||||
let llty = type_of_fn_from_ty(ccx, None, callee_ty).ptr_to();
|
||||
FnData {llfn: PointerCast(bcx, lval, llty)}
|
||||
}
|
||||
_ => {
|
||||
@ -340,9 +326,11 @@ pub fn trans_monomorphized_callee<'a>(
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
|
||||
|
||||
// obtain the `self` value:
|
||||
let self_ty = monomorphize_type(bcx, mentry.self_ty);
|
||||
let mut temp_cleanups = ~[];
|
||||
let Result {bcx, val: llself_val} =
|
||||
trans_self_arg(bcx, base, &mut temp_cleanups, mentry);
|
||||
let Result {bcx, val} = trans_arg_expr(bcx, self_ty, base,
|
||||
&mut temp_cleanups,
|
||||
DontAutorefArg);
|
||||
|
||||
// create a concatenated set of substitutions which includes
|
||||
// those from the impl and those from the method:
|
||||
@ -359,8 +347,9 @@ pub fn trans_monomorphized_callee<'a>(
|
||||
Some(callee_origins));
|
||||
|
||||
// create a llvalue that represents the fn ptr
|
||||
// HACK should not need the pointer cast (add self in trans_fn_ref_with_vtables).
|
||||
let fn_ty = node_id_type(bcx, callee_id);
|
||||
let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).ptr_to();
|
||||
let llfn_ty = type_of_fn_from_ty(ccx, Some(self_ty), fn_ty).ptr_to();
|
||||
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
|
||||
|
||||
// combine the self environment with the rest
|
||||
@ -368,9 +357,8 @@ pub fn trans_monomorphized_callee<'a>(
|
||||
bcx: bcx,
|
||||
data: Method(MethodData {
|
||||
llfn: llfn_val,
|
||||
llself: llself_val,
|
||||
temp_cleanup: temp_cleanups.head_opt().map(|v| *v),
|
||||
self_mode: mentry.self_mode,
|
||||
llself: val,
|
||||
temp_cleanup: temp_cleanups.head_opt().map(|v| *v)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -496,7 +484,7 @@ pub fn trans_trait_callee_from_llval<'a>(
|
||||
|
||||
// Load the function from the vtable and cast it to the expected type.
|
||||
debug!("(translating trait callee) loading method");
|
||||
let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty);
|
||||
let llcallee_ty = type_of_fn_from_ty(ccx, None, callee_ty);
|
||||
let llvtable = Load(bcx,
|
||||
PointerCast(bcx,
|
||||
GEPi(bcx, llpair,
|
||||
@ -510,12 +498,7 @@ pub fn trans_trait_callee_from_llval<'a>(
|
||||
data: Method(MethodData {
|
||||
llfn: mptr,
|
||||
llself: llself,
|
||||
temp_cleanup: temp_cleanup,
|
||||
|
||||
// We know that the func declaration is &self, ~self,
|
||||
// or @self, and such functions are always by-copy
|
||||
// (right now, at least).
|
||||
self_mode: ty::ByCopy,
|
||||
temp_cleanup: temp_cleanup
|
||||
})
|
||||
};
|
||||
}
|
||||
|
@ -13,9 +13,8 @@ use back::link::mangle_exported_name;
|
||||
use driver::session;
|
||||
use lib::llvm::ValueRef;
|
||||
use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint};
|
||||
use middle::trans::base::{trans_enum_variant,push_ctxt};
|
||||
use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val};
|
||||
use middle::trans::base::{trans_fn, decl_internal_rust_fn};
|
||||
use middle::trans::base::{get_item_val, no_self};
|
||||
use middle::trans::base;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::meth;
|
||||
@ -211,8 +210,8 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||
let s = mangle_exported_name(ccx, pt.clone(), mono_ty);
|
||||
debug!("monomorphize_fn mangled to {}", s);
|
||||
|
||||
let mk_lldecl = || {
|
||||
let lldecl = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
|
||||
let mk_lldecl = |self_ty| {
|
||||
let lldecl = decl_internal_rust_fn(ccx, self_ty, f.sig.inputs, f.sig.output, s);
|
||||
let mut monomorphized = ccx.monomorphized.borrow_mut();
|
||||
monomorphized.get().insert(hash_id, lldecl);
|
||||
lldecl
|
||||
@ -223,16 +222,17 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||
node: ast::ItemFn(decl, _, _, _, body),
|
||||
..
|
||||
}, _) => {
|
||||
let d = mk_lldecl();
|
||||
let d = mk_lldecl(None);
|
||||
set_llvm_fn_attrs(i.attrs, d);
|
||||
trans_fn(ccx,
|
||||
pt,
|
||||
decl,
|
||||
body,
|
||||
d,
|
||||
no_self,
|
||||
None,
|
||||
Some(psubsts),
|
||||
fn_id.node,
|
||||
None,
|
||||
[]);
|
||||
d
|
||||
}
|
||||
@ -240,7 +240,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||
ccx.tcx.sess.bug("Can't monomorphize this kind of item")
|
||||
}
|
||||
ast_map::NodeForeignItem(i, _, _, _) => {
|
||||
let d = mk_lldecl();
|
||||
let d = mk_lldecl(None);
|
||||
intrinsic::trans_intrinsic(ccx, d, i, pt, psubsts, i.attrs,
|
||||
ref_id);
|
||||
d
|
||||
@ -248,7 +248,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||
ast_map::NodeVariant(v, enum_item, _) => {
|
||||
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
|
||||
let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
|
||||
let d = mk_lldecl();
|
||||
let d = mk_lldecl(None);
|
||||
set_inline_hint(d);
|
||||
match v.node.kind {
|
||||
ast::TupleVariantKind(ref args) => {
|
||||
@ -266,20 +266,21 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||
d
|
||||
}
|
||||
ast_map::NodeMethod(mth, _, _) => {
|
||||
// XXX: What should the self type be here?
|
||||
let d = mk_lldecl();
|
||||
set_llvm_fn_attrs(mth.attrs, d);
|
||||
meth::trans_method(ccx, pt, mth, Some(psubsts), d);
|
||||
d
|
||||
meth::trans_method(ccx, pt, mth, Some(psubsts), |self_ty| {
|
||||
let d = mk_lldecl(self_ty);
|
||||
set_llvm_fn_attrs(mth.attrs, d);
|
||||
d
|
||||
})
|
||||
}
|
||||
ast_map::NodeTraitMethod(@ast::Provided(mth), _, pt) => {
|
||||
let d = mk_lldecl();
|
||||
set_llvm_fn_attrs(mth.attrs, d);
|
||||
meth::trans_method(ccx, (*pt).clone(), mth, Some(psubsts), d);
|
||||
d
|
||||
meth::trans_method(ccx, (*pt).clone(), mth, Some(psubsts), |self_ty| {
|
||||
let d = mk_lldecl(self_ty);
|
||||
set_llvm_fn_attrs(mth.attrs, d);
|
||||
d
|
||||
})
|
||||
}
|
||||
ast_map::NodeStructCtor(struct_def, _, _) => {
|
||||
let d = mk_lldecl();
|
||||
let d = mk_lldecl(None);
|
||||
set_inline_hint(d);
|
||||
base::trans_tuple_struct(ccx,
|
||||
struct_def.fields,
|
||||
|
@ -295,7 +295,7 @@ impl<'a> Reflector<'a> {
|
||||
sub_path,
|
||||
"get_disr");
|
||||
|
||||
let llfdecl = decl_internal_rust_fn(ccx, [opaqueptrty], ty::mk_u64(), sym);
|
||||
let llfdecl = decl_internal_rust_fn(ccx, None, [opaqueptrty], ty::mk_u64(), sym);
|
||||
let fcx = new_fn_ctxt(ccx,
|
||||
~[],
|
||||
llfdecl,
|
||||
@ -362,7 +362,6 @@ impl<'a> Reflector<'a> {
|
||||
}
|
||||
ty::ty_self(..) => self.leaf("self"),
|
||||
ty::ty_type => self.leaf("type"),
|
||||
ty::ty_opaque_box => self.leaf("opaque_box"),
|
||||
ty::ty_opaque_closure_ptr(ck) => {
|
||||
let ckval = ast_sigil_constant(ck);
|
||||
let extra = ~[self.c_uint(ckval)];
|
||||
|
@ -44,6 +44,7 @@ pub fn type_of_explicit_args(ccx: &CrateContext,
|
||||
}
|
||||
|
||||
pub fn type_of_rust_fn(cx: &CrateContext,
|
||||
self_ty: Option<ty::t>,
|
||||
inputs: &[ty::t],
|
||||
output: ty::t) -> Type {
|
||||
let mut atys: ~[Type] = ~[];
|
||||
@ -57,7 +58,11 @@ pub fn type_of_rust_fn(cx: &CrateContext,
|
||||
}
|
||||
|
||||
// Arg 1: Environment
|
||||
atys.push(Type::opaque_box(cx).ptr_to());
|
||||
let env = match self_ty {
|
||||
Some(t) => type_of_explicit_arg(cx, t),
|
||||
None => Type::opaque_box(cx).ptr_to()
|
||||
};
|
||||
atys.push(env);
|
||||
|
||||
// ... then explicit args.
|
||||
atys.push_all(type_of_explicit_args(cx, inputs));
|
||||
@ -71,14 +76,14 @@ pub fn type_of_rust_fn(cx: &CrateContext,
|
||||
}
|
||||
|
||||
// Given a function type and a count of ty params, construct an llvm type
|
||||
pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type {
|
||||
pub fn type_of_fn_from_ty(cx: &CrateContext, self_ty: Option<ty::t>, fty: ty::t) -> Type {
|
||||
return match ty::get(fty).sty {
|
||||
ty::ty_closure(ref f) => {
|
||||
type_of_rust_fn(cx, f.sig.inputs, f.sig.output)
|
||||
type_of_rust_fn(cx, None, f.sig.inputs, f.sig.output)
|
||||
}
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
if f.abis.is_rust() || f.abis.is_intrinsic() {
|
||||
type_of_rust_fn(cx, f.sig.inputs, f.sig.output)
|
||||
type_of_rust_fn(cx, self_ty, f.sig.inputs, f.sig.output)
|
||||
} else {
|
||||
foreign::lltype_for_foreign_fn(cx, fty)
|
||||
}
|
||||
@ -122,7 +127,6 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
ty::ty_vec(_, ty::vstore_uniq) |
|
||||
ty::ty_vec(_, ty::vstore_box) |
|
||||
ty::ty_box(..) |
|
||||
ty::ty_opaque_box |
|
||||
ty::ty_uniq(..) |
|
||||
ty::ty_ptr(..) |
|
||||
ty::ty_rptr(..) |
|
||||
@ -240,7 +244,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
let ty = type_of(cx, typ);
|
||||
Type::smart_ptr(cx, &ty).ptr_to()
|
||||
}
|
||||
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
|
||||
ty::ty_uniq(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
if ty::type_contents(cx.tcx, mt.ty).owns_managed() {
|
||||
@ -285,10 +288,10 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
}
|
||||
|
||||
ty::ty_bare_fn(_) => {
|
||||
type_of_fn_from_ty(cx, t).ptr_to()
|
||||
type_of_fn_from_ty(cx, None, t).ptr_to()
|
||||
}
|
||||
ty::ty_closure(_) => {
|
||||
let ty = type_of_fn_from_ty(cx, t);
|
||||
let ty = type_of_fn_from_ty(cx, None, t);
|
||||
Type::func_pair(cx, &ty)
|
||||
}
|
||||
ty::ty_trait(_, _, store, _, _) => Type::opaque_trait(cx, store),
|
||||
|
@ -151,14 +151,6 @@ pub enum TraitStore {
|
||||
RegionTraitStore(Region), // &Trait
|
||||
}
|
||||
|
||||
// XXX: This should probably go away at some point. Maybe after destructors
|
||||
// do?
|
||||
#[deriving(Clone, Eq, Encodable, Decodable)]
|
||||
pub enum SelfMode {
|
||||
ByCopy,
|
||||
ByRef,
|
||||
}
|
||||
|
||||
pub struct field_ty {
|
||||
name: Name,
|
||||
id: DefId,
|
||||
@ -659,8 +651,7 @@ pub enum sty {
|
||||
|
||||
// "Fake" types, used for trans purposes
|
||||
ty_type, // type_desc*
|
||||
ty_opaque_box, // used by monomorphizer to represent any @ box
|
||||
ty_opaque_closure_ptr(Sigil), // ptr to env for ||, @fn, ~fn
|
||||
ty_opaque_closure_ptr(Sigil), // ptr to env for || and proc
|
||||
ty_unboxed_vec(mt),
|
||||
}
|
||||
|
||||
@ -1078,8 +1069,7 @@ pub fn mk_t(cx: ctxt, st: sty) -> t {
|
||||
flags |= get(mt.ty).flags;
|
||||
}
|
||||
&ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
|
||||
&ty_str(_) | &ty_type | &ty_opaque_closure_ptr(_) |
|
||||
&ty_opaque_box => (),
|
||||
&ty_str(_) | &ty_type | &ty_opaque_closure_ptr(_) => {}
|
||||
// You might think that we could just return ty_err for
|
||||
// any type containing ty_err as a component, and get
|
||||
// rid of the has_ty_err flag -- likewise for ty_bot (with
|
||||
@ -1354,8 +1344,6 @@ pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
|
||||
mk_t(cx, ty_opaque_closure_ptr(sigil))
|
||||
}
|
||||
|
||||
pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
|
||||
|
||||
pub fn walk_ty(ty: t, f: |t|) {
|
||||
maybe_walk_ty(ty, |t| { f(t); true });
|
||||
}
|
||||
@ -1366,12 +1354,9 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
|
||||
}
|
||||
match get(ty).sty {
|
||||
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_str(_) | ty_type | ty_opaque_box | ty_self(_) |
|
||||
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
|
||||
}
|
||||
ty_box(ref ty) => {
|
||||
maybe_walk_ty(*ty, f);
|
||||
}
|
||||
ty_str(_) | ty_type | ty_self(_) |
|
||||
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {}
|
||||
ty_box(ref ty) => maybe_walk_ty(*ty, f),
|
||||
ty_vec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
|
||||
ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
|
||||
maybe_walk_ty(tm.ty, f);
|
||||
@ -1592,8 +1577,7 @@ pub fn type_is_box(ty: t) -> bool {
|
||||
|
||||
pub fn type_is_boxed(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_box(_) | ty_opaque_box |
|
||||
ty_vec(_, vstore_box) | ty_str(vstore_box) => true,
|
||||
ty_box(_) | ty_vec(_, vstore_box) | ty_str(vstore_box) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
@ -1699,7 +1683,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
|
||||
maybe_walk_ty(ty, |ty| {
|
||||
let old_encountered_box = encountered_box;
|
||||
let result = match get(ty).sty {
|
||||
ty_box(_) | ty_opaque_box => {
|
||||
ty_box(_) => {
|
||||
encountered_box = true;
|
||||
true
|
||||
}
|
||||
@ -2145,8 +2129,6 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
||||
// times.
|
||||
TC::All
|
||||
}
|
||||
|
||||
ty_opaque_box => TC::Managed,
|
||||
ty_unboxed_vec(mt) => TC::InteriorUnsized | tc_mt(cx, mt, cache),
|
||||
ty_opaque_closure_ptr(sigil) => {
|
||||
match sigil {
|
||||
@ -2332,7 +2314,6 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
|
||||
ty_param(_) |
|
||||
ty_self(_) |
|
||||
ty_type |
|
||||
ty_opaque_box |
|
||||
ty_opaque_closure_ptr(_) |
|
||||
ty_vec(_, _) |
|
||||
ty_unboxed_vec(_) => {
|
||||
@ -2515,7 +2496,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
|
||||
ty_box(_) | ty_uniq(_) | ty_closure(_) |
|
||||
ty_str(vstore_uniq) | ty_str(vstore_box) |
|
||||
ty_vec(_, vstore_uniq) | ty_vec(_, vstore_box) |
|
||||
ty_trait(_, _, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
|
||||
ty_trait(_, _, _, _, _) | ty_rptr(_,_) => result = false,
|
||||
// Structural types
|
||||
ty_enum(did, ref substs) => {
|
||||
let variants = enum_variants(cx, did);
|
||||
@ -3345,7 +3326,7 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
|
||||
match get(t).sty {
|
||||
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
|
||||
ty_uint(_) | ty_float(_) | ty_str(_) |
|
||||
ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
|
||||
ty_type | ty_opaque_closure_ptr(_) => {
|
||||
::util::ppaux::ty_to_str(cx, t)
|
||||
}
|
||||
|
||||
@ -4890,13 +4871,12 @@ pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
|
||||
ty_infer(_) => unreachable!(),
|
||||
ty_err => hash.input([23]),
|
||||
ty_type => hash.input([24]),
|
||||
ty_opaque_box => hash.input([25]),
|
||||
ty_opaque_closure_ptr(s) => {
|
||||
hash.input([26]);
|
||||
hash.input([25]);
|
||||
iter(&mut hash, &s);
|
||||
}
|
||||
ty_unboxed_vec(m) => {
|
||||
hash.input([27]);
|
||||
hash.input([26]);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
|
||||
ty::ty_int(_) | ty::ty_uint(_) |
|
||||
ty::ty_float(_) | ty::ty_type |
|
||||
ty::ty_opaque_closure_ptr(_) |
|
||||
ty::ty_err | ty::ty_opaque_box | ty::ty_infer(_) |
|
||||
ty::ty_err | ty::ty_infer(_) |
|
||||
ty::ty_param(..) | ty::ty_self(_) => {
|
||||
(*sty).clone()
|
||||
}
|
||||
|
@ -791,7 +791,7 @@ impl<'a> LookupContext<'a> {
|
||||
ty_err => None,
|
||||
|
||||
ty_opaque_closure_ptr(_) | ty_unboxed_vec(_) |
|
||||
ty_opaque_box | ty_type | ty_infer(TyVar(_)) => {
|
||||
ty_type | ty_infer(TyVar(_)) => {
|
||||
self.bug(format!("Unexpected type: {}",
|
||||
self.ty_to_str(self_ty)));
|
||||
}
|
||||
@ -1020,8 +1020,6 @@ impl<'a> LookupContext<'a> {
|
||||
});
|
||||
debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
|
||||
|
||||
let self_mode = get_mode_from_explicit_self(candidate.method_ty.explicit_self);
|
||||
|
||||
// before we only checked whether self_ty could be a subtype
|
||||
// of rcvr_ty; now we actually make it so (this may cause
|
||||
// variables to unify etc). Since we checked beforehand, and
|
||||
@ -1041,7 +1039,6 @@ impl<'a> LookupContext<'a> {
|
||||
self.fcx.write_substs(self.callee_id, all_substs);
|
||||
method_map_entry {
|
||||
self_ty: transformed_self_ty,
|
||||
self_mode: self_mode,
|
||||
explicit_self: candidate.method_ty.explicit_self,
|
||||
origin: candidate.origin,
|
||||
}
|
||||
@ -1375,13 +1372,6 @@ impl<'a> LookupContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mode_from_explicit_self(explicit_self: ast::ExplicitSelf_) -> SelfMode {
|
||||
match explicit_self {
|
||||
SelfValue(_) => ty::ByRef,
|
||||
_ => ty::ByCopy,
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for RcvrMatchCondition {
|
||||
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
||||
match *self {
|
||||
|
@ -21,7 +21,7 @@ use middle::ty::get;
|
||||
use middle::ty::{ImplContainer, lookup_item_type, subst};
|
||||
use middle::ty::{substs, t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
|
||||
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
|
||||
use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
|
||||
use middle::ty::{ty_param, ty_param_bounds_and_ty, ty_ptr};
|
||||
use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
|
||||
use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure};
|
||||
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec};
|
||||
@ -83,7 +83,7 @@ pub fn get_base_type(inference_context: @InferCtxt,
|
||||
|
||||
ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
|
||||
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
|
||||
ty_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_box |
|
||||
ty_infer(..) | ty_param(..) | ty_self(..) | ty_type |
|
||||
ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) |
|
||||
ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
|
||||
debug!("(getting base type) no base type; found {:?}",
|
||||
|
@ -148,9 +148,6 @@ pub struct method_map_entry {
|
||||
// (FIXME #3446)
|
||||
self_ty: ty::t,
|
||||
|
||||
// the mode of `self`
|
||||
self_mode: ty::SelfMode,
|
||||
|
||||
// the type of explicit self on the method
|
||||
explicit_self: ast::ExplicitSelf_,
|
||||
|
||||
|
@ -693,8 +693,7 @@ impl<'a> ConstraintContext<'a> {
|
||||
}
|
||||
|
||||
ty::ty_infer(..) | ty::ty_err | ty::ty_type |
|
||||
ty::ty_opaque_box | ty::ty_opaque_closure_ptr(..) |
|
||||
ty::ty_unboxed_vec(..) => {
|
||||
ty::ty_opaque_closure_ptr(..) | ty::ty_unboxed_vec(..) => {
|
||||
self.tcx().sess.bug(
|
||||
format!("Unexpected type encountered in \
|
||||
variance inference: {}",
|
||||
|
@ -18,7 +18,7 @@ use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
|
||||
ReEmpty};
|
||||
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
|
||||
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
|
||||
use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
|
||||
use middle::ty::{ty_nil, ty_opaque_closure_ptr, ty_param};
|
||||
use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
|
||||
use middle::ty::{ty_trait, ty_int};
|
||||
use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
|
||||
@ -505,7 +505,6 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
vstore_ty_to_str(cx, mt, vs)
|
||||
}
|
||||
ty_str(vs) => format!("{}{}", vstore_to_str(cx, vs), "str"),
|
||||
ty_opaque_box => ~"@?",
|
||||
ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
|
||||
ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
|
||||
ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
|
||||
|
30
src/test/run-pass/self-in-mut-slot-immediate-value.rs
Normal file
30
src/test/run-pass/self-in-mut-slot-immediate-value.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Assert that `mut self` on an immediate value doesn't
|
||||
// allow mutating the original - issue #10615.
|
||||
|
||||
struct Value {
|
||||
n: int
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn squared(mut self) -> Value {
|
||||
self.n *= self.n;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x = Value { n: 3 };
|
||||
let y = x.squared();
|
||||
assert_eq!(x.n, 3);
|
||||
assert_eq!(y.n, 9);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user