Avoid blocks for static allocas and loading the closure environment
These blocks were required because previously we could only insert instructions at the end of blocks, but we wanted to have all allocas in one place, so they can be collapse. But now we have "direct" access the the LLVM IR builder and can position it freely. This allows us to use the same trick that clang uses, which means that we insert a dummy "marker" instruction to identify the spot at which we want to insert allocas. We can then later position the IR builder at that spot and insert the alloca instruction, without any dedicated block. The block for loading the closure environment can now also go away, because the function context now provides the toplevel block, and the translation of the loading happens first, so that's good enough. Makes the LLVM IR a bit more readable, saving a bunch of branches in the unoptimized code, which benefits unoptimized builds.
This commit is contained in:
parent
565a9bf20b
commit
205baa6ca2
9 changed files with 79 additions and 112 deletions
|
@ -984,6 +984,8 @@ pub mod llvm {
|
|||
pub unsafe fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMInstructionEraseFromParent(Inst: ValueRef);
|
||||
|
||||
/* Operations on call sites */
|
||||
#[fast_ffi]
|
||||
|
|
|
@ -41,7 +41,7 @@ use middle::trans::_match;
|
|||
use middle::trans::adt;
|
||||
use middle::trans::base;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::builder::noname;
|
||||
use middle::trans::builder::{Builder, noname};
|
||||
use middle::trans::callee;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::consts;
|
||||
|
@ -1503,11 +1503,12 @@ pub fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) {
|
|||
}
|
||||
|
||||
pub fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
|
||||
if cx.unreachable { return; }
|
||||
let _icx = push_ctxt("zero_mem");
|
||||
let bcx = cx;
|
||||
let ccx = cx.ccx();
|
||||
let llty = type_of::type_of(ccx, t);
|
||||
memzero(bcx, llptr, llty);
|
||||
memzero(&B(bcx), llptr, llty);
|
||||
}
|
||||
|
||||
// Always use this function instead of storing a zero constant to the memory
|
||||
|
@ -1515,9 +1516,9 @@ 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(cx: block, llptr: ValueRef, ty: Type) {
|
||||
pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
|
||||
let _icx = push_ctxt("memzero");
|
||||
let ccx = cx.ccx();
|
||||
let ccx = b.ccx;
|
||||
|
||||
let intrinsic_key = match ccx.sess.targ_cfg.arch {
|
||||
X86 | Arm | Mips => "llvm.memset.p0i8.i32",
|
||||
|
@ -1525,12 +1526,12 @@ pub fn memzero(cx: block, llptr: ValueRef, ty: Type) {
|
|||
};
|
||||
|
||||
let llintrinsicfn = ccx.intrinsics.get_copy(&intrinsic_key);
|
||||
let llptr = PointerCast(cx, llptr, Type::i8().ptr_to());
|
||||
let llptr = b.pointercast(llptr, Type::i8().ptr_to());
|
||||
let llzeroval = C_u8(0);
|
||||
let size = IntCast(cx, machine::llsize_of(ccx, ty), ccx.int_type);
|
||||
let size = machine::llsize_of(ccx, ty);
|
||||
let align = C_i32(llalign_of_min(ccx, ty) as i32);
|
||||
let volatile = C_i1(false);
|
||||
Call(cx, llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
|
||||
b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
|
||||
}
|
||||
|
||||
pub fn alloc_ty(bcx: block, t: ty::t, name: &str) -> ValueRef {
|
||||
|
@ -1553,9 +1554,12 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
|
|||
return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
|
||||
}
|
||||
}
|
||||
let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
|
||||
let p = Alloca(initcx, ty, name);
|
||||
if zero { memzero(initcx, p, ty); }
|
||||
let p = Alloca(cx, ty, name);
|
||||
if zero {
|
||||
let b = cx.fcx.ccx.builder();
|
||||
b.position_before(cx.fcx.alloca_insert_pt.get());
|
||||
memzero(&b, p, ty);
|
||||
}
|
||||
p
|
||||
}
|
||||
|
||||
|
@ -1566,7 +1570,7 @@ 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.get_llstaticallocas()), ty, v);
|
||||
return ArrayAlloca(cx, ty, v);
|
||||
}
|
||||
|
||||
pub struct BasicBlocks {
|
||||
|
@ -1597,8 +1601,8 @@ 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.get_llstaticallocas()), lloutputtype,
|
||||
"__make_return_pointer")
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
Alloca(bcx, lloutputtype, "__make_return_pointer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1616,6 +1620,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||
output_type: ty::t,
|
||||
skip_retptr: bool,
|
||||
param_substs: Option<@param_substs>,
|
||||
opt_node_info: Option<NodeInfo>,
|
||||
sp: Option<span>)
|
||||
-> fn_ctxt {
|
||||
for param_substs.iter().advance |p| { p.validate(); }
|
||||
|
@ -1639,8 +1644,8 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||
llvm::LLVMGetUndef(Type::i8p().to_ref())
|
||||
},
|
||||
llretptr: None,
|
||||
llstaticallocas: None,
|
||||
llloadenv: None,
|
||||
entry_bcx: None,
|
||||
alloca_insert_pt: None,
|
||||
llreturn: None,
|
||||
llself: None,
|
||||
personality: None,
|
||||
|
@ -1658,6 +1663,15 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||
fcx.llenv = unsafe {
|
||||
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let entry_bcx = top_scope_block(fcx, opt_node_info);
|
||||
Load(entry_bcx, C_null(Type::i8p()));
|
||||
|
||||
fcx.entry_bcx = Some(entry_bcx);
|
||||
fcx.alloca_insert_pt = Some(llvm::LLVMGetFirstInstruction(entry_bcx.llbb));
|
||||
}
|
||||
|
||||
if !ty::type_is_nil(substd_output_type) && !(is_immediate && skip_retptr) {
|
||||
fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
|
||||
}
|
||||
|
@ -1670,7 +1684,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
|
|||
output_type: ty::t,
|
||||
sp: Option<span>)
|
||||
-> fn_ctxt {
|
||||
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, sp)
|
||||
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp)
|
||||
}
|
||||
|
||||
// NB: must keep 4 fns in sync:
|
||||
|
@ -1785,9 +1799,8 @@ 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, last_bcx: block) {
|
||||
pub fn finish_fn(fcx: fn_ctxt, last_bcx: block) {
|
||||
let _icx = push_ctxt("finish_fn");
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
|
||||
let ret_cx = match fcx.llreturn {
|
||||
Some(llreturn) => {
|
||||
|
@ -1799,6 +1812,7 @@ pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
|
|||
None => last_bcx
|
||||
};
|
||||
build_return_block(fcx, ret_cx);
|
||||
fcx.cleanup();
|
||||
}
|
||||
|
||||
// Builds the return block for a function.
|
||||
|
@ -1811,29 +1825,6 @@ pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
||||
let _icx = push_ctxt("tie_up_header_blocks");
|
||||
let llnext = match fcx.llloadenv {
|
||||
Some(ll) => {
|
||||
unsafe {
|
||||
llvm::LLVMMoveBasicBlockBefore(ll, lltop);
|
||||
}
|
||||
Br(raw_block(fcx, false, ll), lltop);
|
||||
ll
|
||||
}
|
||||
None => lltop
|
||||
};
|
||||
match fcx.llstaticallocas {
|
||||
Some(ll) => {
|
||||
unsafe {
|
||||
llvm::LLVMMoveBasicBlockBefore(ll, llnext);
|
||||
}
|
||||
Br(raw_block(fcx, false, ll), llnext);
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
|
||||
|
||||
// trans_closure: Builds an LLVM function out of a source function.
|
||||
|
@ -1866,6 +1857,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
|
|||
output_type,
|
||||
false,
|
||||
param_substs,
|
||||
body.info(),
|
||||
Some(body.span));
|
||||
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
|
||||
|
||||
|
@ -1877,9 +1869,8 @@ pub fn trans_closure(ccx: @mut CrateContext,
|
|||
|
||||
// Create the first basic block in the function and keep a handle on it to
|
||||
// pass to finish_fn later.
|
||||
let bcx_top = top_scope_block(fcx, body.info());
|
||||
let bcx_top = fcx.entry_bcx.get();
|
||||
let mut bcx = bcx_top;
|
||||
let lltop = bcx.llbb;
|
||||
let block_ty = node_id_type(bcx, body.id);
|
||||
|
||||
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
|
||||
|
@ -1915,7 +1906,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
|
|||
}
|
||||
|
||||
// Insert the mandatory first few basic blocks before lltop.
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
}
|
||||
|
||||
// trans_fn: creates an LLVM function corresponding to a source language
|
||||
|
@ -2085,12 +2076,12 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
|||
result_ty,
|
||||
false,
|
||||
param_substs,
|
||||
None,
|
||||
None);
|
||||
|
||||
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
|
||||
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
let arg_tys = ty::ty_fn_args(ctor_ty);
|
||||
|
||||
insert_synthetic_type_entries(bcx, fn_args, arg_tys);
|
||||
|
@ -2108,7 +2099,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);
|
||||
}
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
}
|
||||
|
||||
pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
|
||||
|
@ -2336,9 +2327,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
|||
// be updated if this assertion starts to fail.
|
||||
assert!(fcx.has_immediate_return_value);
|
||||
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
// Call main.
|
||||
let llenvarg = unsafe {
|
||||
let env_arg = fcx.env_arg_pos();
|
||||
|
@ -2347,7 +2336,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
|||
let args = ~[llenvarg];
|
||||
Call(bcx, main_llfn, args);
|
||||
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
return llfdecl;
|
||||
}
|
||||
|
||||
|
|
|
@ -318,14 +318,18 @@ pub fn ArrayMalloc(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
|
|||
pub fn Alloca(cx: block, Ty: Type, name: &str) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
|
||||
B(cx).alloca(Ty, name)
|
||||
let b = cx.fcx.ccx.builder();
|
||||
b.position_before(cx.fcx.alloca_insert_pt.get());
|
||||
b.alloca(Ty, name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ArrayAlloca(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
|
||||
B(cx).array_alloca(Ty, Val)
|
||||
let b = cx.fcx.ccx.builder();
|
||||
b.position_before(cx.fcx.alloca_insert_pt.get());
|
||||
b.array_alloca(Ty, Val)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
use back::abi;
|
||||
use back::link::{mangle_internal_name_by_path_and_seq};
|
||||
use lib::llvm::{llvm, ValueRef};
|
||||
use lib::llvm::ValueRef;
|
||||
use middle::moves;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
|
@ -25,7 +25,6 @@ use util::ppaux::ty_to_str;
|
|||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::str;
|
||||
use std::vec;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map::path_name;
|
||||
|
@ -331,23 +330,7 @@ pub fn load_environment(fcx: fn_ctxt,
|
|||
return;
|
||||
}
|
||||
|
||||
let llloadenv = match fcx.llloadenv {
|
||||
Some(ll) => ll,
|
||||
None => {
|
||||
let ll =
|
||||
str::as_c_str("load_env",
|
||||
|buf|
|
||||
unsafe {
|
||||
llvm::LLVMAppendBasicBlockInContext(fcx.ccx.llcx,
|
||||
fcx.llfn,
|
||||
buf)
|
||||
});
|
||||
fcx.llloadenv = Some(ll);
|
||||
ll
|
||||
}
|
||||
};
|
||||
|
||||
let bcx = raw_block(fcx, false, llloadenv);
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
|
||||
// Load a pointer to the closure data, skipping over the box header:
|
||||
let llcdata = opaque_box_body(bcx, cdata_ty, fcx.llenv);
|
||||
|
|
|
@ -174,17 +174,14 @@ pub struct fn_ctxt_ {
|
|||
// always be Some.
|
||||
llretptr: Option<ValueRef>,
|
||||
|
||||
entry_bcx: Option<block>,
|
||||
|
||||
// These elements: "hoisted basic blocks" containing
|
||||
// administrative activities that have to happen in only one place in
|
||||
// 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: 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>,
|
||||
// A marker for the place where we want to insert the function's static
|
||||
// allocas, so that LLVM will coalesce them into a single alloca call.
|
||||
alloca_insert_pt: Option<ValueRef>,
|
||||
llreturn: Option<BasicBlockRef>,
|
||||
// The 'self' value currently in use in this function, if there
|
||||
// is one.
|
||||
|
@ -252,12 +249,12 @@ 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));
|
||||
pub fn cleanup(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt.get());
|
||||
}
|
||||
|
||||
self.llstaticallocas.get()
|
||||
// Remove the cycle between fcx and bcx, so memory can be freed
|
||||
self.entry_bcx = None;
|
||||
}
|
||||
|
||||
pub fn get_llreturn(&mut self) -> BasicBlockRef {
|
||||
|
|
|
@ -149,8 +149,7 @@ fn build_shim_fn_(ccx: @mut CrateContext,
|
|||
|
||||
// Declare the body of the shim function:
|
||||
let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None);
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
|
||||
let llargbundle = get_param(llshimfn, 0u);
|
||||
let llargvals = arg_builder(bcx, tys, llargbundle);
|
||||
|
@ -162,13 +161,12 @@ fn build_shim_fn_(ccx: @mut CrateContext,
|
|||
|
||||
// Don't finish up the function in the usual way, because this doesn't
|
||||
// follow the normal Rust calling conventions.
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
|
||||
let ret_cx = match fcx.llreturn {
|
||||
Some(llreturn) => raw_block(fcx, false, llreturn),
|
||||
None => bcx
|
||||
};
|
||||
RetVoid(ret_cx);
|
||||
fcx.cleanup();
|
||||
|
||||
return llshimfn;
|
||||
}
|
||||
|
@ -192,19 +190,15 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||
ret_builder: wrap_ret_builder) {
|
||||
let _icx = push_ctxt("foreign::build_wrap_fn_");
|
||||
let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None);
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
|
||||
// Patch up the return type if it's not immediate and we're returning via
|
||||
// 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.get_llstaticallocas()),
|
||||
lloutputtype,
|
||||
""));
|
||||
fcx.llretptr = Some(alloca(bcx, lloutputtype, ""));
|
||||
}
|
||||
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
|
||||
// Allocate the struct and write the arguments into it.
|
||||
let llargbundle = alloca(bcx, tys.bundle_ty, "__llargbundle");
|
||||
arg_builder(bcx, tys, llwrapfn, llargbundle);
|
||||
|
@ -215,10 +209,6 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||
Call(bcx, shim_upcall, [llrawargbundle, llshimfnptr]);
|
||||
ret_builder(bcx, tys, llargbundle);
|
||||
|
||||
// Perform a custom version of `finish_fn`. First, tie up the header
|
||||
// blocks.
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
|
||||
// Then return according to the C ABI.
|
||||
let return_context = match fcx.llreturn {
|
||||
Some(llreturn) => raw_block(fcx, false, llreturn),
|
||||
|
@ -239,6 +229,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||
let llretptr = BitCast(return_context, fcx.llretptr.get(), return_type.ptr_to());
|
||||
Ret(return_context, Load(return_context, llretptr));
|
||||
}
|
||||
fcx.cleanup();
|
||||
}
|
||||
|
||||
// For each foreign function F, we generate a wrapper function W and a shim
|
||||
|
@ -430,8 +421,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
|||
debug!("build_direct_fn(%s)", link_name(ccx, item));
|
||||
|
||||
let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None);
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
let llbasefn = base_fn(ccx, link_name(ccx, item), tys, cc);
|
||||
let ty = ty::lookup_item_type(ccx.tcx,
|
||||
ast_util::local_def(item.id)).ty;
|
||||
|
@ -443,7 +433,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());
|
||||
}
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
}
|
||||
|
||||
// FIXME (#2535): this is very shaky and probably gets ABIs wrong all
|
||||
|
@ -456,8 +446,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
|||
debug!("build_fast_ffi_fn(%s)", link_name(ccx, item));
|
||||
|
||||
let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None);
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
let llbasefn = base_fn(ccx, link_name(ccx, item), tys, cc);
|
||||
set_no_inline(fcx.llfn);
|
||||
set_fixed_stack_segment(fcx.llfn);
|
||||
|
@ -471,7 +460,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());
|
||||
}
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
}
|
||||
|
||||
fn build_wrap_fn(ccx: @mut CrateContext,
|
||||
|
@ -619,6 +608,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
output_type,
|
||||
true,
|
||||
Some(substs),
|
||||
None,
|
||||
Some(item.span));
|
||||
|
||||
set_always_inline(fcx.llfn);
|
||||
|
@ -628,7 +618,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
set_fixed_stack_segment(fcx.llfn);
|
||||
}
|
||||
|
||||
let mut bcx = top_scope_block(fcx, None);
|
||||
let mut bcx = fcx.entry_bcx.get();
|
||||
let first_real_arg = fcx.arg_pos(0u);
|
||||
|
||||
let nm = ccx.sess.str_of(item.ident);
|
||||
|
@ -694,6 +684,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
}
|
||||
}
|
||||
|
||||
fcx.cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -942,6 +933,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
ccx.sess.span_bug(item.span, "unknown intrinsic");
|
||||
}
|
||||
}
|
||||
fcx.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -615,7 +615,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
|
|||
// Zero out the struct
|
||||
unsafe {
|
||||
let ty = Type::from_ref(llvm::LLVMTypeOf(v));
|
||||
memzero(bcx, v, ty);
|
||||
memzero(&B(bcx), v, ty);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -707,13 +707,12 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
|
|||
// llfn is expected be declared to take a parameter of the appropriate
|
||||
// type, so we don't need to explicitly cast the function parameter.
|
||||
|
||||
let bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
let bcx = fcx.entry_bcx.get();
|
||||
let rawptr0_arg = fcx.arg_pos(0u);
|
||||
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
|
||||
let bcx = helper(bcx, llrawptr0, t);
|
||||
|
||||
finish_fn(fcx, lltop, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
|
||||
return llfn;
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ impl Reflector {
|
|||
//
|
||||
llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
|
||||
};
|
||||
let mut bcx = top_scope_block(fcx, None);
|
||||
let mut bcx = fcx.entry_bcx.get();
|
||||
let arg = BitCast(bcx, arg, llptrty);
|
||||
let ret = adt::trans_get_discr(bcx, repr, arg);
|
||||
Store(bcx, ret, fcx.llretptr.get());
|
||||
|
@ -311,7 +311,7 @@ impl Reflector {
|
|||
Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn),
|
||||
None => bcx = cleanup_block(bcx, Some(bcx.llbb))
|
||||
};
|
||||
finish_fn(fcx, bcx.llbb, bcx);
|
||||
finish_fn(fcx, bcx);
|
||||
llfdecl
|
||||
};
|
||||
|
||||
|
|
|
@ -409,6 +409,7 @@ LLVMInsertBasicBlock
|
|||
LLVMInsertBasicBlockInContext
|
||||
LLVMInsertIntoBuilder
|
||||
LLVMInsertIntoBuilderWithName
|
||||
LLVMInstructionEraseFromParent
|
||||
LLVMInt16Type
|
||||
LLVMInt16TypeInContext
|
||||
LLVMInt1Type
|
||||
|
|
Loading…
Add table
Reference in a new issue