MCPcopy Create free account
hub / github.com/Amanieu/regalloc3 / gen_block_insts

Method gen_block_insts

src/debug_utils/generic_function/arbitrary.rs:371–435  ·  view source on GitHub ↗

Generate the contents of a basic block. This should be called in CFG post-order so that uses come before definitions.

(&mut self, block: Block)

Source from the content-addressed store, hash-verified

369 /// This should be called in CFG post-order so that uses come before
370 /// definitions.
371 fn gen_block_insts(&mut self, block: Block) -> Result<()> {
372 // We generate instructions in reverse, starting with the terminator.
373 // This allows us to know exactly what values need to be defined later.
374 let mut num_insts = self.u.int_in_range(self.config.insts_per_block.clone())?;
375
376 // Set up outgoing blockparams if we have a single successor that itself
377 // has multiple predecessors.
378 if let [succ] = self.func.blocks[block].succs[..] {
379 if self.func.blocks[succ].preds.len() > 1 {
380 for idx in 0..self.func.blocks[succ].block_params_in.len() {
381 let bank = self.func.values[self.func.blocks[succ].block_params_in[idx]].bank;
382 // It's fine if this adds defs to the current block, we will
383 // increase num_insts below to ensure these have a defining
384 // instruction.
385 let value = self.get_value_for_use(bank, block, false)?;
386 self.func.blocks[block].block_params_out.push(value);
387 }
388
389 // Our terminator cannot have operands. Create an empty
390 // terminator now before adding any instructions.
391 self.block_insts[block].push(InstData {
392 operands: vec![],
393 clobbers: vec![],
394 block,
395 terminator_kind: Some(TerminatorKind::Jump),
396 is_pure: false,
397 });
398
399 // If there are values that need to be defined in this block for
400 // outgoing blockparams, make sure it has at least one
401 // instruction.
402 if num_insts == 0 && !self.defs_by_blocks[block].is_empty() {
403 num_insts = 1;
404 }
405 }
406 }
407
408 // We need a terminator instruction if an empty one wasn't created
409 // above. This one is allowed to have operands like a normal
410 // instruction.
411 if self.block_insts[block].is_empty() {
412 let is_ret = self.func.blocks[block].succs.is_empty();
413 let mut terminator = self.gen_inst(block, num_insts == 0, is_ret)?;
414 terminator.is_pure = false;
415 terminator.terminator_kind = Some(if is_ret {
416 TerminatorKind::Ret
417 } else {
418 TerminatorKind::Branch
419 });
420 self.block_insts[block].push(terminator);
421 }
422
423 // Generate a sequence of instructions in the block.
424 for idx in 0..num_insts {
425 // If this is the last instruction we generate (i.e. the first one
426 // in the block) then we need to ensure all definitions assigned to
427 // this block are actually processed.
428 let inst = self.gen_inst(block, idx == num_insts - 1, false)?;

Callers 1

arbitrary_with_configMethod · 0.80

Calls 7

cloneMethod · 0.80
get_value_for_useMethod · 0.80
pushMethod · 0.80
gen_instMethod · 0.80
gen_block_start_defsMethod · 0.80
lenMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected