librustc_trans: use unboxed closures
This commit is contained in:
parent
0d4d8b9b78
commit
0676c3bf03
@ -488,8 +488,12 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||
// pass manager passed to the closure should be ensured to not
|
||||
// escape the closure itself, and the manager should only be
|
||||
// used once.
|
||||
unsafe fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
|
||||
no_builtins: bool, f: |PassManagerRef|) {
|
||||
unsafe fn with_codegen<F>(tm: TargetMachineRef,
|
||||
llmod: ModuleRef,
|
||||
no_builtins: bool,
|
||||
f: F) where
|
||||
F: FnOnce(PassManagerRef),
|
||||
{
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
|
@ -79,7 +79,9 @@ struct DxrVisitor<'l, 'tcx: 'l> {
|
||||
}
|
||||
|
||||
impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
fn nest(&mut self, scope_id: NodeId, f: |&mut DxrVisitor<'l, 'tcx>|) {
|
||||
fn nest<F>(&mut self, scope_id: NodeId, f: F) where
|
||||
F: FnOnce(&mut DxrVisitor<'l, 'tcx>),
|
||||
{
|
||||
let parent_scope = self.cur_scope;
|
||||
self.cur_scope = scope_id;
|
||||
f(self);
|
||||
|
@ -1578,14 +1578,15 @@ pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
bind_irrefutable_pat(bcx, pat, llvalue, body_scope)
|
||||
}
|
||||
|
||||
fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
|
||||
p_id: ast::NodeId,
|
||||
ident: &ast::Ident,
|
||||
cleanup_scope: cleanup::ScopeId,
|
||||
arg: A,
|
||||
populate: |A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|
|
||||
-> Block<'blk, 'tcx>)
|
||||
-> Block<'blk, 'tcx> {
|
||||
fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
|
||||
p_id: ast::NodeId,
|
||||
ident: &ast::Ident,
|
||||
cleanup_scope: cleanup::ScopeId,
|
||||
arg: A,
|
||||
populate: F)
|
||||
-> Block<'blk, 'tcx> where
|
||||
F: FnOnce(A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
|
||||
{
|
||||
let var_ty = node_id_type(bcx, p_id);
|
||||
|
||||
// Allocate memory on stack for the binding.
|
||||
|
@ -858,10 +858,13 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v
|
||||
GEPi(bcx, val, &[0, ix])
|
||||
}
|
||||
|
||||
pub fn fold_variants<'blk, 'tcx>(
|
||||
bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, value: ValueRef,
|
||||
f: |Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef| -> Block<'blk, 'tcx>)
|
||||
-> Block<'blk, 'tcx> {
|
||||
pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
r: &Repr<'tcx>,
|
||||
value: ValueRef,
|
||||
mut f: F)
|
||||
-> Block<'blk, 'tcx> where
|
||||
F: FnMut(Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> Block<'blk, 'tcx>,
|
||||
{
|
||||
let fcx = bcx.fcx;
|
||||
match *r {
|
||||
Univariant(ref st, _) => {
|
||||
|
@ -107,9 +107,11 @@ thread_local!(static TASK_LOCAL_INSN_KEY: RefCell<Option<Vec<&'static str>>> = {
|
||||
RefCell::new(None)
|
||||
})
|
||||
|
||||
pub fn with_insn_ctxt(blk: |&[&'static str]|) {
|
||||
TASK_LOCAL_INSN_KEY.with(|slot| {
|
||||
slot.borrow().as_ref().map(|s| blk(s.as_slice()));
|
||||
pub fn with_insn_ctxt<F>(blk: F) where
|
||||
F: FnOnce(&[&'static str]),
|
||||
{
|
||||
TASK_LOCAL_INSN_KEY.with(move |slot| {
|
||||
slot.borrow().as_ref().map(move |s| blk(s.as_slice()));
|
||||
})
|
||||
}
|
||||
|
||||
@ -841,12 +843,15 @@ pub fn cast_shift_const_rhs(op: ast::BinOp,
|
||||
|a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
|
||||
}
|
||||
|
||||
pub fn cast_shift_rhs(op: ast::BinOp,
|
||||
lhs: ValueRef,
|
||||
rhs: ValueRef,
|
||||
trunc: |ValueRef, Type| -> ValueRef,
|
||||
zext: |ValueRef, Type| -> ValueRef)
|
||||
-> ValueRef {
|
||||
pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
|
||||
lhs: ValueRef,
|
||||
rhs: ValueRef,
|
||||
trunc: F,
|
||||
zext: G)
|
||||
-> ValueRef where
|
||||
F: FnOnce(ValueRef, Type) -> ValueRef,
|
||||
G: FnOnce(ValueRef, Type) -> ValueRef,
|
||||
{
|
||||
// Shifts may have any size int on the rhs
|
||||
unsafe {
|
||||
if ast_util::is_shift_binop(op) {
|
||||
@ -1101,10 +1106,12 @@ pub fn raw_block<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
|
||||
common::BlockS::new(llbb, is_lpad, None, fcx)
|
||||
}
|
||||
|
||||
pub fn with_cond<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
val: ValueRef,
|
||||
f: |Block<'blk, 'tcx>| -> Block<'blk, 'tcx>)
|
||||
-> Block<'blk, 'tcx> {
|
||||
pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
val: ValueRef,
|
||||
f: F)
|
||||
-> Block<'blk, 'tcx> where
|
||||
F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>,
|
||||
{
|
||||
let _icx = push_ctxt("with_cond");
|
||||
let fcx = bcx.fcx;
|
||||
let next_cx = fcx.new_temp_block("next");
|
||||
|
@ -342,11 +342,13 @@ pub fn compute_abi_info(ccx: &CrateContext,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
fn x86_64_ty(ccx: &CrateContext,
|
||||
ty: Type,
|
||||
is_mem_cls: |cls: &[RegClass]| -> bool,
|
||||
ind_attr: Attribute)
|
||||
-> ArgType {
|
||||
fn x86_64_ty<F>(ccx: &CrateContext,
|
||||
ty: Type,
|
||||
is_mem_cls: F,
|
||||
ind_attr: Attribute)
|
||||
-> ArgType where
|
||||
F: FnOnce(&[RegClass]) -> bool,
|
||||
{
|
||||
if !ty.is_reg_ty() {
|
||||
let cls = classify_ty(ty);
|
||||
if is_mem_cls(cls.as_slice()) {
|
||||
|
@ -781,15 +781,15 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
///
|
||||
/// For non-lang items, `dest` is always Some, and hence the result is written into memory
|
||||
/// somewhere. Nonetheless we return the actual return value of the function.
|
||||
pub fn trans_call_inner<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
call_info: Option<NodeInfo>,
|
||||
callee_ty: Ty<'tcx>,
|
||||
get_callee: |bcx: Block<'blk, 'tcx>,
|
||||
arg_cleanup_scope: cleanup::ScopeId|
|
||||
-> Callee<'blk, 'tcx>,
|
||||
args: CallArgs<'a, 'tcx>,
|
||||
dest: Option<expr::Dest>)
|
||||
-> Result<'blk, 'tcx> {
|
||||
pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
call_info: Option<NodeInfo>,
|
||||
callee_ty: Ty<'tcx>,
|
||||
get_callee: F,
|
||||
args: CallArgs<'a, 'tcx>,
|
||||
dest: Option<expr::Dest>)
|
||||
-> Result<'blk, 'tcx> where
|
||||
F: FnOnce(Block<'blk, 'tcx>, cleanup::ScopeId) -> Callee<'blk, 'tcx>,
|
||||
{
|
||||
// Introduce a temporary cleanup scope that will contain cleanups
|
||||
// for the arguments while they are being evaluated. The purpose
|
||||
// this cleanup is to ensure that, should a panic occur while
|
||||
|
@ -527,7 +527,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
|
||||
self.scopes.borrow_mut().pop().unwrap()
|
||||
}
|
||||
|
||||
fn top_scope<R>(&self, f: |&CleanupScope<'blk, 'tcx>| -> R) -> R {
|
||||
fn top_scope<R, F>(&self, f: F) -> R where F: FnOnce(&CleanupScope<'blk, 'tcx>) -> R {
|
||||
f(self.scopes.borrow().last().unwrap())
|
||||
}
|
||||
|
||||
@ -1145,5 +1145,5 @@ trait CleanupHelperMethods<'blk, 'tcx> {
|
||||
fn scopes_len(&self) -> uint;
|
||||
fn push_scope(&self, scope: CleanupScope<'blk, 'tcx>);
|
||||
fn pop_scope(&self) -> CleanupScope<'blk, 'tcx>;
|
||||
fn top_scope<R>(&self, f: |&CleanupScope<'blk, 'tcx>| -> R) -> R;
|
||||
fn top_scope<R, F>(&self, f: F) -> R where F: FnOnce(&CleanupScope<'blk, 'tcx>) -> R;
|
||||
}
|
||||
|
@ -113,15 +113,16 @@ pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
/// it. The memory will be dropped upon exit from `scope`. The callback `populate` should
|
||||
/// initialize the memory. If `zero` is true, the space will be zeroed when it is allocated; this
|
||||
/// is not necessary unless `bcx` does not dominate the end of `scope`.
|
||||
pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
name: &str,
|
||||
zero: bool,
|
||||
scope: cleanup::ScopeId,
|
||||
arg: A,
|
||||
populate: |A, Block<'blk, 'tcx>, ValueRef|
|
||||
-> Block<'blk, 'tcx>)
|
||||
-> DatumBlock<'blk, 'tcx, Lvalue> {
|
||||
pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
name: &str,
|
||||
zero: bool,
|
||||
scope: cleanup::ScopeId,
|
||||
arg: A,
|
||||
populate: F)
|
||||
-> DatumBlock<'blk, 'tcx, Lvalue> where
|
||||
F: FnOnce(A, Block<'blk, 'tcx>, ValueRef) -> Block<'blk, 'tcx>,
|
||||
{
|
||||
let scratch = if zero {
|
||||
alloca_zeroed(bcx, ty, name)
|
||||
} else {
|
||||
@ -339,10 +340,10 @@ impl<'tcx> Datum<'tcx, Rvalue> {
|
||||
/// here since we can `match self.kind` rather than having to implement
|
||||
/// generic methods in `KindOps`.)
|
||||
impl<'tcx> Datum<'tcx, Expr> {
|
||||
fn match_kind<R>(self,
|
||||
if_lvalue: |Datum<'tcx, Lvalue>| -> R,
|
||||
if_rvalue: |Datum<'tcx, Rvalue>| -> R)
|
||||
-> R {
|
||||
fn match_kind<R, F, G>(self, if_lvalue: F, if_rvalue: G) -> R where
|
||||
F: FnOnce(Datum<'tcx, Lvalue>) -> R,
|
||||
G: FnOnce(Datum<'tcx, Rvalue>) -> R,
|
||||
{
|
||||
let Datum { val, ty, kind } = self;
|
||||
match kind {
|
||||
LvalueExpr => if_lvalue(Datum::new(val, ty, Lvalue)),
|
||||
@ -455,9 +456,11 @@ impl<'tcx> Datum<'tcx, Lvalue> {
|
||||
// datum may also be unsized _without the size information_. It is the
|
||||
// callers responsibility to package the result in some way to make a valid
|
||||
// datum in that case (e.g., by making a fat pointer or opened pair).
|
||||
pub fn get_element<'blk>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
|
||||
gep: |ValueRef| -> ValueRef)
|
||||
-> Datum<'tcx, Lvalue> {
|
||||
pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
|
||||
gep: F)
|
||||
-> Datum<'tcx, Lvalue> where
|
||||
F: FnOnce(ValueRef) -> ValueRef,
|
||||
{
|
||||
let val = match self.ty.sty {
|
||||
_ if ty::type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
|
||||
ty::ty_open(_) => {
|
||||
|
@ -3212,13 +3212,13 @@ fn populate_scope_map(cx: &CrateContext,
|
||||
});
|
||||
|
||||
// local helper functions for walking the AST.
|
||||
fn with_new_scope(cx: &CrateContext,
|
||||
scope_span: Span,
|
||||
scope_stack: &mut Vec<ScopeStackEntry> ,
|
||||
scope_map: &mut NodeMap<DIScope>,
|
||||
inner_walk: |&CrateContext,
|
||||
&mut Vec<ScopeStackEntry> ,
|
||||
&mut NodeMap<DIScope>|) {
|
||||
fn with_new_scope<F>(cx: &CrateContext,
|
||||
scope_span: Span,
|
||||
scope_stack: &mut Vec<ScopeStackEntry> ,
|
||||
scope_map: &mut NodeMap<DIScope>,
|
||||
inner_walk: F) where
|
||||
F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
|
||||
{
|
||||
// Create a new lexical scope and push it onto the stack
|
||||
let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
|
||||
let file_metadata = file_metadata(cx, loc.file.name.as_slice());
|
||||
|
@ -295,6 +295,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
// into a type to be destructed. If we want to end up with a Box pointer,
|
||||
// then mk_ty should make a Box pointer (T -> Box<T>), if we want a
|
||||
// borrowed reference then it should be T -> &T.
|
||||
// FIXME(#19596) unbox `mk_ty`
|
||||
fn unsized_info<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
kind: &ty::UnsizeKind<'tcx>,
|
||||
id: ast::NodeId,
|
||||
@ -341,27 +342,30 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
|
||||
// Closures for extracting and manipulating the data and payload parts of
|
||||
// the fat pointer.
|
||||
let base = match k {
|
||||
&ty::UnsizeStruct(..) =>
|
||||
|bcx, val| PointerCast(bcx,
|
||||
val,
|
||||
type_of::type_of(bcx.ccx(), unsized_ty).ptr_to()),
|
||||
&ty::UnsizeLength(..) =>
|
||||
|bcx, val| GEPi(bcx, val, &[0u, 0u]),
|
||||
&ty::UnsizeVtable(..) =>
|
||||
|_bcx, val| PointerCast(bcx, val, Type::i8p(bcx.ccx()))
|
||||
};
|
||||
let info = |bcx, _val| unsized_info(bcx,
|
||||
k,
|
||||
expr.id,
|
||||
datum_ty,
|
||||
|t| ty::mk_rptr(tcx,
|
||||
ty::ReStatic,
|
||||
ty::mt{
|
||||
ty: t,
|
||||
mutbl: ast::MutImmutable
|
||||
}));
|
||||
into_fat_ptr(bcx, expr, datum, dest_ty, base, info)
|
||||
let info = |: bcx, _val| unsized_info(bcx,
|
||||
k,
|
||||
expr.id,
|
||||
datum_ty,
|
||||
|t| ty::mk_rptr(tcx,
|
||||
ty::ReStatic,
|
||||
ty::mt{
|
||||
ty: t,
|
||||
mutbl: ast::MutImmutable
|
||||
}));
|
||||
match *k {
|
||||
ty::UnsizeStruct(..) =>
|
||||
into_fat_ptr(bcx, expr, datum, dest_ty, |bcx, val| {
|
||||
PointerCast(bcx, val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
|
||||
}, info),
|
||||
ty::UnsizeLength(..) =>
|
||||
into_fat_ptr(bcx, expr, datum, dest_ty, |bcx, val| {
|
||||
GEPi(bcx, val, &[0u, 0u])
|
||||
}, info),
|
||||
ty::UnsizeVtable(..) =>
|
||||
into_fat_ptr(bcx, expr, datum, dest_ty, |_bcx, val| {
|
||||
PointerCast(bcx, val, Type::i8p(bcx.ccx()))
|
||||
}, info),
|
||||
}
|
||||
}
|
||||
|
||||
fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
@ -370,18 +374,21 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||
let tcx = bcx.tcx();
|
||||
let dest_ty = ty::close_type(tcx, datum.ty);
|
||||
let base = |bcx, val| Load(bcx, get_dataptr(bcx, val));
|
||||
let len = |bcx, val| Load(bcx, get_len(bcx, val));
|
||||
let base = |: bcx, val| Load(bcx, get_dataptr(bcx, val));
|
||||
let len = |: bcx, val| Load(bcx, get_len(bcx, val));
|
||||
into_fat_ptr(bcx, expr, datum, dest_ty, base, len)
|
||||
}
|
||||
|
||||
fn into_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
expr: &ast::Expr,
|
||||
datum: Datum<'tcx, Expr>,
|
||||
dest_ty: Ty<'tcx>,
|
||||
base: |Block<'blk, 'tcx>, ValueRef| -> ValueRef,
|
||||
info: |Block<'blk, 'tcx>, ValueRef| -> ValueRef)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||
fn into_fat_ptr<'blk, 'tcx, F, G>(bcx: Block<'blk, 'tcx>,
|
||||
expr: &ast::Expr,
|
||||
datum: Datum<'tcx, Expr>,
|
||||
dest_ty: Ty<'tcx>,
|
||||
base: F,
|
||||
info: G)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> where
|
||||
F: FnOnce(Block<'blk, 'tcx>, ValueRef) -> ValueRef,
|
||||
G: FnOnce(Block<'blk, 'tcx>, ValueRef) -> ValueRef,
|
||||
{
|
||||
let mut bcx = bcx;
|
||||
|
||||
// Arrange cleanup
|
||||
@ -659,17 +666,19 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
base: &ast::Expr,
|
||||
get_idx: |&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]| -> uint)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||
fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
base: &ast::Expr,
|
||||
get_idx: F)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> where
|
||||
F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]) -> uint,
|
||||
{
|
||||
let mut bcx = bcx;
|
||||
let _icx = push_ctxt("trans_rec_field");
|
||||
|
||||
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
|
||||
let bare_ty = ty::unopen_type(base_datum.ty);
|
||||
let repr = adt::represent_type(bcx.ccx(), bare_ty);
|
||||
with_field_tys(bcx.tcx(), bare_ty, None, |discr, field_tys| {
|
||||
with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
|
||||
let ix = get_idx(bcx.tcx(), field_tys);
|
||||
let d = base_datum.get_element(
|
||||
bcx,
|
||||
@ -1254,11 +1263,13 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
/// Helper for enumerating the field types of structs, enums, or records. The optional node ID here
|
||||
/// is the node ID of the path identifying the enum variant in use. If none, this cannot possibly
|
||||
/// an enum variant (so, if it is and `node_id_opt` is none, this function panics).
|
||||
pub fn with_field_tys<'tcx, R>(tcx: &ty::ctxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
node_id_opt: Option<ast::NodeId>,
|
||||
op: |ty::Disr, (&[ty::field<'tcx>])| -> R)
|
||||
-> R {
|
||||
pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
node_id_opt: Option<ast::NodeId>,
|
||||
op: F)
|
||||
-> R where
|
||||
F: FnOnce(ty::Disr, &[ty::field<'tcx>]) -> R,
|
||||
{
|
||||
match ty.sty {
|
||||
ty::ty_struct(did, ref substs) => {
|
||||
op(0, struct_fields(tcx, did, substs).as_slice())
|
||||
|
Loading…
x
Reference in New Issue
Block a user