|
14 | 14 | //! and methods are represented as just a fn ptr and not a full |
15 | 15 | //! closure. |
16 | 16 |
|
17 | | -use llvm::{self, ValueRef, get_params}; |
| 17 | +use llvm::{self, ValueRef}; |
18 | 18 | use rustc::hir::def_id::DefId; |
19 | | -use rustc::ty::subst::{Substs, Subst}; |
20 | | -use abi::{Abi, FnType}; |
| 19 | +use rustc::ty::subst::Substs; |
21 | 20 | use attributes; |
22 | | -use builder::Builder; |
23 | 21 | use common::{self, CrateContext}; |
24 | | -use cleanup::CleanupScope; |
25 | | -use mir::lvalue::LvalueRef; |
26 | 22 | use monomorphize; |
27 | 23 | use consts; |
28 | 24 | use declare; |
29 | | -use value::Value; |
30 | 25 | use monomorphize::Instance; |
31 | | -use back::symbol_names::symbol_name; |
32 | 26 | use trans_item::TransItem; |
33 | 27 | use type_of; |
34 | | -use rustc::ty::{self, TypeFoldable}; |
35 | | -use std::iter; |
36 | | - |
37 | | -use mir::lvalue::Alignment; |
38 | | - |
39 | | -fn trans_fn_once_adapter_shim<'a, 'tcx>( |
40 | | - ccx: &'a CrateContext<'a, 'tcx>, |
41 | | - def_id: DefId, |
42 | | - substs: ty::ClosureSubsts<'tcx>, |
43 | | - method_instance: Instance<'tcx>, |
44 | | - llreffn: ValueRef) |
45 | | - -> ValueRef |
46 | | -{ |
47 | | - if let Some(&llfn) = ccx.instances().borrow().get(&method_instance) { |
48 | | - return llfn; |
49 | | - } |
50 | | - |
51 | | - debug!("trans_fn_once_adapter_shim(def_id={:?}, substs={:?}, llreffn={:?})", |
52 | | - def_id, substs, Value(llreffn)); |
53 | | - |
54 | | - let tcx = ccx.tcx(); |
55 | | - |
56 | | - // Find a version of the closure type. Substitute static for the |
57 | | - // region since it doesn't really matter. |
58 | | - let closure_ty = tcx.mk_closure_from_closure_substs(def_id, substs); |
59 | | - let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty); |
60 | | - |
61 | | - // Make a version with the type of by-ref closure. |
62 | | - let sig = tcx.closure_type(def_id).subst(tcx, substs.substs); |
63 | | - let sig = tcx.erase_late_bound_regions_and_normalize(&sig); |
64 | | - assert_eq!(sig.abi, Abi::RustCall); |
65 | | - let llref_fn_sig = tcx.mk_fn_sig( |
66 | | - iter::once(ref_closure_ty).chain(sig.inputs().iter().cloned()), |
67 | | - sig.output(), |
68 | | - sig.variadic, |
69 | | - sig.unsafety, |
70 | | - Abi::RustCall |
71 | | - ); |
72 | | - let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(llref_fn_sig)); |
73 | | - debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}", |
74 | | - llref_fn_ty); |
75 | | - |
76 | | - |
77 | | - // Make a version of the closure type with the same arguments, but |
78 | | - // with argument #0 being by value. |
79 | | - let sig = tcx.mk_fn_sig( |
80 | | - iter::once(closure_ty).chain(sig.inputs().iter().cloned()), |
81 | | - sig.output(), |
82 | | - sig.variadic, |
83 | | - sig.unsafety, |
84 | | - Abi::RustCall |
85 | | - ); |
86 | | - |
87 | | - let fn_ty = FnType::new(ccx, sig, &[]); |
88 | | - let llonce_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig)); |
89 | | - |
90 | | - // Create the by-value helper. |
91 | | - let function_name = symbol_name(method_instance, ccx.shared()); |
92 | | - let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty); |
93 | | - attributes::set_frame_pointer_elimination(ccx, lloncefn); |
94 | | - |
95 | | - let orig_fn_ty = fn_ty; |
96 | | - let mut bcx = Builder::new_block(ccx, lloncefn, "entry-block"); |
97 | | - |
98 | | - // the first argument (`self`) will be the (by value) closure env. |
99 | | - |
100 | | - let mut llargs = get_params(lloncefn); |
101 | | - let fn_ty = FnType::new(ccx, llref_fn_sig, &[]); |
102 | | - let self_idx = fn_ty.ret.is_indirect() as usize; |
103 | | - let env_arg = &orig_fn_ty.args[0]; |
104 | | - let env = if env_arg.is_indirect() { |
105 | | - LvalueRef::new_sized_ty(llargs[self_idx], closure_ty, Alignment::AbiAligned) |
106 | | - } else { |
107 | | - let scratch = LvalueRef::alloca(&bcx, closure_ty, "self"); |
108 | | - let mut llarg_idx = self_idx; |
109 | | - env_arg.store_fn_arg(&bcx, &mut llarg_idx, scratch.llval); |
110 | | - scratch |
111 | | - }; |
112 | | - |
113 | | - debug!("trans_fn_once_adapter_shim: env={:?}", env); |
114 | | - // Adjust llargs such that llargs[self_idx..] has the call arguments. |
115 | | - // For zero-sized closures that means sneaking in a new argument. |
116 | | - if env_arg.is_ignore() { |
117 | | - llargs.insert(self_idx, env.llval); |
118 | | - } else { |
119 | | - llargs[self_idx] = env.llval; |
120 | | - } |
121 | | - |
122 | | - // Call the by-ref closure body with `self` in a cleanup scope, |
123 | | - // to drop `self` when the body returns, or in case it unwinds. |
124 | | - let self_scope = CleanupScope::schedule_drop_mem(&bcx, env); |
125 | | - |
126 | | - let llret; |
127 | | - if let Some(landing_pad) = self_scope.landing_pad { |
128 | | - let normal_bcx = bcx.build_sibling_block("normal-return"); |
129 | | - llret = bcx.invoke(llreffn, &llargs[..], normal_bcx.llbb(), landing_pad, None); |
130 | | - bcx = normal_bcx; |
131 | | - } else { |
132 | | - llret = bcx.call(llreffn, &llargs[..], None); |
133 | | - } |
134 | | - fn_ty.apply_attrs_callsite(llret); |
135 | | - |
136 | | - if sig.output().is_never() { |
137 | | - bcx.unreachable(); |
138 | | - } else { |
139 | | - self_scope.trans(&bcx); |
140 | | - |
141 | | - if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() { |
142 | | - bcx.ret_void(); |
143 | | - } else { |
144 | | - bcx.ret(llret); |
145 | | - } |
146 | | - } |
147 | | - |
148 | | - ccx.instances().borrow_mut().insert(method_instance, lloncefn); |
149 | | - |
150 | | - lloncefn |
151 | | -} |
152 | | - |
| 28 | +use rustc::ty::TypeFoldable; |
153 | 29 |
|
154 | 30 | /// Translates a reference to a fn/method item, monomorphizing and |
155 | 31 | /// inlining as it goes. |
156 | 32 | /// |
157 | 33 | /// # Parameters |
158 | 34 | /// |
159 | 35 | /// - `ccx`: the crate context |
160 | | -/// - `def_id`: def id of the fn or method item being referenced |
161 | | -/// - `substs`: values for each of the fn/method's parameters |
162 | | -fn do_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, |
163 | | - instance: Instance<'tcx>) |
164 | | - -> ValueRef |
| 36 | +/// - `instance`: the instance to be instantiated |
| 37 | +pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, |
| 38 | + instance: Instance<'tcx>) |
| 39 | + -> ValueRef |
165 | 40 | { |
166 | 41 | let tcx = ccx.tcx(); |
167 | 42 |
|
@@ -248,40 +123,6 @@ fn do_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, |
248 | 123 | llfn |
249 | 124 | } |
250 | 125 |
|
251 | | -pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, |
252 | | - instance: Instance<'tcx>) |
253 | | - -> ValueRef |
254 | | -{ |
255 | | - match instance.def { |
256 | | - ty::InstanceDef::Intrinsic(_) => { |
257 | | - bug!("intrinsic {} getting reified", instance) |
258 | | - } |
259 | | - ty::InstanceDef::ClosureOnceShim { .. } => { |
260 | | - let closure_ty = instance.substs.type_at(0); |
261 | | - let (closure_def_id, closure_substs) = match closure_ty.sty { |
262 | | - ty::TyClosure(def_id, substs) => (def_id, substs), |
263 | | - _ => bug!("bad closure instance {:?}", instance) |
264 | | - }; |
265 | | - |
266 | | - trans_fn_once_adapter_shim( |
267 | | - ccx, |
268 | | - closure_def_id, |
269 | | - closure_substs, |
270 | | - instance, |
271 | | - do_get_fn( |
272 | | - ccx, |
273 | | - Instance::new(closure_def_id, closure_substs.substs) |
274 | | - ) |
275 | | - ) |
276 | | - } |
277 | | - ty::InstanceDef::FnPtrShim(..) | |
278 | | - ty::InstanceDef::Item(..) | |
279 | | - ty::InstanceDef::Virtual(..) => { |
280 | | - do_get_fn(ccx, instance) |
281 | | - } |
282 | | - } |
283 | | -} |
284 | | - |
285 | 126 | pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, |
286 | 127 | def_id: DefId, |
287 | 128 | substs: &'tcx Substs<'tcx>) |
|
0 commit comments