use std::sync::Arc;
use analyssa::{
events::EventLog,
host::{DirtySet, SsaStore},
ir::function::SsaFunction,
scheduling::SsaPassHost,
world::World,
PointerSize,
};
use crate::{
analysis::{CilTarget, MethodRef},
compiler::CompilerContext,
metadata::token::Token,
CilObject,
};
pub trait CilHost: SsaPassHost<CilTarget> {
fn assembly(&self) -> Option<Arc<CilObject>>;
fn ctx(&self) -> &CompilerContext;
}
impl World<CilTarget> for CompilerContext {
fn all_methods(&self) -> Vec<MethodRef> {
self.ssa_functions
.iter()
.map(|e| MethodRef::new(*e.key()))
.collect()
}
fn entry_points(&self) -> Vec<MethodRef> {
self.entry_points
.iter()
.map(|t| MethodRef::new(*t))
.collect()
}
fn callees(&self, method: &MethodRef) -> Vec<MethodRef> {
self.call_graph
.callees(method.0)
.into_iter()
.map(MethodRef::new)
.collect()
}
fn is_dead(&self, method: &MethodRef) -> bool {
self.dead_methods.contains(&method.0)
}
fn mark_dead(&self, method: &MethodRef) {
self.dead_methods.insert(method.0);
}
fn methods_reverse_topological(&self) -> Vec<MethodRef> {
CompilerContext::methods_reverse_topological(self)
.into_iter()
.map(MethodRef::new)
.collect()
}
}
impl SsaStore<CilTarget> for CompilerContext {
fn contains(&self, method: &MethodRef) -> bool {
self.ssa_functions.contains_key(&method.0)
}
fn take_ssa(&self, method: &MethodRef) -> Option<SsaFunction<CilTarget>> {
self.ssa_functions.remove(&method.0).map(|(_, ssa)| ssa)
}
fn insert_ssa(&self, method: MethodRef, ssa: SsaFunction<CilTarget>) {
self.ssa_functions.insert(method.0, ssa);
}
fn clone_ssa(&self, method: &MethodRef) -> Option<SsaFunction<CilTarget>> {
self.ssa_functions.get(&method.0).map(|r| r.clone())
}
fn iter_methods(&self) -> Vec<MethodRef> {
self.ssa_functions
.iter()
.map(|e| MethodRef::new(*e.key()))
.collect()
}
}
impl DirtySet<CilTarget> for CompilerContext {
fn mark_dirty(&self, method: &MethodRef) {
self.processing_state.mark_method_dirty(method.0);
}
fn is_dirty(&self, method: &MethodRef) -> bool {
self.processing_state.method_dirty.contains(&method.0)
}
fn dirty_snapshot(&self) -> Vec<MethodRef> {
self.processing_state
.method_dirty
.iter()
.map(|t| MethodRef::new(*t))
.collect()
}
fn clear_dirty_for(&self, method: &MethodRef) {
self.processing_state.mark_method_stable(method.0);
}
fn mark_processed(&self, method: &MethodRef) {
self.processed_methods.insert(method.0);
}
fn is_processed(&self, method: &MethodRef) -> bool {
self.processed_methods.contains(&method.0)
}
}
impl SsaPassHost<CilTarget> for CompilerContext {
fn events(&self) -> &EventLog<CilTarget> {
&self.events
}
fn ptr_size(&self) -> PointerSize {
match self.assembly() {
Some(asm) => PointerSize::from_is_64bit(asm.file().pe().is_64bit),
None => PointerSize::Bit64,
}
}
}
impl CilHost for CompilerContext {
fn assembly(&self) -> Option<Arc<CilObject>> {
Self::assembly(self)
}
fn ctx(&self) -> &CompilerContext {
self
}
}
#[allow(dead_code)]
fn _token_methodref_compat() {
let _: MethodRef = MethodRef::from(Token::new(0));
let _: Token = MethodRef::new(Token::new(0)).0;
}