Return blocks from DropTree::build_mir

Rather than requiring the user to pass in a correctly sized blocks map.
This commit is contained in:
bjorn3
2025-03-11 15:33:37 +01:00
parent 961351c76c
commit c58c06a6f5

View File

@@ -305,27 +305,25 @@ impl DropTree {
} }
/// Builds the MIR for a given drop tree. /// Builds the MIR for a given drop tree.
///
/// `blocks` should have the same length as `self.drops`, and may have its
/// first value set to some already existing block.
fn build_mir<'tcx, T: DropTreeBuilder<'tcx>>( fn build_mir<'tcx, T: DropTreeBuilder<'tcx>>(
&mut self, &mut self,
cfg: &mut CFG<'tcx>, cfg: &mut CFG<'tcx>,
blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>, root_node: Option<BasicBlock>,
) { ) -> IndexVec<DropIdx, Option<BasicBlock>> {
debug!("DropTree::build_mir(drops = {:#?})", self); debug!("DropTree::build_mir(drops = {:#?})", self);
assert_eq!(blocks.len(), self.drops.len());
self.assign_blocks::<T>(cfg, blocks); let mut blocks = self.assign_blocks::<T>(cfg, root_node);
self.link_blocks(cfg, blocks) self.link_blocks(cfg, &mut blocks);
blocks
} }
/// Assign blocks for all of the drops in the drop tree that need them. /// Assign blocks for all of the drops in the drop tree that need them.
fn assign_blocks<'tcx, T: DropTreeBuilder<'tcx>>( fn assign_blocks<'tcx, T: DropTreeBuilder<'tcx>>(
&mut self, &mut self,
cfg: &mut CFG<'tcx>, cfg: &mut CFG<'tcx>,
blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>, root_node: Option<BasicBlock>,
) { ) -> IndexVec<DropIdx, Option<BasicBlock>> {
// StorageDead statements can share blocks with each other and also with // StorageDead statements can share blocks with each other and also with
// a Drop terminator. We iterate through the drops to find which drops // a Drop terminator. We iterate through the drops to find which drops
// need their own block. // need their own block.
@@ -342,8 +340,11 @@ impl DropTree {
Own, Own,
} }
let mut blocks = IndexVec::from_elem(None, &self.drops);
blocks[ROOT_NODE] = root_node;
let mut needs_block = IndexVec::from_elem(Block::None, &self.drops); let mut needs_block = IndexVec::from_elem(Block::None, &self.drops);
if blocks[ROOT_NODE].is_some() { if root_node.is_some() {
// In some cases (such as drops for `continue`) the root node // In some cases (such as drops for `continue`) the root node
// already has a block. In this case, make sure that we don't // already has a block. In this case, make sure that we don't
// override it. // override it.
@@ -385,6 +386,8 @@ impl DropTree {
debug!("assign_blocks: blocks = {:#?}", blocks); debug!("assign_blocks: blocks = {:#?}", blocks);
assert!(entry_points.is_empty()); assert!(entry_points.is_empty());
blocks
} }
fn link_blocks<'tcx>( fn link_blocks<'tcx>(
@@ -1574,10 +1577,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
span: Span, span: Span,
continue_block: Option<BasicBlock>, continue_block: Option<BasicBlock>,
) -> Option<BlockAnd<()>> { ) -> Option<BlockAnd<()>> {
let mut blocks = IndexVec::from_elem(None, &drops.drops); let blocks = drops.build_mir::<ExitScopes>(&mut self.cfg, continue_block);
blocks[ROOT_NODE] = continue_block;
drops.build_mir::<ExitScopes>(&mut self.cfg, &mut blocks);
let is_coroutine = self.coroutine.is_some(); let is_coroutine = self.coroutine.is_some();
// Link the exit drop tree to unwind drop tree. // Link the exit drop tree to unwind drop tree.
@@ -1633,8 +1633,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
let drops = &mut self.scopes.coroutine_drops; let drops = &mut self.scopes.coroutine_drops;
let cfg = &mut self.cfg; let cfg = &mut self.cfg;
let fn_span = self.fn_span; let fn_span = self.fn_span;
let mut blocks = IndexVec::from_elem(None, &drops.drops); let blocks = drops.build_mir::<CoroutineDrop>(cfg, None);
drops.build_mir::<CoroutineDrop>(cfg, &mut blocks);
if let Some(root_block) = blocks[ROOT_NODE] { if let Some(root_block) = blocks[ROOT_NODE] {
cfg.terminate( cfg.terminate(
root_block, root_block,
@@ -1670,9 +1669,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
fn_span: Span, fn_span: Span,
resume_block: &mut Option<BasicBlock>, resume_block: &mut Option<BasicBlock>,
) { ) {
let mut blocks = IndexVec::from_elem(None, &drops.drops); let blocks = drops.build_mir::<Unwind>(cfg, *resume_block);
blocks[ROOT_NODE] = *resume_block;
drops.build_mir::<Unwind>(cfg, &mut blocks);
if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) { if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) {
cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume); cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume);