use middle::trans::adt;
use middle::trans::base;
use middle::trans::build::*;
+use middle::trans::builder::{Builder, noname};
use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::consts;
}
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
// 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",
};
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 {
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
}
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 {
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")
}
}
}
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(); }
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,
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));
}
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:
// 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) => {
None => last_bcx
};
build_return_block(fcx, ret_cx);
+ fcx.cleanup();
}
// Builds the return block for a function.
}
}
-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.
output_type,
false,
param_substs,
+ body.info(),
Some(body.span));
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
// 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));
}
// 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
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);
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,
// 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();
let args = ~[llenvarg];
Call(bcx, main_llfn, args);
- finish_fn(fcx, lltop, bcx);
+ finish_fn(fcx, bcx);
return llfdecl;
}