Calculates the [StackState] of the block.
(
&mut self,
context: &mut CodeGenContext<Emission>,
masm: &mut M,
)
| 352 | |
| 353 | /// Calculates the [StackState] of the block. |
| 354 | fn calculate_stack_state<M: MacroAssembler>( |
| 355 | &mut self, |
| 356 | context: &mut CodeGenContext<Emission>, |
| 357 | masm: &mut M, |
| 358 | ) -> Result<()> { |
| 359 | use ControlStackFrame::*; |
| 360 | let sig = self.sig(); |
| 361 | // If the block type contains a full [ABISig], do not take into account |
| 362 | // the params, since these are the params of the function that is |
| 363 | // currently being compiled and the value stack doesn't currently |
| 364 | // contain any values anyway. |
| 365 | let param_count = if sig.ty.is_sig() { |
| 366 | 0 |
| 367 | } else { |
| 368 | sig.param_count() |
| 369 | }; |
| 370 | let return_count = sig.return_count(); |
| 371 | ensure!( |
| 372 | context.stack.len() >= param_count, |
| 373 | CodeGenError::missing_values_in_stack() |
| 374 | ); |
| 375 | let results_size = self.results::<M>()?.size(); |
| 376 | |
| 377 | // Save any live registers and locals. |
| 378 | context.spill(masm)?; |
| 379 | |
| 380 | let base_len = context.stack.len() - param_count; |
| 381 | let stack_consumed = context.stack.sizeof(param_count); |
| 382 | let current_sp = masm.sp_offset()?; |
| 383 | let base_offset = SPOffset::from_u32(current_sp.as_u32() - stack_consumed); |
| 384 | |
| 385 | match self { |
| 386 | If { stack_state, .. } | Block { stack_state, .. } | Loop { stack_state, .. } => { |
| 387 | stack_state.base_offset = base_offset; |
| 388 | stack_state.base_len = base_len; |
| 389 | stack_state.target_offset = SPOffset::from_u32(base_offset.as_u32() + results_size); |
| 390 | stack_state.target_len = base_len + return_count; |
| 391 | } |
| 392 | _ => {} |
| 393 | } |
| 394 | Ok(()) |
| 395 | } |
| 396 | |
| 397 | /// This function ensures that the state of the -- machine and value -- |
| 398 | /// stack is the right one when reaching a control frame branch in which |