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);
|
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 {
|
pub fn ignore_lhs(_bcx: block, local: &ast::local) -> bool {
|
||||||
match local.node.pat.node {
|
match local.node.pat.node {
|
||||||
ast::pat_wild => true, _ => false
|
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) {
|
pub fn cleanup_and_Br(bcx: block, upto: block, target: BasicBlockRef) {
|
||||||
let _icx = push_ctxt("cleanup_and_Br");
|
let _icx = push_ctxt("cleanup_and_Br");
|
||||||
cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
|
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());
|
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);
|
let p = Alloca(initcx, ty, name);
|
||||||
if zero { memzero(initcx, p, ty); }
|
if zero { memzero(initcx, p, ty); }
|
||||||
p
|
p
|
||||||
@ -1539,24 +1570,26 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
|
|||||||
return llvm::LLVMGetUndef(ty.to_ref());
|
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 {
|
pub struct BasicBlocks {
|
||||||
sa: BasicBlockRef,
|
sa: BasicBlockRef,
|
||||||
rt: BasicBlockRef
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the standard set of basic blocks for a function
|
pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||||
pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cx = task_llcx();
|
let cx = task_llcx();
|
||||||
BasicBlocks {
|
str::as_c_str("static_allocas",
|
||||||
sa: str::as_c_str("static_allocas",
|
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
|
||||||
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)),
|
}
|
||||||
rt: str::as_c_str("return",
|
}
|
||||||
|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)
|
llvm::LLVMGetParam(fcx.llfn, 0)
|
||||||
} else {
|
} else {
|
||||||
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
|
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")
|
"__make_return_pointer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1596,8 +1629,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||||||
id,
|
id,
|
||||||
param_substs.repr(ccx.tcx));
|
param_substs.repr(ccx.tcx));
|
||||||
|
|
||||||
let llbbs = mk_standard_basic_blocks(llfndecl);
|
|
||||||
|
|
||||||
let substd_output_type = match param_substs {
|
let substd_output_type = match param_substs {
|
||||||
None => output_type,
|
None => output_type,
|
||||||
Some(substs) => {
|
Some(substs) => {
|
||||||
@ -1611,9 +1642,9 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||||||
llvm::LLVMGetUndef(Type::i8p().to_ref())
|
llvm::LLVMGetUndef(Type::i8p().to_ref())
|
||||||
},
|
},
|
||||||
llretptr: None,
|
llretptr: None,
|
||||||
llstaticallocas: llbbs.sa,
|
llstaticallocas: None,
|
||||||
llloadenv: None,
|
llloadenv: None,
|
||||||
llreturn: llbbs.rt,
|
llreturn: None,
|
||||||
llself: None,
|
llself: None,
|
||||||
personality: None,
|
personality: None,
|
||||||
loop_ret: None,
|
loop_ret: None,
|
||||||
@ -1757,16 +1788,24 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
|||||||
|
|
||||||
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
|
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
|
||||||
// and builds the return block.
|
// 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");
|
let _icx = push_ctxt("finish_fn");
|
||||||
tie_up_header_blocks(fcx, lltop);
|
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.
|
// Builds the return block for a function.
|
||||||
pub fn build_return_block(fcx: fn_ctxt) {
|
pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
|
||||||
let ret_cx = raw_block(fcx, false, fcx.llreturn);
|
|
||||||
|
|
||||||
// Return the value if this function immediate; otherwise, return void.
|
// Return the value if this function immediate; otherwise, return void.
|
||||||
if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
|
if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
|
||||||
Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
|
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) {
|
pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
||||||
let _icx = push_ctxt("tie_up_header_blocks");
|
let _icx = push_ctxt("tie_up_header_blocks");
|
||||||
match fcx.llloadenv {
|
let llnext = match fcx.llloadenv {
|
||||||
Some(ll) => {
|
Some(ll) => {
|
||||||
Br(raw_block(fcx, false, fcx.llstaticallocas), ll);
|
unsafe {
|
||||||
|
llvm::LLVMMoveBasicBlockBefore(ll, lltop);
|
||||||
|
}
|
||||||
Br(raw_block(fcx, false, ll), lltop);
|
Br(raw_block(fcx, false, ll), lltop);
|
||||||
|
ll
|
||||||
}
|
}
|
||||||
None => {
|
None => lltop
|
||||||
Br(raw_block(fcx, false, fcx.llstaticallocas), 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);
|
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.
|
// Put return block after all other blocks.
|
||||||
// This somewhat improves single-stepping experience in debugger.
|
// This somewhat improves single-stepping experience in debugger.
|
||||||
unsafe {
|
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.
|
// 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
|
// 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];
|
let arg_ty = arg_tys[i];
|
||||||
memcpy_ty(bcx, lldestptr, llarg, arg_ty);
|
memcpy_ty(bcx, lldestptr, llarg, arg_ty);
|
||||||
}
|
}
|
||||||
build_return(bcx);
|
finish_fn(fcx, lltop, bcx);
|
||||||
finish_fn(fcx, lltop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
|
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];
|
let args = ~[llenvarg];
|
||||||
Call(bcx, main_llfn, args);
|
Call(bcx, main_llfn, args);
|
||||||
|
|
||||||
build_return(bcx);
|
finish_fn(fcx, lltop, bcx);
|
||||||
finish_fn(fcx, lltop);
|
|
||||||
return llfdecl;
|
return llfdecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +704,7 @@ pub fn trans_call_inner(in_cx: block,
|
|||||||
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
|
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);
|
Unreachable(bcx);
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
|
@ -178,13 +178,13 @@ pub struct fn_ctxt_ {
|
|||||||
// the function, due to LLVM's quirks.
|
// the function, due to LLVM's quirks.
|
||||||
// A block for all the function's static allocas, so that LLVM
|
// A block for all the function's static allocas, so that LLVM
|
||||||
// will coalesce them into a single alloca call.
|
// will coalesce them into a single alloca call.
|
||||||
llstaticallocas: BasicBlockRef,
|
llstaticallocas: Option<BasicBlockRef>,
|
||||||
// A block containing code that copies incoming arguments to space
|
// A block containing code that copies incoming arguments to space
|
||||||
// already allocated by code in one of the llallocas blocks.
|
// already allocated by code in one of the llallocas blocks.
|
||||||
// (LLVM requires that arguments be copied to local allocas before
|
// (LLVM requires that arguments be copied to local allocas before
|
||||||
// allowing most any operation to be performed on them.)
|
// allowing most any operation to be performed on them.)
|
||||||
llloadenv: Option<BasicBlockRef>,
|
llloadenv: Option<BasicBlockRef>,
|
||||||
llreturn: BasicBlockRef,
|
llreturn: Option<BasicBlockRef>,
|
||||||
// The 'self' value currently in use in this function, if there
|
// The 'self' value currently in use in this function, if there
|
||||||
// is one.
|
// 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_;
|
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();
|
expr::trans_to_datum(bcx, cond).to_result();
|
||||||
|
|
||||||
let then_bcx_in = scope_block(bcx, thn.info(), "then");
|
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);
|
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(then_bcx_in, thn, dest);
|
||||||
let then_bcx_out = trans_block_cleanups(then_bcx_out,
|
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
|
// because trans_expr will create another scope block
|
||||||
// context for the block, but we've already got the
|
// context for the block, but we've already got the
|
||||||
// 'else' context
|
// 'else' context
|
||||||
let else_bcx_out = match els {
|
let (else_bcx_in, next_bcx) = match els {
|
||||||
Some(elexpr) => {
|
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(_, _, _) => {
|
ast::expr_if(_, _, _) => {
|
||||||
let elseif_blk = ast_util::block_from_expr(elexpr);
|
let elseif_blk = ast_util::block_from_expr(elexpr);
|
||||||
trans_block(else_bcx_in, &elseif_blk, dest)
|
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
|
// would be nice to have a constraint on ifs
|
||||||
_ => bcx.tcx().sess.bug("strange alternative in if")
|
_ => bcx.tcx().sess.bug("strange alternative in if")
|
||||||
}
|
};
|
||||||
}
|
let else_bcx_out = trans_block_cleanups(else_bcx_out,
|
||||||
_ => else_bcx_in
|
block_cleanups(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]);
|
|
||||||
|
|
||||||
|
(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 {
|
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
|
// This is a return from a loop body block
|
||||||
None => {
|
None => {
|
||||||
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
|
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);
|
Unreachable(bcx);
|
||||||
return 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);
|
Unreachable(bcx);
|
||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,10 @@ fn build_shim_fn_(ccx: @mut CrateContext,
|
|||||||
// follow the normal Rust calling conventions.
|
// follow the normal Rust calling conventions.
|
||||||
tie_up_header_blocks(fcx, lltop);
|
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);
|
RetVoid(ret_cx);
|
||||||
|
|
||||||
return llshimfn;
|
return llshimfn;
|
||||||
@ -194,7 +197,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||||||
// the C ABI.
|
// the C ABI.
|
||||||
if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
|
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);
|
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,
|
lloutputtype,
|
||||||
""));
|
""));
|
||||||
}
|
}
|
||||||
@ -217,7 +220,10 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||||||
tie_up_header_blocks(fcx, lltop);
|
tie_up_header_blocks(fcx, lltop);
|
||||||
|
|
||||||
// Then return according to the C ABI.
|
// 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 = val_ty(llwrapfn);
|
||||||
let llfunctiontype = llfunctiontype.element_type();
|
let llfunctiontype = llfunctiontype.element_type();
|
||||||
@ -388,7 +394,6 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
|||||||
tys.ret_def,
|
tys.ret_def,
|
||||||
llargbundle,
|
llargbundle,
|
||||||
llretval);
|
llretval);
|
||||||
build_return(bcx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let lname = link_name(ccx, foreign_item);
|
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) {
|
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
|
||||||
Store(bcx, retval, fcx.llretptr.get());
|
Store(bcx, retval, fcx.llretptr.get());
|
||||||
}
|
}
|
||||||
build_return(bcx);
|
finish_fn(fcx, lltop, bcx);
|
||||||
finish_fn(fcx, lltop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME (#2535): this is very shaky and probably gets ABIs wrong all
|
// 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) {
|
if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) {
|
||||||
Store(bcx, retval, fcx.llretptr.get());
|
Store(bcx, retval, fcx.llretptr.get());
|
||||||
}
|
}
|
||||||
build_return(bcx);
|
finish_fn(fcx, lltop, bcx);
|
||||||
finish_fn(fcx, lltop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_wrap_fn(ccx: @mut CrateContext,
|
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]);
|
let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]);
|
||||||
Store(bcx, Load(bcx, llretptr), retptr);
|
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, bcx);
|
||||||
finish_fn(fcx, lltop);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1124,8 +1125,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||||||
ccx.sess.span_bug(item.span, "unknown intrinsic");
|
ccx.sess.span_bug(item.span, "unknown intrinsic");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
build_return(bcx);
|
finish_fn(fcx, lltop, bcx);
|
||||||
finish_fn(fcx, lltop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1257,8 +1257,6 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
|||||||
// NB: The return pointer in the Rust ABI function is wired
|
// NB: The return pointer in the Rust ABI function is wired
|
||||||
// directly into the return slot in the shim struct.
|
// directly into the return slot in the shim struct.
|
||||||
}
|
}
|
||||||
|
|
||||||
build_return(bcx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let shim_name = link::mangle_internal_name_by_path(
|
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) {
|
fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) {
|
||||||
let _icx = push_ctxt("foreign::foreign::wrap::build_ret");
|
let _icx = push_ctxt("foreign::foreign::wrap::build_ret");
|
||||||
tys.fn_ty.build_wrap_ret(bcx, tys.llsig.llarg_tys, llargbundle);
|
tys.fn_ty.build_wrap_ret(bcx, tys.llsig.llarg_tys, llargbundle);
|
||||||
build_return(bcx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,9 +348,9 @@ pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint)
|
|||||||
return cx;
|
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 _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 mut bcx = bcx;
|
||||||
let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
|
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());
|
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
|
// The visitor is a boxed object and needs to be dropped
|
||||||
add_clean(bcx, v, object_ty);
|
add_clean(bcx, v, object_ty);
|
||||||
bcx
|
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.
|
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||||
let _icx = push_ctxt("make_free_glue");
|
let _icx = push_ctxt("make_free_glue");
|
||||||
let bcx = match ty::get(t).sty {
|
match ty::get(t).sty {
|
||||||
ty::ty_box(body_mt) => {
|
ty::ty_box(body_mt) => {
|
||||||
let v = Load(bcx, v);
|
let v = Load(bcx, v);
|
||||||
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
|
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)
|
tvec::make_uniq_free_glue(bcx, v, t)
|
||||||
}
|
}
|
||||||
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
||||||
make_free_glue(bcx, v,
|
make_free_glue(bcx, v, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
|
||||||
tvec::expand_boxed_vec_ty(bcx.tcx(), t));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
ty::ty_closure(_) => {
|
ty::ty_closure(_) => {
|
||||||
closure::make_closure_glue(bcx, v, t, free_ty)
|
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)
|
closure::make_opaque_cbox_free_glue(bcx, ck, v)
|
||||||
}
|
}
|
||||||
_ => bcx
|
_ => bcx
|
||||||
};
|
}
|
||||||
build_return(bcx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
|
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
|
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.
|
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||||
let _icx = push_ctxt("make_drop_glue");
|
let _icx = push_ctxt("make_drop_glue");
|
||||||
let ccx = bcx.ccx();
|
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_box(_) | ty::ty_opaque_box |
|
||||||
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
|
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
|
||||||
decr_refcnt_maybe_free(bcx, Load(bcx, v0), Some(v0), t)
|
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)
|
iter_structural_ty(bcx, v0, t, drop_ty)
|
||||||
} else { bcx }
|
} else { bcx }
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
build_return(bcx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// box_ptr_ptr is optional, it is constructed if not supplied.
|
// 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");
|
let _icx = push_ctxt("make_take_glue");
|
||||||
// NB: v is a *pointer* to type t here, not a direct value.
|
// 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_box(_) | ty::ty_opaque_box |
|
||||||
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
||||||
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
|
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)
|
iter_structural_ty(bcx, v, t, take_ty)
|
||||||
}
|
}
|
||||||
_ => bcx
|
_ => bcx
|
||||||
};
|
}
|
||||||
|
|
||||||
build_return(bcx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
|
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;
|
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,
|
pub fn declare_generic_glue(ccx: &mut CrateContext, t: ty::t, llfnty: Type,
|
||||||
name: &str) -> ValueRef {
|
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 llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
|
||||||
let llty = type_of(ccx, t);
|
let llty = type_of(ccx, t);
|
||||||
let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
|
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
|
finish_fn(fcx, lltop, bcx);
|
||||||
Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
|
|
||||||
RetVoid(raw_block(fcx, false, fcx.llreturn));
|
|
||||||
|
|
||||||
return llfn;
|
return llfn;
|
||||||
}
|
}
|
||||||
|
@ -299,12 +299,15 @@ impl Reflector {
|
|||||||
//
|
//
|
||||||
llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
|
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 arg = BitCast(bcx, arg, llptrty);
|
||||||
let ret = adt::trans_get_discr(bcx, repr, arg);
|
let ret = adt::trans_get_discr(bcx, repr, arg);
|
||||||
Store(bcx, ret, fcx.llretptr.get());
|
Store(bcx, ret, fcx.llretptr.get());
|
||||||
cleanup_and_Br(bcx, bcx, fcx.llreturn);
|
match fcx.llreturn {
|
||||||
finish_fn(fcx, bcx.llbb);
|
Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn),
|
||||||
|
None => bcx = cleanup_block(bcx, Some(bcx.llbb))
|
||||||
|
};
|
||||||
|
finish_fn(fcx, bcx.llbb, bcx);
|
||||||
llfdecl
|
llfdecl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user