(
&mut self,
masm: &mut M,
context: &mut CodeGenContext<Emission>,
)
| 308 | } |
| 309 | |
| 310 | fn init<M: MacroAssembler>( |
| 311 | &mut self, |
| 312 | masm: &mut M, |
| 313 | context: &mut CodeGenContext<Emission>, |
| 314 | ) -> Result<()> { |
| 315 | self.calculate_stack_state(context, masm)?; |
| 316 | // If the block has stack results, immediately resolve the return area |
| 317 | // base. |
| 318 | if self.results::<M>()?.on_stack() { |
| 319 | let results_base = self.stack_state().target_offset; |
| 320 | self.results::<M>()?.set_ret_area(RetArea::sp(results_base)); |
| 321 | } |
| 322 | |
| 323 | if self.is_if() || self.is_loop() { |
| 324 | // Preemptively handle block params as results so that the params |
| 325 | // are correctly placed in memory. This is especially |
| 326 | // important for control flow joins with empty blocks: |
| 327 | // |
| 328 | //(module |
| 329 | // (func (export "params") (param i32) (result i32) |
| 330 | // (i32.const 2) |
| 331 | // (if (param i32) (result i32) (local.get 0) |
| 332 | // (then)) |
| 333 | // (i32.const 3) |
| 334 | // (i32.add) |
| 335 | // ) |
| 336 | //) |
| 337 | let base_offset = self.stack_state().base_offset; |
| 338 | if self.params::<M>()?.on_stack() { |
| 339 | let offset = base_offset.as_u32() + self.params::<M>()?.size(); |
| 340 | self.params::<M>()? |
| 341 | .set_ret_area(RetArea::sp(SPOffset::from_u32(offset))); |
| 342 | } |
| 343 | Self::top_abi_results_impl( |
| 344 | self.params::<M>()?, |
| 345 | context, |
| 346 | masm, |
| 347 | |params: &ABIResults, _, _| Ok(params.ret_area().copied()), |
| 348 | )?; |
| 349 | } |
| 350 | Ok(()) |
| 351 | } |
| 352 | |
| 353 | /// Calculates the [StackState] of the block. |
| 354 | fn calculate_stack_state<M: MacroAssembler>( |
no test coverage detected