auto merge of #7763 : dotdash/rust/empty_blocks, r=pcwalton
These commits remove a bunch of empty or otherwise unnecessary blocks, reducing the size of the pre-optimization IR and improving its readability. `librustc.ll` created with `--passes ""` shrinks by about 120k lines which equals about 5% of the total size.
This commit is contained in:
commit
8d0feb58e7
@ -1102,11 +1102,6 @@ pub fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: @str) {
|
||||
Call(bcx, ccx.upcalls.trace, args);
|
||||
}
|
||||
|
||||
pub fn build_return(bcx: block) {
|
||||
let _icx = push_ctxt("build_return");
|
||||
Br(bcx, bcx.fcx.llreturn);
|
||||
}
|
||||
|
||||
pub fn ignore_lhs(_bcx: block, local: &ast::local) -> bool {
|
||||
match local.node.pat.node {
|
||||
ast::pat_wild => true, _ => false
|
||||
@ -1364,6 +1359,42 @@ pub fn cleanup_and_leave(bcx: block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cleanup_block(bcx: block, upto: Option<BasicBlockRef>) -> block{
|
||||
let _icx = push_ctxt("cleanup_block");
|
||||
let mut cur = bcx;
|
||||
let mut bcx = bcx;
|
||||
loop {
|
||||
debug!("cleanup_block: %s", cur.to_str());
|
||||
|
||||
if bcx.sess().trace() {
|
||||
trans_trace(
|
||||
bcx, None,
|
||||
(fmt!("cleanup_block(%s)", cur.to_str())).to_managed());
|
||||
}
|
||||
|
||||
let mut cur_scope = cur.scope;
|
||||
loop {
|
||||
cur_scope = match cur_scope {
|
||||
Some (inf) => {
|
||||
bcx = trans_block_cleanups_(bcx, inf.cleanups.to_owned(), false);
|
||||
inf.parent
|
||||
}
|
||||
None => break
|
||||
}
|
||||
}
|
||||
|
||||
match upto {
|
||||
Some(bb) => { if cur.llbb == bb { break; } }
|
||||
_ => ()
|
||||
}
|
||||
cur = match cur.parent {
|
||||
Some(next) => next,
|
||||
None => { assert!(upto.is_none()); break; }
|
||||
};
|
||||
}
|
||||
bcx
|
||||
}
|
||||
|
||||
pub fn cleanup_and_Br(bcx: block, upto: block, target: BasicBlockRef) {
|
||||
let _icx = push_ctxt("cleanup_and_Br");
|
||||
cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
|
||||
@ -1526,7 +1557,7 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
|
||||
return llvm::LLVMGetUndef(ty.to_ref());
|
||||
}
|
||||
}
|
||||
let initcx = base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
|
||||
let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
|
||||
let p = Alloca(initcx, ty, name);
|
||||
if zero { memzero(initcx, p, ty); }
|
||||
p
|
||||
@ -1539,24 +1570,26 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
|
||||
return llvm::LLVMGetUndef(ty.to_ref());
|
||||
}
|
||||
}
|
||||
return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), ty, v);
|
||||
return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas()), ty, v);
|
||||
}
|
||||
|
||||
pub struct BasicBlocks {
|
||||
sa: BasicBlockRef,
|
||||
rt: BasicBlockRef
|
||||
}
|
||||
|
||||
// Creates the standard set of basic blocks for a function
|
||||
pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
|
||||
pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||
unsafe {
|
||||
let cx = task_llcx();
|
||||
BasicBlocks {
|
||||
sa: str::as_c_str("static_allocas",
|
||||
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)),
|
||||
rt: str::as_c_str("return",
|
||||
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
|
||||
}
|
||||
str::as_c_str("static_allocas",
|
||||
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||
unsafe {
|
||||
let cx = task_llcx();
|
||||
str::as_c_str("return",
|
||||
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1568,7 +1601,7 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
|
||||
llvm::LLVMGetParam(fcx.llfn, 0)
|
||||
} else {
|
||||
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
|
||||
alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype,
|
||||
alloca(raw_block(fcx, false, fcx.get_llstaticallocas()), lloutputtype,
|
||||
"__make_return_pointer")
|
||||
}
|
||||
}
|
||||
@ -1596,8 +1629,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
||||
id,
|
||||
param_substs.repr(ccx.tcx));
|
||||
|
||||
let llbbs = mk_standard_basic_blocks(llfndecl);
|
||||
|
||||
let substd_output_type = match param_substs {
|
||||
None => output_type,
|
||||
Some(substs) => {
|
||||
@ -1611,9 +1642,9 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
||||
llvm::LLVMGetUndef(Type::i8p().to_ref())
|
||||
},
|
||||
llretptr: None,
|
||||
llstaticallocas: llbbs.sa,
|
||||
llstaticallocas: None,
|
||||
llloadenv: None,
|
||||
llreturn: llbbs.rt,
|
||||
llreturn: None,
|
||||
llself: None,
|
||||
personality: None,
|
||||
loop_ret: None,
|
||||
@ -1757,16 +1788,24 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
||||
|
||||
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
|
||||
// and builds the return block.
|
||||
pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
||||
pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
|
||||
let _icx = push_ctxt("finish_fn");
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
build_return_block(fcx);
|
||||
|
||||
let ret_cx = match fcx.llreturn {
|
||||
Some(llreturn) => {
|
||||
if !last_bcx.terminated {
|
||||
Br(last_bcx, llreturn);
|
||||
}
|
||||
raw_block(fcx, false, llreturn)
|
||||
}
|
||||
None => last_bcx
|
||||
};
|
||||
build_return_block(fcx, ret_cx);
|
||||
}
|
||||
|
||||
// Builds the return block for a function.
|
||||
pub fn build_return_block(fcx: fn_ctxt) {
|
||||
let ret_cx = raw_block(fcx, false, fcx.llreturn);
|
||||
|
||||
pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
|
||||
// Return the value if this function immediate; otherwise, return void.
|
||||
if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
|
||||
Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
|
||||
@ -1777,14 +1816,24 @@ pub fn build_return_block(fcx: fn_ctxt) {
|
||||
|
||||
pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
||||
let _icx = push_ctxt("tie_up_header_blocks");
|
||||
match fcx.llloadenv {
|
||||
let llnext = match fcx.llloadenv {
|
||||
Some(ll) => {
|
||||
Br(raw_block(fcx, false, fcx.llstaticallocas), ll);
|
||||
unsafe {
|
||||
llvm::LLVMMoveBasicBlockBefore(ll, lltop);
|
||||
}
|
||||
Br(raw_block(fcx, false, ll), lltop);
|
||||
ll
|
||||
}
|
||||
None => {
|
||||
Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
|
||||
None => lltop
|
||||
};
|
||||
match fcx.llstaticallocas {
|
||||
Some(ll) => {
|
||||
unsafe {
|
||||
llvm::LLVMMoveBasicBlockBefore(ll, llnext);
|
||||
}
|
||||
Br(raw_block(fcx, false, ll), llnext);
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1854,16 +1903,21 @@ pub fn trans_closure(ccx: @mut CrateContext,
|
||||
}
|
||||
|
||||
finish(bcx);
|
||||
cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
|
||||
match fcx.llreturn {
|
||||
Some(llreturn) => cleanup_and_Br(bcx, bcx_top, llreturn),
|
||||
None => bcx = cleanup_block(bcx, Some(bcx_top.llbb))
|
||||
};
|
||||
|
||||
// Put return block after all other blocks.
|
||||
// This somewhat improves single-stepping experience in debugger.
|
||||
unsafe {
|
||||
llvm::LLVMMoveBasicBlockAfter(fcx.llreturn, bcx.llbb);
|
||||
for fcx.llreturn.iter().advance |&llreturn| {
|
||||
llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the mandatory first few basic blocks before lltop.
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
}
|
||||
|
||||
// trans_fn: creates an LLVM function corresponding to a source language
|
||||
@ -2046,8 +2100,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
let arg_ty = arg_tys[i];
|
||||
memcpy_ty(bcx, lldestptr, llarg, arg_ty);
|
||||
}
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
}
|
||||
|
||||
pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
|
||||
@ -2288,8 +2341,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
||||
let args = ~[llenvarg];
|
||||
Call(bcx, main_llfn, args);
|
||||
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
return llfdecl;
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ pub fn trans_call_inner(in_cx: block,
|
||||
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
|
||||
}
|
||||
}
|
||||
base::cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
||||
base::cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
|
||||
Unreachable(bcx);
|
||||
bcx
|
||||
}
|
||||
|
@ -178,13 +178,13 @@ pub struct fn_ctxt_ {
|
||||
// the function, due to LLVM's quirks.
|
||||
// A block for all the function's static allocas, so that LLVM
|
||||
// will coalesce them into a single alloca call.
|
||||
llstaticallocas: BasicBlockRef,
|
||||
llstaticallocas: Option<BasicBlockRef>,
|
||||
// A block containing code that copies incoming arguments to space
|
||||
// already allocated by code in one of the llallocas blocks.
|
||||
// (LLVM requires that arguments be copied to local allocas before
|
||||
// allowing most any operation to be performed on them.)
|
||||
llloadenv: Option<BasicBlockRef>,
|
||||
llreturn: BasicBlockRef,
|
||||
llreturn: Option<BasicBlockRef>,
|
||||
// The 'self' value currently in use in this function, if there
|
||||
// is one.
|
||||
//
|
||||
@ -251,6 +251,21 @@ impl fn_ctxt_ {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_llstaticallocas(&mut self) -> BasicBlockRef {
|
||||
if self.llstaticallocas.is_none() {
|
||||
self.llstaticallocas = Some(base::mk_staticallocas_basic_block(self.llfn));
|
||||
}
|
||||
|
||||
self.llstaticallocas.get()
|
||||
}
|
||||
|
||||
pub fn get_llreturn(&mut self) -> BasicBlockRef {
|
||||
if self.llreturn.is_none() {
|
||||
self.llreturn = Some(base::mk_return_basic_block(self.llfn));
|
||||
}
|
||||
|
||||
self.llreturn.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub type fn_ctxt = @mut fn_ctxt_;
|
||||
|
@ -67,13 +67,8 @@ pub fn trans_if(bcx: block,
|
||||
expr::trans_to_datum(bcx, cond).to_result();
|
||||
|
||||
let then_bcx_in = scope_block(bcx, thn.info(), "then");
|
||||
let else_bcx_in = scope_block(bcx, els.info(), "else");
|
||||
|
||||
let cond_val = bool_to_i1(bcx, cond_val);
|
||||
CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
|
||||
|
||||
debug!("then_bcx_in=%s, else_bcx_in=%s",
|
||||
then_bcx_in.to_str(), else_bcx_in.to_str());
|
||||
|
||||
let then_bcx_out = trans_block(then_bcx_in, thn, dest);
|
||||
let then_bcx_out = trans_block_cleanups(then_bcx_out,
|
||||
@ -83,9 +78,10 @@ pub fn trans_if(bcx: block,
|
||||
// because trans_expr will create another scope block
|
||||
// context for the block, but we've already got the
|
||||
// 'else' context
|
||||
let else_bcx_out = match els {
|
||||
let (else_bcx_in, next_bcx) = match els {
|
||||
Some(elexpr) => {
|
||||
match elexpr.node {
|
||||
let else_bcx_in = scope_block(bcx, els.info(), "else");
|
||||
let else_bcx_out = match elexpr.node {
|
||||
ast::expr_if(_, _, _) => {
|
||||
let elseif_blk = ast_util::block_from_expr(elexpr);
|
||||
trans_block(else_bcx_in, &elseif_blk, dest)
|
||||
@ -95,14 +91,25 @@ pub fn trans_if(bcx: block,
|
||||
}
|
||||
// would be nice to have a constraint on ifs
|
||||
_ => bcx.tcx().sess.bug("strange alternative in if")
|
||||
}
|
||||
}
|
||||
_ => else_bcx_in
|
||||
};
|
||||
let else_bcx_out = trans_block_cleanups(else_bcx_out,
|
||||
block_cleanups(else_bcx_in));
|
||||
return join_blocks(bcx, [then_bcx_out, else_bcx_out]);
|
||||
};
|
||||
let else_bcx_out = trans_block_cleanups(else_bcx_out,
|
||||
block_cleanups(else_bcx_in));
|
||||
|
||||
(else_bcx_in, join_blocks(bcx, [then_bcx_out, else_bcx_out]))
|
||||
}
|
||||
_ => {
|
||||
let next_bcx = sub_block(bcx, "next");
|
||||
Br(then_bcx_out, next_bcx.llbb);
|
||||
|
||||
(next_bcx, next_bcx)
|
||||
}
|
||||
};
|
||||
|
||||
debug!("then_bcx_in=%s, else_bcx_in=%s",
|
||||
then_bcx_in.to_str(), else_bcx_in.to_str());
|
||||
|
||||
CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
|
||||
next_bcx
|
||||
}
|
||||
|
||||
pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {
|
||||
@ -279,7 +286,7 @@ pub fn trans_break_cont(bcx: block,
|
||||
// This is a return from a loop body block
|
||||
None => {
|
||||
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
|
||||
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
||||
cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
|
||||
Unreachable(bcx);
|
||||
return bcx;
|
||||
}
|
||||
@ -328,7 +335,7 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
||||
cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
|
||||
Unreachable(bcx);
|
||||
return bcx;
|
||||
}
|
||||
|
@ -164,7 +164,10 @@ fn build_shim_fn_(ccx: @mut CrateContext,
|
||||
// follow the normal Rust calling conventions.
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
|
||||
let ret_cx = raw_block(fcx, false, fcx.llreturn);
|
||||
let ret_cx = match fcx.llreturn {
|
||||
Some(llreturn) => raw_block(fcx, false, llreturn),
|
||||
None => bcx
|
||||
};
|
||||
RetVoid(ret_cx);
|
||||
|
||||
return llshimfn;
|
||||
@ -194,7 +197,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||
// the C ABI.
|
||||
if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
|
||||
let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
|
||||
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
|
||||
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.get_llstaticallocas()),
|
||||
lloutputtype,
|
||||
""));
|
||||
}
|
||||
@ -217,7 +220,10 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
|
||||
// Then return according to the C ABI.
|
||||
let return_context = raw_block(fcx, false, fcx.llreturn);
|
||||
let return_context = match fcx.llreturn {
|
||||
Some(llreturn) => raw_block(fcx, false, llreturn),
|
||||
None => bcx
|
||||
};
|
||||
|
||||
let llfunctiontype = val_ty(llwrapfn);
|
||||
let llfunctiontype = llfunctiontype.element_type();
|
||||
@ -388,7 +394,6 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
tys.ret_def,
|
||||
llargbundle,
|
||||
llretval);
|
||||
build_return(bcx);
|
||||
}
|
||||
|
||||
let lname = link_name(ccx, foreign_item);
|
||||
@ -438,8 +443,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
|
||||
Store(bcx, retval, fcx.llretptr.get());
|
||||
}
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
}
|
||||
|
||||
// FIXME (#2535): this is very shaky and probably gets ABIs wrong all
|
||||
@ -467,8 +471,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
|
||||
Store(bcx, retval, fcx.llretptr.get());
|
||||
}
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
}
|
||||
|
||||
fn build_wrap_fn(ccx: @mut CrateContext,
|
||||
@ -534,7 +537,6 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]);
|
||||
Store(bcx, Load(bcx, llretptr), retptr);
|
||||
}
|
||||
build_return(bcx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -629,8 +631,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
}
|
||||
}
|
||||
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1124,8 +1125,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
ccx.sess.span_bug(item.span, "unknown intrinsic");
|
||||
}
|
||||
}
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1257,8 +1257,6 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
// NB: The return pointer in the Rust ABI function is wired
|
||||
// directly into the return slot in the shim struct.
|
||||
}
|
||||
|
||||
build_return(bcx);
|
||||
}
|
||||
|
||||
let shim_name = link::mangle_internal_name_by_path(
|
||||
@ -1314,7 +1312,6 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) {
|
||||
let _icx = push_ctxt("foreign::foreign::wrap::build_ret");
|
||||
tys.fn_ty.build_wrap_ret(bcx, tys.llsig.llarg_tys, llargbundle);
|
||||
build_return(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,9 +348,9 @@ pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint)
|
||||
return cx;
|
||||
}
|
||||
|
||||
pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
let _icx = push_ctxt("make_visit_glue");
|
||||
let bcx = do with_scope(bcx, None, "visitor cleanup") |bcx| {
|
||||
do with_scope(bcx, None, "visitor cleanup") |bcx| {
|
||||
let mut bcx = bcx;
|
||||
let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
|
||||
let v = PointerCast(bcx, v, type_of::type_of(bcx.ccx(), object_ty).ptr_to());
|
||||
@ -358,14 +358,13 @@ pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
// The visitor is a boxed object and needs to be dropped
|
||||
add_clean(bcx, v, object_ty);
|
||||
bcx
|
||||
};
|
||||
build_return(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("make_free_glue");
|
||||
let bcx = match ty::get(t).sty {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(body_mt) => {
|
||||
let v = Load(bcx, v);
|
||||
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
|
||||
@ -389,9 +388,7 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
tvec::make_uniq_free_glue(bcx, v, t)
|
||||
}
|
||||
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
||||
make_free_glue(bcx, v,
|
||||
tvec::expand_boxed_vec_ty(bcx.tcx(), t));
|
||||
return;
|
||||
make_free_glue(bcx, v, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
|
||||
}
|
||||
ty::ty_closure(_) => {
|
||||
closure::make_closure_glue(bcx, v, t, free_ty)
|
||||
@ -400,8 +397,7 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
closure::make_opaque_cbox_free_glue(bcx, ck, v)
|
||||
}
|
||||
_ => bcx
|
||||
};
|
||||
build_return(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
|
||||
@ -475,11 +471,11 @@ pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::
|
||||
bcx
|
||||
}
|
||||
|
||||
pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
||||
pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) -> block {
|
||||
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("make_drop_glue");
|
||||
let ccx = bcx.ccx();
|
||||
let bcx = match ty::get(t).sty {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
|
||||
decr_refcnt_maybe_free(bcx, Load(bcx, v0), Some(v0), t)
|
||||
@ -542,8 +538,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
||||
iter_structural_ty(bcx, v0, t, drop_ty)
|
||||
} else { bcx }
|
||||
}
|
||||
};
|
||||
build_return(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
// box_ptr_ptr is optional, it is constructed if not supplied.
|
||||
@ -569,10 +564,10 @@ pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef,
|
||||
}
|
||||
|
||||
|
||||
pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
let _icx = push_ctxt("make_take_glue");
|
||||
// NB: v is a *pointer* to type t here, not a direct value.
|
||||
let bcx = match ty::get(t).sty {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
||||
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
|
||||
@ -638,9 +633,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
iter_structural_ty(bcx, v, t, take_ty)
|
||||
}
|
||||
_ => bcx
|
||||
};
|
||||
|
||||
build_return(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
|
||||
@ -690,7 +683,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
return inf;
|
||||
}
|
||||
|
||||
pub type glue_helper<'self> = &'self fn(block, ValueRef, ty::t);
|
||||
pub type glue_helper<'self> = &'self fn(block, ValueRef, ty::t) -> block;
|
||||
|
||||
pub fn declare_generic_glue(ccx: &mut CrateContext, t: ty::t, llfnty: Type,
|
||||
name: &str) -> ValueRef {
|
||||
@ -723,11 +716,9 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
|
||||
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
|
||||
let llty = type_of(ccx, t);
|
||||
let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
|
||||
helper(bcx, llrawptr0, t);
|
||||
let bcx = helper(bcx, llrawptr0, t);
|
||||
|
||||
// This is from the general finish fn, but that emits a ret {} that we don't want
|
||||
Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
|
||||
RetVoid(raw_block(fcx, false, fcx.llreturn));
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
|
||||
return llfn;
|
||||
}
|
||||
|
@ -299,12 +299,15 @@ impl Reflector {
|
||||
//
|
||||
llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
|
||||
};
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let mut bcx = top_scope_block(fcx, None);
|
||||
let arg = BitCast(bcx, arg, llptrty);
|
||||
let ret = adt::trans_get_discr(bcx, repr, arg);
|
||||
Store(bcx, ret, fcx.llretptr.get());
|
||||
cleanup_and_Br(bcx, bcx, fcx.llreturn);
|
||||
finish_fn(fcx, bcx.llbb);
|
||||
match fcx.llreturn {
|
||||
Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn),
|
||||
None => bcx = cleanup_block(bcx, Some(bcx.llbb))
|
||||
};
|
||||
finish_fn(fcx, bcx.llbb, bcx);
|
||||
llfdecl
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user