@@ -186,12 +186,12 @@ impl<'tcx> Translator<'tcx> {
186
186
let function_def_id =
187
187
extract_def_id_of_called_function_from_operand ( func, current_function. def_id , self . tcx ) ;
188
188
let function_name = self . tcx . def_path_str ( function_def_id) ;
189
+ let start_place = current_function. get_start_place_for_function_call ( ) ;
189
190
info ! ( "Encountered function call: {function_name}" ) ;
190
191
191
192
if is_panic_function ( & function_name) {
192
193
// Function call which starts an abnormal termination of the program.
193
194
// Non-recursive call for the translation process.
194
- let start_place = current_function. get_start_place_for_function_call ( ) ;
195
195
call_panic_function (
196
196
& start_place,
197
197
& self . program_panic ,
@@ -201,22 +201,63 @@ impl<'tcx> Translator<'tcx> {
201
201
return ;
202
202
}
203
203
204
- let Some ( return_block) = target else {
205
- // Call to a function which does not return (Return type: -> !).
206
- // Non-recursive call for the translation process.
207
- let start_place = current_function. get_start_place_for_function_call ( ) ;
208
- call_diverging_function ( & start_place, & function_name, & mut self . net ) ;
209
- return ;
210
- } ;
211
-
212
- let start_place = current_function. get_start_place_for_function_call ( ) ;
213
- let end_place =
214
- current_function. get_end_place_for_function_call ( return_block, & mut self . net ) ;
215
- let cleanup_place = if let rustc_middle:: mir:: UnwindAction :: Cleanup ( cleanup_block) = unwind
216
- {
217
- Some ( current_function. get_end_place_for_function_call ( cleanup_block, & mut self . net ) )
218
- } else {
219
- None
204
+ // Depending on whether a return or a unwind for the function are present,
205
+ // we have different possibilities for the function call end place and the (optional) cleanup place.
206
+ let ( end_place, cleanup_place) = match ( target, unwind) {
207
+ ( Some ( return_block) , rustc_middle:: mir:: UnwindAction :: Continue ) => {
208
+ // MIR function or foreign function calls without a cleanup block.
209
+ let end_place =
210
+ current_function. get_end_place_for_function_call ( return_block, & mut self . net ) ;
211
+ ( end_place, None )
212
+ }
213
+ ( Some ( return_block) , rustc_middle:: mir:: UnwindAction :: Cleanup ( cleanup_block) ) => {
214
+ // The usual foreign function call case.
215
+ let end_place =
216
+ current_function. get_end_place_for_function_call ( return_block, & mut self . net ) ;
217
+ let cleanup_place =
218
+ current_function. get_end_place_for_function_call ( cleanup_block, & mut self . net ) ;
219
+ ( end_place, Some ( cleanup_place) )
220
+ }
221
+ ( Some ( return_block) , rustc_middle:: mir:: UnwindAction :: Terminate ) => {
222
+ // Specific foreign function calls that terminate the program (abort).
223
+ let end_place =
224
+ current_function. get_end_place_for_function_call ( return_block, & mut self . net ) ;
225
+ // Connect cleanup to panic place
226
+ ( end_place, Some ( self . program_panic . clone ( ) ) )
227
+ }
228
+ ( None , rustc_middle:: mir:: UnwindAction :: Terminate ) => {
229
+ // Foreign function calls that simply terminate the program.
230
+ ( self . program_panic . clone ( ) , None )
231
+ }
232
+ ( None , rustc_middle:: mir:: UnwindAction :: Cleanup ( cleanup_block) ) => {
233
+ // A very special case seen in functions like `std::process::exit`
234
+ // where the return block is actually expressed as a cleanup.
235
+ // This needs to be modelled differently than a diverging function.
236
+ let end_place =
237
+ current_function. get_end_place_for_function_call ( cleanup_block, & mut self . net ) ;
238
+ ( end_place, None )
239
+ }
240
+ ( None , rustc_middle:: mir:: UnwindAction :: Continue ) => {
241
+ // Call to a function which does not return (Return type: -> !).
242
+ // Non-recursive call for the translation process.
243
+ call_diverging_function ( & start_place, & function_name, & mut self . net ) ;
244
+ return ;
245
+ }
246
+ ( Some ( return_block) , rustc_middle:: mir:: UnwindAction :: Unreachable ) => {
247
+ // Support the unreachable case simply by matching the cleanup place to the program end place.
248
+ // This is a compromise solution to avoid polluting the panic state with these extraneous states
249
+ // that are actually not reachable during execution.
250
+ let end_place =
251
+ current_function. get_end_place_for_function_call ( return_block, & mut self . net ) ;
252
+ // Connect cleanup to program end place.
253
+ ( end_place, Some ( self . program_end . clone ( ) ) )
254
+ }
255
+ ( None , rustc_middle:: mir:: UnwindAction :: Unreachable ) => {
256
+ // Support the unreachable case simply by matching the cleanup place to the program end place.
257
+ // This is a compromise solution to avoid polluting the panic state with these extraneous states
258
+ // that are actually not reachable during execution.
259
+ ( self . program_end . clone ( ) , None )
260
+ }
220
261
} ;
221
262
222
263
let function_call = FunctionCall :: new ( function_def_id, self . tcx ) ;
0 commit comments