@@ -23,6 +23,7 @@ use super::{CachedLlbb, FunctionCx, LocalRef};
2323use crate :: base:: { self , is_call_from_compiler_builtins_to_upstream_monomorphization} ;
2424use crate :: common:: { self , IntPredicate } ;
2525use crate :: errors:: CompilerBuiltinsCannotCall ;
26+ use crate :: mir:: retag;
2627use crate :: traits:: * ;
2728use crate :: { MemFlags , meth} ;
2829
@@ -263,6 +264,12 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
263264 bx. lifetime_end ( tmp, size) ;
264265 }
265266 fx. store_return ( bx, ret_dest, & fn_abi. ret , invokeret) ;
267+
268+ // If the return value has variants that needed to be retagged,
269+ // then we might be in a different basic block now.
270+ // Update the cached block for `target` to point to this new
271+ // block, where codegen will continue.
272+ fx. cached_llbbs [ target] = CachedLlbb :: Some ( bx. llbb ( ) ) ;
266273 }
267274 MergingSucc :: False
268275 } else {
@@ -1054,21 +1061,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10541061 let result_layout =
10551062 self . cx . layout_of ( self . monomorphized_place_ty ( destination. as_ref ( ) ) ) ;
10561063
1064+ let needs_retag = retag:: place_needs_retag ( & destination) ;
1065+
10571066 let return_dest = if result_layout. is_zst ( ) {
10581067 ReturnDest :: Nothing
10591068 } else if let Some ( index) = destination. as_local ( ) {
10601069 match self . locals [ index] {
1061- LocalRef :: Place ( dest) => ReturnDest :: Store ( dest) ,
1070+ LocalRef :: Place ( dest) => ReturnDest :: Store { dest, needs_retag } ,
10621071 LocalRef :: UnsizedPlace ( _) => bug ! ( "return type must be sized" ) ,
10631072 LocalRef :: PendingOperand => {
10641073 // Handle temporary places, specifically `Operand` ones, as
10651074 // they don't have `alloca`s.
1066- ReturnDest :: DirectOperand ( index)
1075+ ReturnDest :: DirectOperand { index, needs_retag }
10671076 }
10681077 LocalRef :: Operand ( _) => bug ! ( "place local already assigned to" ) ,
10691078 }
10701079 } else {
1071- ReturnDest :: Store ( self . codegen_place ( bx, destination. as_ref ( ) ) )
1080+ ReturnDest :: Store {
1081+ dest : self . codegen_place ( bx, destination. as_ref ( ) ) ,
1082+ needs_retag,
1083+ }
10721084 } ;
10731085
10741086 let args =
@@ -2097,6 +2109,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
20972109 if fn_ret. is_ignore ( ) {
20982110 return ReturnDest :: Nothing ;
20992111 }
2112+
2113+ let needs_retag = retag:: place_needs_retag ( & dest) ;
2114+
21002115 let dest = if let Some ( index) = dest. as_local ( ) {
21012116 match self . locals [ index] {
21022117 LocalRef :: Place ( dest) => dest,
@@ -2110,9 +2125,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
21102125 let tmp = PlaceRef :: alloca ( bx, fn_ret. layout ) ;
21112126 tmp. storage_live ( bx) ;
21122127 llargs. push ( tmp. val . llval ) ;
2113- ReturnDest :: IndirectOperand ( tmp, index)
2128+ ReturnDest :: IndirectOperand { tmp, index, needs_retag }
21142129 } else {
2115- ReturnDest :: DirectOperand ( index)
2130+ ReturnDest :: DirectOperand { index, needs_retag }
21162131 } ;
21172132 }
21182133 LocalRef :: Operand ( _) => {
@@ -2135,7 +2150,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
21352150 llargs. push ( dest. val . llval ) ;
21362151 ReturnDest :: Nothing
21372152 } else {
2138- ReturnDest :: Store ( dest)
2153+ ReturnDest :: Store { dest, needs_retag }
21392154 }
21402155 }
21412156
@@ -2148,19 +2163,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
21482163 llval : Bx :: Value ,
21492164 ) {
21502165 use self :: ReturnDest :: * ;
2151-
2166+ let retags_enabled = bx . tcx ( ) . sess . opts . unstable_opts . codegen_emit_retag . is_some ( ) ;
21522167 match dest {
21532168 Nothing => ( ) ,
2154- Store ( dst) => bx. store_arg ( ret_abi, llval, dst) ,
2155- IndirectOperand ( tmp, index) => {
2156- let op = bx. load_operand ( tmp) ;
2169+ Store { dest, needs_retag } => {
2170+ bx. store_arg ( ret_abi, llval, dest) ;
2171+ if retags_enabled && needs_retag {
2172+ self . codegen_retag_place ( bx, dest, false ) ;
2173+ }
2174+ }
2175+ IndirectOperand { tmp, index, needs_retag } => {
2176+ let mut op = bx. load_operand ( tmp) ;
2177+ if retags_enabled && needs_retag {
2178+ op = self . codegen_retag_operand ( bx, op, false ) ;
2179+ }
21572180 tmp. storage_dead ( bx) ;
21582181 self . overwrite_local ( index, LocalRef :: Operand ( op) ) ;
21592182 self . debug_introduce_local ( bx, index) ;
21602183 }
2161- DirectOperand ( index) => {
2184+ DirectOperand { index, needs_retag } => {
21622185 // If there is a cast, we have to store and reload.
2163- let op = if let PassMode :: Cast { .. } = ret_abi. mode {
2186+ let mut op = if let PassMode :: Cast { .. } = ret_abi. mode {
21642187 let tmp = PlaceRef :: alloca ( bx, ret_abi. layout ) ;
21652188 tmp. storage_live ( bx) ;
21662189 bx. store_arg ( ret_abi, llval, tmp) ;
@@ -2170,6 +2193,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
21702193 } else {
21712194 OperandRef :: from_immediate_or_packed_pair ( bx, llval, ret_abi. layout )
21722195 } ;
2196+ if retags_enabled && needs_retag {
2197+ op = self . codegen_retag_operand ( bx, op, false ) ;
2198+ }
21732199 self . overwrite_local ( index, LocalRef :: Operand ( op) ) ;
21742200 self . debug_introduce_local ( bx, index) ;
21752201 }
@@ -2181,11 +2207,28 @@ enum ReturnDest<'tcx, V> {
21812207 /// Do nothing; the return value is indirect or ignored.
21822208 Nothing ,
21832209 /// Store the return value to the pointer.
2184- Store ( PlaceRef < ' tcx , V > ) ,
2210+ Store {
2211+ /// The destination place
2212+ dest : PlaceRef < ' tcx , V > ,
2213+ /// If this place needs to be retagged
2214+ needs_retag : bool ,
2215+ } ,
21852216 /// Store an indirect return value to an operand local place.
2186- IndirectOperand ( PlaceRef < ' tcx , V > , mir:: Local ) ,
2217+ IndirectOperand {
2218+ /// The temp place where the value is loaded from
2219+ tmp : PlaceRef < ' tcx , V > ,
2220+ /// The local that it is assigned to
2221+ index : mir:: Local ,
2222+ /// If this local needs to be retagged after the assignment
2223+ needs_retag : bool ,
2224+ } ,
21872225 /// Store a direct return value to an operand local place.
2188- DirectOperand ( mir:: Local ) ,
2226+ DirectOperand {
2227+ /// The destination local
2228+ index : mir:: Local ,
2229+ /// If this local needs to be retagged after the assignment.
2230+ needs_retag : bool ,
2231+ } ,
21892232}
21902233
21912234fn load_cast < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
0 commit comments