feat(mir): Phase 260 P2 - Delete BasicBlock.jump_args, unify to terminator SSOT
- Delete legacy jump_args/jump_args_layout fields from BasicBlock - Add return_env/return_env_layout for Return-specific metadata - Rename set_return_edge_args() → set_return_env() (clearer semantics) - Remove 8 legacy helper methods (has/get/set/clear legacy_jump_args) - Simplify set_jump/branch_with_edge_args (remove legacy sync, keep API) - Update edge_args_from_terminator() to terminator-only (no fallback) - Update 10+ JoinIR handler/test sites to use new API This completes Phase 260 P0 → P2 migration: edge-args are now exclusively in terminator operands (Jump/Branch) or Return-specific metadata (renamed from legacy terminology). BREAKING: BasicBlock.jump_args field removed. Use terminator edge-args or block.return_env() for Return blocks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -92,13 +92,14 @@ pub struct BasicBlock {
|
||||
/// Is this block sealed? (all predecessors are known)
|
||||
pub sealed: bool,
|
||||
|
||||
/// Phase 246-EX: Jump args metadata for exit PHI construction
|
||||
/// Phase 260 P2: Return environment metadata
|
||||
/// Return has no edge-args operand, so we keep metadata for continuation.
|
||||
/// When a JoinIR Jump is converted to MIR Return, this field preserves
|
||||
/// all the Jump args (not just the first one) so that exit PHI can correctly
|
||||
/// merge carrier values from multiple exit paths.
|
||||
pub jump_args: Option<Vec<ValueId>>,
|
||||
/// Phase 260 P0: Layout for legacy jump_args (for consistency checks)
|
||||
pub jump_args_layout: Option<JumpArgsLayout>,
|
||||
pub return_env: Option<Vec<ValueId>>,
|
||||
/// Phase 260 P2: Layout for return environment
|
||||
pub return_env_layout: Option<JumpArgsLayout>,
|
||||
}
|
||||
|
||||
impl BasicBlock {
|
||||
@ -115,8 +116,8 @@ impl BasicBlock {
|
||||
effects: EffectMask::PURE,
|
||||
reachable: false,
|
||||
sealed: false,
|
||||
jump_args: None, // Phase 246-EX: No jump args by default
|
||||
jump_args_layout: None, // Phase 260 P0: Unknown by default
|
||||
return_env: None, // Phase 260 P2: No return env by default
|
||||
return_env_layout: None, // Phase 260 P2: Unknown by default
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,7 +237,7 @@ impl BasicBlock {
|
||||
..
|
||||
}) => vec![OutEdge {
|
||||
target,
|
||||
args: edge_args.clone().or_else(|| self.legacy_edge_args()),
|
||||
args: edge_args.clone(), // Phase 260 P2: No fallback, terminator SSOT
|
||||
}],
|
||||
_ => Vec::new(),
|
||||
}
|
||||
@ -250,59 +251,33 @@ impl BasicBlock {
|
||||
.and_then(|edge| edge.args)
|
||||
}
|
||||
|
||||
/// Set legacy jump args metadata (migration helper)
|
||||
pub fn set_legacy_jump_args(&mut self, values: Vec<ValueId>, layout: Option<JumpArgsLayout>) {
|
||||
self.jump_args = Some(values.clone());
|
||||
self.jump_args_layout = layout;
|
||||
if let (Some(layout), Some(MirInstruction::Jump { target, edge_args: None })) =
|
||||
(layout, self.terminator.clone())
|
||||
{
|
||||
let edge_args = EdgeArgs { layout, values };
|
||||
self.set_jump_with_edge_args(target, Some(edge_args));
|
||||
}
|
||||
}
|
||||
|
||||
/// Record edge-args for Return terminators (migration helper)
|
||||
/// Set Return environment metadata (Return-specific)
|
||||
///
|
||||
/// Return has no edge-args operand, so we keep this metadata for now.
|
||||
pub fn set_return_edge_args(&mut self, edge_args: EdgeArgs) {
|
||||
/// Return has no edge-args operand, so we keep this metadata for continuation.
|
||||
pub fn set_return_env(&mut self, env: EdgeArgs) {
|
||||
if !matches!(self.terminator, Some(MirInstruction::Return { .. })) {
|
||||
panic!("set_return_edge_args requires Return terminator");
|
||||
panic!("set_return_env requires Return terminator");
|
||||
}
|
||||
self.jump_args = Some(edge_args.values);
|
||||
self.jump_args_layout = Some(edge_args.layout);
|
||||
self.return_env = Some(env.values);
|
||||
self.return_env_layout = Some(env.layout);
|
||||
}
|
||||
|
||||
/// Clear legacy jump args metadata (migration helper)
|
||||
pub fn clear_legacy_jump_args(&mut self) {
|
||||
self.jump_args = None;
|
||||
self.jump_args_layout = None;
|
||||
/// Get Return environment metadata
|
||||
pub fn return_env(&self) -> Option<EdgeArgs> {
|
||||
if matches!(self.terminator, Some(MirInstruction::Return { .. })) {
|
||||
match (self.return_env.as_ref(), self.return_env_layout) {
|
||||
(Some(values), Some(layout)) => Some(EdgeArgs {
|
||||
layout,
|
||||
values: values.clone(),
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if legacy jump args metadata exists
|
||||
pub fn has_legacy_jump_args(&self) -> bool {
|
||||
self.jump_args.is_some()
|
||||
}
|
||||
|
||||
/// Access legacy jump args values (read-only, migration helper)
|
||||
pub fn legacy_jump_args_values(&self) -> Option<&[ValueId]> {
|
||||
self.jump_args.as_deref()
|
||||
}
|
||||
|
||||
/// Access legacy jump args layout (read-only, migration helper)
|
||||
pub fn legacy_jump_args_layout(&self) -> Option<JumpArgsLayout> {
|
||||
self.jump_args_layout
|
||||
}
|
||||
|
||||
/// Build edge args from legacy values with an explicit layout (migration helper)
|
||||
pub fn legacy_edge_args_with_layout(&self, layout: JumpArgsLayout) -> Option<EdgeArgs> {
|
||||
self.jump_args.as_ref().map(|values| EdgeArgs {
|
||||
layout,
|
||||
values: values.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Set jump terminator with edge args and legacy metadata (SSOT write helper)
|
||||
/// Set jump terminator with edge args (SSOT write helper)
|
||||
pub fn set_jump_with_edge_args(&mut self, target: BasicBlockId, edge_args: Option<EdgeArgs>) {
|
||||
let terminator = MirInstruction::Jump {
|
||||
target,
|
||||
@ -315,16 +290,10 @@ impl BasicBlock {
|
||||
self.effects = self.effects | terminator.effects();
|
||||
self.terminator = Some(terminator);
|
||||
self.terminator_span = Some(Span::unknown());
|
||||
if let Some(args) = edge_args {
|
||||
self.jump_args = Some(args.values.clone());
|
||||
self.jump_args_layout = Some(args.layout);
|
||||
} else {
|
||||
self.clear_legacy_jump_args();
|
||||
}
|
||||
self.update_successors_from_terminator();
|
||||
}
|
||||
|
||||
/// Set branch terminator with per-edge args (clears legacy metadata)
|
||||
/// Set branch terminator with per-edge args
|
||||
pub fn set_branch_with_edge_args(
|
||||
&mut self,
|
||||
condition: ValueId,
|
||||
@ -347,29 +316,16 @@ impl BasicBlock {
|
||||
self.effects = self.effects | terminator.effects();
|
||||
self.terminator = Some(terminator);
|
||||
self.terminator_span = Some(Span::unknown());
|
||||
self.clear_legacy_jump_args();
|
||||
self.update_successors_from_terminator();
|
||||
}
|
||||
|
||||
fn legacy_edge_args(&self) -> Option<EdgeArgs> {
|
||||
let values = self.jump_args.as_ref()?;
|
||||
let layout = self.jump_args_layout?;
|
||||
Some(EdgeArgs {
|
||||
layout,
|
||||
values: values.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get edge-args from the current terminator (migration helper)
|
||||
/// Get edge-args from the current terminator
|
||||
///
|
||||
/// Jump uses its edge-args operand when present, otherwise falls back to
|
||||
/// stored metadata. Return relies on stored metadata.
|
||||
/// Jump uses its edge-args operand. Return uses return_env metadata.
|
||||
pub fn edge_args_from_terminator(&self) -> Option<EdgeArgs> {
|
||||
match self.terminator {
|
||||
Some(MirInstruction::Jump { ref edge_args, .. }) => {
|
||||
edge_args.clone().or_else(|| self.legacy_edge_args())
|
||||
}
|
||||
Some(MirInstruction::Return { .. }) => self.legacy_edge_args(),
|
||||
Some(MirInstruction::Jump { ref edge_args, .. }) => edge_args.clone(),
|
||||
Some(MirInstruction::Return { .. }) => self.return_env(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,8 +744,8 @@ mod tests {
|
||||
.get(&entry)
|
||||
.expect("missing loop_body entry block");
|
||||
assert!(
|
||||
entry_block.has_legacy_jump_args(),
|
||||
"loop_body entry block must have legacy jump_args metadata in bridged MIR"
|
||||
entry_block.return_env().is_some(),
|
||||
"loop_body entry block must have return_env metadata in bridged MIR"
|
||||
);
|
||||
|
||||
// Loop-only (the routing path in real lowering): still must encode loop_step as a tail-call.
|
||||
|
||||
@ -198,8 +198,8 @@ where
|
||||
terminator,
|
||||
);
|
||||
if let Some(block) = mir_func.blocks.get_mut(¤t_block_id) {
|
||||
if block.terminator.is_some() && !block.has_legacy_jump_args() {
|
||||
block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
if matches!(block.terminator, Some(MirInstruction::Return { .. })) && block.return_env().is_none() {
|
||||
block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args.to_vec(),
|
||||
});
|
||||
@ -365,12 +365,10 @@ mod tests {
|
||||
_ => panic!("Expected Return terminator"),
|
||||
}
|
||||
|
||||
// Check legacy jump args metadata
|
||||
assert!(block.has_legacy_jump_args());
|
||||
let jump_args = block.legacy_jump_args_values().unwrap();
|
||||
let layout = block.legacy_jump_args_layout();
|
||||
assert_eq!(jump_args, &[ValueId(10), ValueId(20)]);
|
||||
assert_eq!(layout, Some(JumpArgsLayout::CarriersOnly));
|
||||
// Check return environment metadata
|
||||
let env = block.return_env().expect("Block should have return_env");
|
||||
assert_eq!(env.values, vec![ValueId(10), ValueId(20)]);
|
||||
assert_eq!(env.layout, JumpArgsLayout::CarriersOnly);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -221,7 +221,7 @@ where
|
||||
exit_block.set_terminator(MirInstruction::Return {
|
||||
value: Some(call_result_id),
|
||||
});
|
||||
exit_block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
exit_block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args.to_vec(),
|
||||
});
|
||||
@ -250,8 +250,8 @@ where
|
||||
|
||||
finalize_fn(mir_func, current_block_id, current_instructions, return_terminator);
|
||||
if let Some(block) = mir_func.blocks.get_mut(¤t_block_id) {
|
||||
if block.terminator.is_some() && !block.has_legacy_jump_args() {
|
||||
block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
if matches!(block.terminator, Some(MirInstruction::Return { .. })) && block.return_env().is_none() {
|
||||
block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args.to_vec(),
|
||||
});
|
||||
@ -391,12 +391,10 @@ mod tests {
|
||||
_ => panic!("Expected Return terminator"),
|
||||
}
|
||||
|
||||
// Check legacy jump args metadata
|
||||
assert!(block.has_legacy_jump_args());
|
||||
let jump_args = block.legacy_jump_args_values().unwrap();
|
||||
let layout = block.legacy_jump_args_layout();
|
||||
assert_eq!(jump_args, &[ValueId(10), ValueId(20)]);
|
||||
assert_eq!(layout, Some(JumpArgsLayout::CarriersOnly));
|
||||
// Check return environment metadata
|
||||
let env = block.return_env().expect("Block should have return_env");
|
||||
assert_eq!(env.values, vec![ValueId(10), ValueId(20)]);
|
||||
assert_eq!(env.layout, JumpArgsLayout::CarriersOnly);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -479,12 +477,10 @@ mod tests {
|
||||
_ => panic!("Expected Return terminator"),
|
||||
}
|
||||
|
||||
// Check legacy jump args metadata in exit block
|
||||
assert!(exit_block.has_legacy_jump_args());
|
||||
let jump_args = exit_block.legacy_jump_args_values().unwrap();
|
||||
let layout = exit_block.legacy_jump_args_layout();
|
||||
assert_eq!(jump_args, &[ValueId(1), ValueId(2)]);
|
||||
assert_eq!(layout, Some(JumpArgsLayout::CarriersOnly));
|
||||
// Check return environment metadata in exit block
|
||||
let env = exit_block.return_env().expect("Exit block should have return_env");
|
||||
assert_eq!(env.values, vec![ValueId(1), ValueId(2)]);
|
||||
assert_eq!(env.layout, JumpArgsLayout::CarriersOnly);
|
||||
|
||||
// Check continue block exists and is empty
|
||||
let continue_block = mir_func.blocks.get(&BasicBlockId(2)).unwrap();
|
||||
|
||||
@ -443,8 +443,8 @@ impl JoinIrBlockConverter {
|
||||
terminator,
|
||||
);
|
||||
if let Some(block) = mir_func.blocks.get_mut(&self.current_block_id) {
|
||||
if block.terminator.is_some() && !block.has_legacy_jump_args() {
|
||||
block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
if matches!(block.terminator, Some(MirInstruction::Return { .. })) && block.return_env().is_none() {
|
||||
block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args.to_vec(),
|
||||
});
|
||||
@ -521,7 +521,7 @@ impl JoinIrBlockConverter {
|
||||
});
|
||||
exit_block.instruction_spans.push(Span::unknown());
|
||||
exit_block.set_terminator(MirInstruction::Return { value: Some(call_result_id) });
|
||||
exit_block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
exit_block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args.to_vec(),
|
||||
});
|
||||
@ -557,8 +557,8 @@ impl JoinIrBlockConverter {
|
||||
return_terminator,
|
||||
);
|
||||
if let Some(block) = mir_func.blocks.get_mut(&self.current_block_id) {
|
||||
if block.terminator.is_some() && !block.has_legacy_jump_args() {
|
||||
block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
if matches!(block.terminator, Some(MirInstruction::Return { .. })) && block.return_env().is_none() {
|
||||
block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args.to_vec(),
|
||||
});
|
||||
|
||||
@ -422,7 +422,7 @@ fn build_exit_or_tail_branch(
|
||||
block.instructions.clear();
|
||||
block.instruction_spans.clear();
|
||||
block.set_terminator(MirInstruction::Return { value: ret_val });
|
||||
block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: env.to_vec(),
|
||||
});
|
||||
@ -484,7 +484,6 @@ fn finalize_block(
|
||||
target,
|
||||
edge_args: None,
|
||||
});
|
||||
block.clear_legacy_jump_args();
|
||||
}
|
||||
}
|
||||
MirInstruction::Branch {
|
||||
@ -501,22 +500,18 @@ fn finalize_block(
|
||||
else_bb,
|
||||
else_edge_args,
|
||||
);
|
||||
block.clear_legacy_jump_args();
|
||||
}
|
||||
MirInstruction::Return { .. } => {
|
||||
block.set_terminator(terminator);
|
||||
if let Some(args) = jump_args {
|
||||
block.set_return_edge_args(crate::mir::EdgeArgs {
|
||||
block.set_return_env(crate::mir::EdgeArgs {
|
||||
layout: JumpArgsLayout::CarriersOnly,
|
||||
values: args,
|
||||
});
|
||||
} else {
|
||||
block.clear_legacy_jump_args();
|
||||
}
|
||||
}
|
||||
other => {
|
||||
block.set_terminator(other);
|
||||
block.clear_legacy_jump_args();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user