@@ -118,7 +118,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
118118 llargs : & [ ValueRef ] ,
119119 destination : Option < ( ReturnDest < ' tcx > , mir:: BasicBlock ) > ,
120120 cleanup : Option < mir:: BasicBlock >
121- | {
121+ | -> Option < ValueRef > {
122122 if let Some ( cleanup) = cleanup {
123123 let ret_bcx = if let Some ( ( _, target) ) = destination {
124124 this. blocks [ target]
@@ -137,6 +137,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
137137 this. set_debug_loc ( & ret_bcx, terminator. source_info ) ;
138138 this. store_return ( & ret_bcx, ret_dest, & fn_ty. ret , invokeret) ;
139139 }
140+
141+ None
140142 } else {
141143 let llret = bcx. call ( fn_ptr, & llargs, cleanup_bundle) ;
142144 fn_ty. apply_attrs_callsite ( llret) ;
@@ -154,6 +156,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
154156 } else {
155157 bcx. unreachable ( ) ;
156158 }
159+
160+ Some ( llret)
157161 }
158162 } ;
159163
@@ -209,9 +213,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
209213 mir:: TerminatorKind :: Return => {
210214 let llval = match self . fn_ty . ret . mode {
211215 PassMode :: Ignore | PassMode :: Indirect ( _) => {
212- bcx. ret_void ( ) ;
213- return ;
214- }
216+ bcx. ret_void ( ) ;
217+ return ;
218+ }
215219
216220 PassMode :: Direct ( _) | PassMode :: Pair ( ..) => {
217221 let op = self . trans_consume ( & bcx, & mir:: Place :: Local ( mir:: RETURN_PLACE ) ) ;
@@ -224,27 +228,27 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
224228
225229 PassMode :: Cast ( cast_ty) => {
226230 let op = match self . locals [ mir:: RETURN_PLACE ] {
227- LocalRef :: Operand ( Some ( op) ) => op,
228- LocalRef :: Operand ( None ) => bug ! ( "use of return before def" ) ,
231+ LocalRef :: Operand ( Some ( op) ) => op,
232+ LocalRef :: Operand ( None ) => bug ! ( "use of return before def" ) ,
229233 LocalRef :: Place ( tr_place) => {
230- OperandRef {
234+ OperandRef {
231235 val : Ref ( tr_place. llval , tr_place. alignment ) ,
232236 layout : tr_place. layout
233- }
234237 }
235- } ;
236- let llslot = match op. val {
237- Immediate ( _) | Pair ( ..) => {
238+ }
239+ } ;
240+ let llslot = match op. val {
241+ Immediate ( _) | Pair ( ..) => {
238242 let scratch = PlaceRef :: alloca ( & bcx, self . fn_ty . ret . layout , "ret" ) ;
239243 op. val . store ( & bcx, scratch) ;
240244 scratch. llval
241- }
242- Ref ( llval, align) => {
243- assert_eq ! ( align, Alignment :: AbiAligned ,
245+ }
246+ Ref ( llval, align) => {
247+ assert_eq ! ( align, Alignment :: AbiAligned ,
244248 "return place is unaligned!" ) ;
245- llval
246- }
247- } ;
249+ llval
250+ }
251+ } ;
248252 bcx. load (
249253 bcx. pointercast ( llslot, cast_ty. llvm_type ( bcx. ccx ) . ptr_to ( ) ) ,
250254 Some ( self . fn_ty . ret . layout . align ) )
@@ -448,6 +452,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
448452 let sig = callee. layout . ty . fn_sig ( bcx. tcx ( ) ) ;
449453 let sig = bcx. tcx ( ) . erase_late_bound_regions_and_normalize ( & sig) ;
450454 let abi = sig. abi ;
455+ let notail = def. map ( |def| {
456+ def. attrs ( bcx. ccx . tcx ( ) )
457+ . iter ( )
458+ . any ( |attr| attr. check_name ( "notail_when_called" ) )
459+ } ) . unwrap_or ( false ) ;
451460
452461 // Handle intrinsics old trans wants Expr's for, ourselves.
453462 let intrinsic = match def {
@@ -508,28 +517,28 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
508517 ReturnDest :: Store ( dst) => dst. llval ,
509518 ReturnDest :: DirectOperand ( _) =>
510519 bug ! ( "Cannot use direct operand with an intrinsic call" )
511- } ;
520+ } ;
512521
513522 let args: Vec < _ > = args. iter ( ) . enumerate ( ) . map ( |( i, arg) | {
514- // The indices passed to simd_shuffle* in the
515- // third argument must be constant. This is
516- // checked by const-qualification, which also
517- // promotes any complex rvalues to constants.
523+ // The indices passed to simd_shuffle* in the
524+ // third argument must be constant. This is
525+ // checked by const-qualification, which also
526+ // promotes any complex rvalues to constants.
518527 if i == 2 && intrinsic. unwrap ( ) . starts_with ( "simd_shuffle" ) {
519- match * arg {
528+ match * arg {
520529 mir:: Operand :: Copy ( _) |
521530 mir:: Operand :: Move ( _) => {
522- span_bug ! ( span, "shuffle indices must be constant" ) ;
523- }
524- mir:: Operand :: Constant ( ref constant) => {
525- let val = self . trans_constant ( & bcx, constant) ;
531+ span_bug ! ( span, "shuffle indices must be constant" ) ;
532+ }
533+ mir:: Operand :: Constant ( ref constant) => {
534+ let val = self . trans_constant ( & bcx, constant) ;
526535 return OperandRef {
527536 val : Immediate ( val. llval ) ,
528537 layout : bcx. ccx . layout_of ( val. ty )
529538 } ;
530- }
531539 }
532540 }
541+ }
533542
534543 self . trans_operand ( & bcx, arg)
535544 } ) . collect ( ) ;
@@ -597,9 +606,14 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
597606 _ => span_bug ! ( span, "no llfn for call" ) ,
598607 } ;
599608
600- do_call ( self , bcx, fn_ty, fn_ptr, & llargs,
609+ let llret = do_call ( self , bcx, fn_ty, fn_ptr, & llargs,
601610 destination. as_ref ( ) . map ( |& ( _, target) | ( ret_dest, target) ) ,
602611 cleanup) ;
612+ if notail {
613+ unsafe {
614+ llret. map ( |llret| llvm:: LLVMRustSetCallNoTail ( llret) ) ;
615+ }
616+ }
603617 }
604618 mir:: TerminatorKind :: GeneratorDrop |
605619 mir:: TerminatorKind :: Yield { .. } |
@@ -615,21 +629,21 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
615629 // Fill padding with undef value, where applicable.
616630 if let Some ( ty) = arg. pad {
617631 llargs. push ( C_undef ( ty. llvm_type ( bcx. ccx ) ) ) ;
618- }
632+ }
619633
620634 if arg. is_ignore ( ) {
621635 return ;
622- }
636+ }
623637
624638 if let PassMode :: Pair ( ..) = arg. mode {
625639 match op. val {
626640 Pair ( a, b) => {
627641 llargs. push ( a) ;
628642 llargs. push ( b) ;
629- return ;
630- }
631- _ => bug ! ( "trans_argument: {:?} invalid for pair arugment" , op)
643+ return ;
632644 }
645+ _ => bug ! ( "trans_argument: {:?} invalid for pair arugment" , op)
646+ }
633647 }
634648
635649 // Force by-ref if we have to load through a cast pointer.
@@ -640,10 +654,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
640654 let scratch = PlaceRef :: alloca ( bcx, arg. layout , "arg" ) ;
641655 op. val . store ( bcx, scratch) ;
642656 ( scratch. llval , Alignment :: AbiAligned , true )
643- }
657+ }
644658 _ => {
645659 ( op. immediate_or_packed_pair ( bcx) , Alignment :: AbiAligned , false )
646- }
660+ }
647661 }
648662 }
649663 Ref ( llval, align @ Alignment :: Packed ( _) ) if arg. is_indirect ( ) => {
@@ -674,8 +688,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
674688 if let layout:: Abi :: Scalar ( ref scalar) = arg. layout . abi {
675689 if scalar. is_bool ( ) {
676690 bcx. range_metadata ( llval, 0 ..2 ) ;
677- }
678- }
691+ }
692+ }
679693 // We store bools as i8 so we need to truncate to i1.
680694 llval = base:: to_immediate ( bcx, llval, arg. layout ) ;
681695 }
@@ -697,15 +711,15 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
697711 for i in 0 ..tuple. layout . fields . count ( ) {
698712 let field_ptr = tuple_ptr. project_field ( bcx, i) ;
699713 self . trans_argument ( bcx, field_ptr. load ( bcx) , llargs, & args[ i] ) ;
700- }
701- } else {
714+ }
715+ } else {
702716 // If the tuple is immediate, the elements are as well.
703717 for i in 0 ..tuple. layout . fields . count ( ) {
704718 let op = tuple. extract_field ( bcx, i) ;
705719 self . trans_argument ( bcx, op, llargs, & args[ i] ) ;
720+ }
721+ }
706722 }
707- }
708- }
709723
710724 fn get_personality_slot ( & mut self , bcx : & Builder < ' a , ' tcx > ) -> PlaceRef < ' tcx > {
711725 let ccx = bcx. ccx ;
0 commit comments