33use rustc:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
44use rustc:: mir:: visit:: * ;
55use rustc:: mir:: * ;
6- use rustc:: ty:: subst:: { InternalSubsts , Subst , SubstsRef } ;
6+ use rustc:: ty:: subst:: { InternalSubsts , Subst } ;
77use rustc:: ty:: { self , Instance , InstanceDef , ParamEnv , Ty , TyCtxt , TypeFoldable } ;
88use rustc_attr as attr;
9- use rustc_hir:: def_id:: DefId ;
109use rustc_index:: bit_set:: BitSet ;
1110use rustc_index:: vec:: { Idx , IndexVec } ;
1211use rustc_session:: config:: Sanitizer ;
@@ -29,8 +28,7 @@ pub struct Inline;
2928
3029#[ derive( Copy , Clone , Debug ) ]
3130struct CallSite < ' tcx > {
32- callee : DefId ,
33- substs : SubstsRef < ' tcx > ,
31+ callee : Instance < ' tcx > ,
3432 bb : BasicBlock ,
3533 source_info : SourceInfo ,
3634}
@@ -94,13 +92,19 @@ impl Inliner<'tcx> {
9492 local_change = false ;
9593 while let Some ( callsite) = callsites. pop_front ( ) {
9694 debug ! ( "checking whether to inline callsite {:?}" , callsite) ;
97- if !self . tcx . is_mir_available ( callsite. callee ) {
98- debug ! ( "checking whether to inline callsite {:?} - MIR unavailable" , callsite) ;
99- continue ;
95+
96+ if let InstanceDef :: Item ( callee_def_id) = callsite. callee . def {
97+ if !self . tcx . is_mir_available ( callee_def_id) {
98+ debug ! (
99+ "checking whether to inline callsite {:?} - MIR unavailable" ,
100+ callsite,
101+ ) ;
102+ continue ;
103+ }
100104 }
101105
102106 let self_node_id = self . tcx . hir ( ) . as_local_node_id ( self . source . def_id ( ) ) . unwrap ( ) ;
103- let callee_node_id = self . tcx . hir ( ) . as_local_node_id ( callsite. callee ) ;
107+ let callee_node_id = self . tcx . hir ( ) . as_local_node_id ( callsite. callee . def_id ( ) ) ;
104108
105109 let callee_body = if let Some ( callee_node_id) = callee_node_id {
106110 // Avoid a cycle here by only using `optimized_mir` only if we have
@@ -110,19 +114,21 @@ impl Inliner<'tcx> {
110114 if !self . tcx . dep_graph . is_fully_enabled ( )
111115 && self_node_id. as_u32 ( ) < callee_node_id. as_u32 ( )
112116 {
113- self . tcx . optimized_mir ( callsite. callee )
117+ self . tcx . instance_mir ( callsite. callee . def )
114118 } else {
115119 continue ;
116120 }
117121 } else {
118122 // This cannot result in a cycle since the callee MIR is from another crate
119123 // and is already optimized.
120- self . tcx . optimized_mir ( callsite. callee )
124+ self . tcx . instance_mir ( callsite. callee . def )
121125 } ;
122126
127+ let callee_body: & Body < ' tcx > = & * callee_body;
128+
123129 let callee_body = if self . consider_optimizing ( callsite, callee_body) {
124130 self . tcx . subst_and_normalize_erasing_regions (
125- & callsite. substs ,
131+ & callsite. callee . substs ,
126132 param_env,
127133 callee_body,
128134 )
@@ -183,18 +189,13 @@ impl Inliner<'tcx> {
183189 let terminator = bb_data. terminator ( ) ;
184190 if let TerminatorKind :: Call { func : ref op, .. } = terminator. kind {
185191 if let ty:: FnDef ( callee_def_id, substs) = op. ty ( caller_body, self . tcx ) . kind {
186- let instance = Instance :: resolve ( self . tcx , param_env, callee_def_id, substs) ?;
192+ let callee = Instance :: resolve ( self . tcx , param_env, callee_def_id, substs) ?;
187193
188- if let InstanceDef :: Virtual ( ..) = instance . def {
194+ if let InstanceDef :: Virtual ( ..) | InstanceDef :: Intrinsic ( _ ) = callee . def {
189195 return None ;
190196 }
191197
192- return Some ( CallSite {
193- callee : instance. def_id ( ) ,
194- substs : instance. substs ,
195- bb,
196- source_info : terminator. source_info ,
197- } ) ;
198+ return Some ( CallSite { callee, bb, source_info : terminator. source_info } ) ;
198199 }
199200 }
200201
@@ -219,7 +220,7 @@ impl Inliner<'tcx> {
219220 return false ;
220221 }
221222
222- let codegen_fn_attrs = tcx. codegen_fn_attrs ( callsite. callee ) ;
223+ let codegen_fn_attrs = tcx. codegen_fn_attrs ( callsite. callee . def_id ( ) ) ;
223224
224225 if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: TRACK_CALLER ) {
225226 debug ! ( "`#[track_caller]` present - not inlining" ) ;
@@ -264,8 +265,8 @@ impl Inliner<'tcx> {
264265 // Only inline local functions if they would be eligible for cross-crate
265266 // inlining. This is to ensure that the final crate doesn't have MIR that
266267 // reference unexported symbols
267- if callsite. callee . is_local ( ) {
268- if callsite. substs . non_erasable_generics ( ) . count ( ) == 0 && !hinted {
268+ if callsite. callee . def_id ( ) . is_local ( ) {
269+ if callsite. callee . substs . non_erasable_generics ( ) . count ( ) == 0 && !hinted {
269270 debug ! ( " callee is an exported function - not inlining" ) ;
270271 return false ;
271272 }
@@ -321,7 +322,7 @@ impl Inliner<'tcx> {
321322 work_list. push ( target) ;
322323 // If the location doesn't actually need dropping, treat it like
323324 // a regular goto.
324- let ty = location. ty ( callee_body, tcx) . subst ( tcx, callsite. substs ) . ty ;
325+ let ty = location. ty ( callee_body, tcx) . subst ( tcx, callsite. callee . substs ) . ty ;
325326 if ty. needs_drop ( tcx, param_env) {
326327 cost += CALL_PENALTY ;
327328 if let Some ( unwind) = unwind {
@@ -371,7 +372,7 @@ impl Inliner<'tcx> {
371372
372373 for v in callee_body. vars_and_temps_iter ( ) {
373374 let v = & callee_body. local_decls [ v] ;
374- let ty = v. ty . subst ( tcx, callsite. substs ) ;
375+ let ty = v. ty . subst ( tcx, callsite. callee . substs ) ;
375376 // Cost of the var is the size in machine-words, if we know
376377 // it.
377378 if let Some ( size) = type_size_of ( tcx, param_env, ty) {
@@ -399,7 +400,7 @@ impl Inliner<'tcx> {
399400 & self ,
400401 callsite : CallSite < ' tcx > ,
401402 caller_body : & mut BodyAndCache < ' tcx > ,
402- mut callee_body : BodyAndCache < ' tcx > ,
403+ mut callee_body : Body < ' tcx > ,
403404 ) -> bool {
404405 let terminator = caller_body[ callsite. bb ] . terminator . take ( ) . unwrap ( ) ;
405406 match terminator. kind {
@@ -501,6 +502,13 @@ impl Inliner<'tcx> {
501502 caller_body. var_debug_info . push ( var_debug_info) ;
502503 }
503504
505+ // HACK(eddyb) work around the `basic_blocks` field of `mir::Body`
506+ // being private, due to `BodyAndCache` implementing `DerefMut`
507+ // to `mir::Body` (which would allow bypassing `basic_blocks_mut`).
508+ // The only way to make `basic_blocks` public again would be to
509+ // remove that `DerefMut` impl and add more `*_mut` accessors.
510+ let mut callee_body = BodyAndCache :: new ( callee_body) ;
511+
504512 for ( bb, mut block) in callee_body. basic_blocks_mut ( ) . drain_enumerated ( ..) {
505513 integrator. visit_basic_block_data ( bb, & mut block) ;
506514 caller_body. basic_blocks_mut ( ) . push ( block) ;
@@ -554,7 +562,9 @@ impl Inliner<'tcx> {
554562 // tmp2 = tuple_tmp.2
555563 //
556564 // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
557- if tcx. is_closure ( callsite. callee ) {
565+ // FIXME(eddyb) make this check for `"rust-call"` ABI combined with
566+ // `callee_body.spread_arg == None`, instead of special-casing closures.
567+ if tcx. is_closure ( callsite. callee . def_id ( ) ) {
558568 let mut args = args. into_iter ( ) ;
559569 let self_ = self . create_temp_if_necessary ( args. next ( ) . unwrap ( ) , callsite, caller_body) ;
560570 let tuple = self . create_temp_if_necessary ( args. next ( ) . unwrap ( ) , callsite, caller_body) ;
0 commit comments