@@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId;
9
9
use rustc:: mir:: {
10
10
AggregateKind , Constant , Location , Place , PlaceBase , Body , Operand , Rvalue , Local , UnOp ,
11
11
StatementKind , Statement , LocalKind , TerminatorKind , Terminator , ClearCrossCrate , SourceInfo ,
12
- BinOp , SourceScope , SourceScopeLocalData , LocalDecl , BasicBlock ,
12
+ BinOp , SourceScope , SourceScopeLocalData , LocalDecl , BasicBlock , RETURN_PLACE ,
13
13
} ;
14
14
use rustc:: mir:: visit:: {
15
15
Visitor , PlaceContext , MutatingUseContext , MutVisitor , NonMutatingUseContext ,
@@ -25,6 +25,7 @@ use rustc::ty::layout::{
25
25
LayoutOf , TyLayout , LayoutError , HasTyCtxt , TargetDataLayout , HasDataLayout ,
26
26
} ;
27
27
28
+ use crate :: rustc:: ty:: subst:: Subst ;
28
29
use crate :: interpret:: {
29
30
self , InterpCx , ScalarMaybeUndef , Immediate , OpTy ,
30
31
StackPopCleanup , LocalValue , LocalState , AllocId , Frame ,
@@ -269,6 +270,7 @@ struct ConstPropagator<'mir, 'tcx> {
269
270
param_env : ParamEnv < ' tcx > ,
270
271
source_scope_local_data : ClearCrossCrate < IndexVec < SourceScope , SourceScopeLocalData > > ,
271
272
local_decls : IndexVec < Local , LocalDecl < ' tcx > > ,
273
+ ret : Option < OpTy < ' tcx , ( ) > > ,
272
274
}
273
275
274
276
impl < ' mir , ' tcx > LayoutOf for ConstPropagator < ' mir , ' tcx > {
@@ -308,11 +310,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
308
310
let mut ecx = InterpCx :: new ( tcx. at ( span) , param_env, ConstPropMachine , ( ) ) ;
309
311
let can_const_prop = CanConstProp :: check ( body) ;
310
312
313
+ let substs = & InternalSubsts :: identity_for_item ( tcx, def_id) ;
314
+
315
+ let ret =
316
+ ecx
317
+ . layout_of ( body. return_ty ( ) . subst ( tcx, substs) )
318
+ . ok ( )
319
+ // Don't bother allocating memory for ZST types which have no values.
320
+ . filter ( |ret_layout| !ret_layout. is_zst ( ) )
321
+ . map ( |ret_layout| ecx. allocate ( ret_layout, MemoryKind :: Stack ) ) ;
322
+
311
323
ecx. push_stack_frame (
312
- Instance :: new ( def_id, & InternalSubsts :: identity_for_item ( tcx , def_id ) ) ,
324
+ Instance :: new ( def_id, substs ) ,
313
325
span,
314
326
dummy_body,
315
- None ,
327
+ ret . map ( Into :: into ) ,
316
328
StackPopCleanup :: None {
317
329
cleanup : false ,
318
330
} ,
@@ -327,6 +339,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
327
339
source_scope_local_data,
328
340
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
329
341
local_decls : body. local_decls . clone ( ) ,
342
+ ret : ret. map ( Into :: into) ,
330
343
}
331
344
}
332
345
@@ -335,6 +348,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
335
348
}
336
349
337
350
fn get_const ( & self , local : Local ) -> Option < Const < ' tcx > > {
351
+ if local == RETURN_PLACE {
352
+ // Try to read the return place as an immediate so that if it is representable as a
353
+ // scalar, we can handle it as such, but otherwise, just return the value as is.
354
+ return match self . ret . map ( |ret| self . ecx . try_read_immediate ( ret) ) {
355
+ Some ( Ok ( Ok ( imm) ) ) => Some ( imm. into ( ) ) ,
356
+ _ => self . ret ,
357
+ } ;
358
+ }
359
+
338
360
self . ecx . access_local ( self . ecx . frame ( ) , local, None ) . ok ( )
339
361
}
340
362
@@ -643,7 +665,8 @@ impl CanConstProp {
643
665
// lint for x != y
644
666
// FIXME(oli-obk): lint variables until they are used in a condition
645
667
// FIXME(oli-obk): lint if return value is constant
646
- * val = body. local_kind ( local) == LocalKind :: Temp ;
668
+ let local_kind = body. local_kind ( local) ;
669
+ * val = local_kind == LocalKind :: Temp || local_kind == LocalKind :: ReturnPointer ;
647
670
648
671
if !* val {
649
672
trace ! ( "local {:?} can't be propagated because it's not a temporary" , local) ;
@@ -731,7 +754,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
731
754
}
732
755
} else {
733
756
trace ! ( "can't propagate into {:?}" , local) ;
734
- self . remove_const ( local) ;
757
+ if local != RETURN_PLACE {
758
+ self . remove_const ( local) ;
759
+ }
735
760
}
736
761
}
737
762
}
0 commit comments