phase29an(p13): add cleanup facts scaffold and projections

This commit is contained in:
2025-12-30 03:38:46 +09:00
parent 5746477f40
commit 34ec46d13e
3 changed files with 62 additions and 6 deletions

View File

@ -23,6 +23,18 @@ pub(in crate::mir::builder) struct ExitMapFacts {
pub kinds_present: BTreeSet<ExitKindFacts>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(in crate::mir::builder) enum CleanupKindFacts {
Return,
Break,
Continue,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(in crate::mir::builder) struct CleanupFacts {
pub kinds_present: BTreeSet<CleanupKindFacts>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(in crate::mir::builder) struct LoopFeatureFacts {
pub exit_usage: ExitUsageFacts,
@ -34,8 +46,6 @@ pub(in crate::mir::builder) struct LoopFeatureFacts {
#[derive(Debug, Clone, PartialEq, Eq)]
pub(in crate::mir::builder) struct ValueJoinFacts;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(in crate::mir::builder) struct CleanupFacts;
pub(in crate::mir::builder) fn try_extract_loop_feature_facts(
body: &[ASTNode],

View File

@ -3,7 +3,7 @@
#![allow(dead_code)]
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
ExitKindFacts, ExitUsageFacts,
CleanupKindFacts, ExitKindFacts, ExitUsageFacts,
};
use crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonKind;
use crate::mir::builder::control_flow::plan::facts::LoopFacts;
@ -15,6 +15,7 @@ pub(in crate::mir::builder) struct CanonicalLoopFacts {
pub skeleton_kind: SkeletonKind,
pub exit_usage: ExitUsageFacts,
pub exit_kinds_present: BTreeSet<ExitKindFacts>,
pub cleanup_kinds_present: BTreeSet<CleanupKindFacts>,
}
pub(in crate::mir::builder) fn canonicalize_loop_facts(facts: LoopFacts) -> CanonicalLoopFacts {
@ -27,6 +28,12 @@ pub(in crate::mir::builder) fn canonicalize_loop_facts(facts: LoopFacts) -> Cano
.as_ref()
.map(|map| map.kinds_present.clone())
.unwrap_or_default(),
cleanup_kinds_present: facts
.features
.cleanup
.as_ref()
.map(|cleanup| cleanup.kinds_present.clone())
.unwrap_or_default(),
facts,
}
}
@ -36,7 +43,8 @@ mod tests {
use super::canonicalize_loop_facts;
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
ExitKindFacts, ExitMapFacts, ExitUsageFacts, LoopFeatureFacts,
CleanupFacts, CleanupKindFacts, ExitKindFacts, ExitMapFacts, ExitUsageFacts,
LoopFeatureFacts,
};
use crate::mir::builder::control_flow::plan::facts::loop_facts::LoopFacts;
use crate::mir::builder::control_flow::plan::facts::scan_shapes::{
@ -65,6 +73,8 @@ mod tests {
kinds_present.insert(ExitKindFacts::Break);
kinds_present.insert(ExitKindFacts::Continue);
kinds_present.insert(ExitKindFacts::Return);
let mut cleanup_kinds_present = BTreeSet::new();
cleanup_kinds_present.insert(CleanupKindFacts::Return);
let facts = LoopFacts {
condition_shape: ConditionShape::Unknown,
step_shape: StepShape::Unknown,
@ -79,7 +89,9 @@ mod tests {
},
exit_map: Some(ExitMapFacts { kinds_present }),
value_join: None,
cleanup: None,
cleanup: Some(CleanupFacts {
kinds_present: cleanup_kinds_present,
}),
},
scan_with_init: None,
split_scan: None,
@ -101,6 +113,10 @@ mod tests {
assert!(canonical.exit_kinds_present.contains(&ExitKindFacts::Break));
assert!(canonical.exit_kinds_present.contains(&ExitKindFacts::Continue));
assert!(canonical.exit_kinds_present.contains(&ExitKindFacts::Return));
assert_eq!(canonical.cleanup_kinds_present.len(), 1);
assert!(canonical
.cleanup_kinds_present
.contains(&CleanupKindFacts::Return));
}
#[test]
@ -125,6 +141,7 @@ mod tests {
};
let canonical = canonicalize_loop_facts(facts);
assert!(canonical.exit_kinds_present.is_empty());
assert!(canonical.cleanup_kinds_present.is_empty());
}
#[test]

View File

@ -5,7 +5,7 @@
use crate::ast::ASTNode;
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
ExitKindFacts, ExitUsageFacts,
CleanupKindFacts, ExitKindFacts, ExitUsageFacts,
};
use crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonKind;
use crate::mir::builder::control_flow::plan::normalize::CanonicalLoopFacts;
@ -62,6 +62,10 @@ pub(in crate::mir::builder) fn build_plan_from_facts_ctx(
let _skeleton_kind = infer_skeleton_kind(&facts);
let _exit_usage = infer_exit_usage(&facts);
debug_assert_cleanup_kinds_match_exit_kinds(
&facts.cleanup_kinds_present,
&facts.exit_kinds_present,
);
let mut candidates = CandidateSet::new();
@ -140,6 +144,31 @@ fn debug_assert_exit_usage_matches_plan(
) {
}
#[cfg(debug_assertions)]
fn debug_assert_cleanup_kinds_match_exit_kinds(
cleanup_kinds_present: &BTreeSet<CleanupKindFacts>,
exit_kinds_present: &BTreeSet<ExitKindFacts>,
) {
for cleanup_kind in cleanup_kinds_present {
let exit_kind = match cleanup_kind {
CleanupKindFacts::Return => ExitKindFacts::Return,
CleanupKindFacts::Break => ExitKindFacts::Break,
CleanupKindFacts::Continue => ExitKindFacts::Continue,
};
debug_assert!(
exit_kinds_present.contains(&exit_kind),
"cleanup kind requires matching exit kind presence"
);
}
}
#[cfg(not(debug_assertions))]
fn debug_assert_cleanup_kinds_match_exit_kinds(
_cleanup_kinds_present: &BTreeSet<CleanupKindFacts>,
_exit_kinds_present: &BTreeSet<ExitKindFacts>,
) {
}
fn push_scan_with_init(candidates: &mut CandidateSet, facts: &CanonicalLoopFacts) {
let Some(scan) = &facts.facts.scan_with_init else {
return;