use super::types::{ReferenceEdge, ReferenceNode, ReferenceType};
use crate::models::dag::DependencyGraph;
use crate::models::unified_ast::{AstDag, NodeKey};
use super::analysis::DeadCodeAnalyzer;
impl DeadCodeAnalyzer {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn build_reference_graph(&mut self, dag: &AstDag) {
let mut references = self.references.write();
let mut entry_points = self.entry_points.write();
for (idx, node) in dag.nodes.iter().enumerate() {
let node_key = idx as NodeKey;
let node_name = format!("node_{}_{:?}", idx, node.kind);
references.nodes.insert(
node_key,
ReferenceNode {
key: node_key,
name: node_name.clone(),
language: node.lang,
},
);
if node_name.contains("main")
|| node
.flags
.has(crate::models::unified_ast::NodeFlags::EXPORTED)
{
entry_points.insert(node_key);
}
if node.first_child != 0 && node.first_child < dag.nodes.len() as NodeKey {
references.edges.push(ReferenceEdge {
from: node_key,
to: node.first_child,
reference_type: ReferenceType::DirectCall,
confidence: 0.9,
});
}
if node.next_sibling != 0 && node.next_sibling < dag.nodes.len() as NodeKey {
references.edges.push(ReferenceEdge {
from: node_key,
to: node.next_sibling,
reference_type: ReferenceType::TypeReference,
confidence: 0.8,
});
}
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn resolve_dynamic_calls(&mut self) {
let references = self.references.read();
let _vtable_resolver = self.vtable_analysis.read();
for _edge in &references.edges {
}
}
#[inline]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn mark_reachable_vectorized(&mut self) {
#[cfg(feature = "simd")]
{
self.mark_reachable_trueno();
}
#[cfg(not(feature = "simd"))]
{
self.mark_reachable_scalar();
}
}
#[cfg(feature = "simd")]
fn mark_reachable_trueno(&mut self) {
use trueno::Vector;
let entry_points = self.entry_points.read().clone();
let mut reachable = self.reachability.write();
let references = self.references.read();
for &entry in &entry_points {
reachable.set(entry);
}
let mut changed = true;
while changed {
changed = false;
const BATCH_SIZE: usize = 256; for chunk in references.edges.chunks(BATCH_SIZE) {
for edge in chunk {
if reachable.is_set(edge.from) && !reachable.is_set(edge.to) {
reachable.set(edge.to);
changed = true;
}
}
}
}
let _reachable_count = reachable.count_set();
let _demo_vec = Vector::from_slice(&vec![1.0f32; 8]);
}
#[cfg(not(feature = "simd"))]
fn mark_reachable_scalar(&mut self) {
let entry_points = self.entry_points.read().clone();
let mut reachable = self.reachability.write();
let references = self.references.read();
for &entry in &entry_points {
reachable.set(entry);
}
let mut changed = true;
while changed {
changed = false;
for edge in &references.edges {
if reachable.is_set(edge.from) && !reachable.is_set(edge.to) {
reachable.set(edge.to);
changed = true;
}
}
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn add_entry_point(&mut self, node_key: NodeKey) {
self.entry_points.write().insert(node_key);
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn add_reference(&mut self, edge: ReferenceEdge) {
let mut references = self.references.write();
let edge_idx = references.edges.len();
references
.edge_index
.entry(edge.from)
.or_default()
.push(edge_idx);
references.edges.push(edge);
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn build_reference_graph_from_dep_graph(&mut self, dag: &DependencyGraph) {
let mut references = self.references.write();
let mut entry_points = self.entry_points.write();
for (node_id, node_info) in &dag.nodes {
let key = node_id.parse::<u32>().unwrap_or(0);
references.nodes.insert(
key,
ReferenceNode {
key,
name: node_info.label.clone(),
language: crate::models::unified_ast::Language::Rust, },
);
if node_info.label == "main"
|| node_info.label.starts_with("pub ")
|| node_info.node_type == crate::models::dag::NodeType::Function
&& node_info.label.contains("main")
|| node_info.file_path.contains("main.rs")
|| node_info.file_path.contains("lib.rs")
{
entry_points.insert(key);
}
}
for edge in &dag.edges {
let from_key = edge.from.parse::<u32>().unwrap_or(0);
let to_key = edge.to.parse::<u32>().unwrap_or(0);
let reference_type = match edge.edge_type {
crate::models::dag::EdgeType::Calls => ReferenceType::DirectCall,
crate::models::dag::EdgeType::Imports => ReferenceType::Import,
crate::models::dag::EdgeType::Inherits => ReferenceType::Inheritance,
crate::models::dag::EdgeType::Implements => ReferenceType::TypeReference,
crate::models::dag::EdgeType::Uses => ReferenceType::TypeReference,
};
references.edges.push(ReferenceEdge {
from: from_key,
to: to_key,
reference_type,
confidence: 0.95,
});
}
if entry_points.is_empty() && !dag.nodes.is_empty() {
for (idx, _) in dag.nodes.iter().take(5) {
if let Ok(key) = idx.parse::<u32>() {
entry_points.insert(key);
}
}
}
}
}