Skip to content

Commit 173e806

Browse files
authored
feat: Add lifetime to pcodestore (#147)
* feat: parameterize pcodestore with a lifetime for borrowed ops * clippy
1 parent 5257a09 commit 173e806

File tree

9 files changed

+51
-33
lines changed

9 files changed

+51
-33
lines changed

jingle/src/analysis/cfg/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::analysis::pcode_store::PcodeStore;
1+
use crate::analysis::pcode_store::{PcodeOpRef, PcodeStore};
22
use crate::modeling::machine::cpu::concrete::ConcretePcodeAddress;
33
use jingle_sleigh::{PcodeOperation, SleighArchInfo};
44
pub use model::{CfgState, CfgStateModel, ModelTransition};
@@ -402,17 +402,31 @@ impl<N: CfgState, D: ModelTransition<N::Model>> PcodeCfg<N, D> {
402402
}
403403
}
404404

405-
impl<L: CfgState> PcodeStore for PcodeCfg<L, PcodeOperation> {
406-
fn get_pcode_op_at<'a, T: Borrow<ConcretePcodeAddress>>(
407-
&'a self,
405+
impl<'op, L: CfgState> PcodeStore<'op> for PcodeCfg<L, PcodeOperation> {
406+
fn get_pcode_op_at<T: Borrow<ConcretePcodeAddress>>(
407+
&'op self,
408408
addr: T,
409-
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'a>> {
409+
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'op>> {
410410
let addr = *addr.borrow();
411411
self.get_op_at_address(addr)
412412
.map(crate::analysis::pcode_store::PcodeOpRef::from)
413413
}
414414
}
415415

416+
impl<'op, L: CfgState> PcodeStore<'op> for PcodeCfg<L, PcodeOpRef<'op>> {
417+
fn get_pcode_op_at<T: Borrow<ConcretePcodeAddress>>(
418+
&'op self,
419+
addr: T,
420+
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'op>> {
421+
let addr = *addr.borrow();
422+
// The CFG stores `PcodeOpRef<'static>` values. We can return a borrowed
423+
// `PcodeOpRef<'op>` that references the inner operation without cloning.
424+
self.get_op_at_address(addr).map(|op_ref_static| {
425+
crate::analysis::pcode_store::PcodeOpRef::from(op_ref_static.as_ref())
426+
})
427+
}
428+
}
429+
416430
impl<N: CfgState> PcodeCfg<N, PcodeOperation> {
417431
pub fn basic_blocks(&self) -> PcodeCfg<N, Vec<PcodeOperation>> {
418432
use petgraph::visit::EdgeRef;

jingle/src/analysis/compound/state.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ macro_rules! named_tuple {
157157
$F: 'static,
158158
$( $T: 'static ),+
159159
{
160-
fn get_operation<'a, P: crate::analysis::pcode_store::PcodeStore + ?Sized>(
160+
fn get_operation<'op, P: crate::analysis::pcode_store::PcodeStore<'op> + ?Sized>(
161161
&self,
162-
t: &'a P,
163-
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'a>> {
162+
t: &'op P,
163+
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'op>> {
164164
self.$first_field.get_operation(t)
165165
}
166166

jingle/src/analysis/cpa/lattice/pcode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ impl AbstractState for PcodeAddressLattice {
175175
}
176176

177177
impl LocationState for PcodeAddressLattice {
178-
fn get_operation<'a, T: crate::analysis::pcode_store::PcodeStore + ?Sized>(
178+
fn get_operation<'a, T: crate::analysis::pcode_store::PcodeStore<'a> + ?Sized>(
179179
&self,
180180
t: &'a T,
181181
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'a>> {

jingle/src/analysis/cpa/lattice/simple.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ impl<S: AbstractState + PartialJoinSemiLattice> AbstractState for SimpleLattice<
8181
}
8282

8383
impl<S: LocationState + AbstractState + PartialJoinSemiLattice> LocationState for SimpleLattice<S> {
84-
fn get_operation<'a, T: crate::analysis::pcode_store::PcodeStore + ?Sized>(
84+
fn get_operation<'op, T: crate::analysis::pcode_store::PcodeStore<'op> + ?Sized>(
8585
&self,
86-
t: &'a T,
87-
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'a>> {
86+
t: &'op T,
87+
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'op>> {
8888
match self {
8989
SimpleLattice::Value(a) => a.get_operation(t),
9090
SimpleLattice::Top => None,

jingle/src/analysis/cpa/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ where
5858
/// p-code operation references returned by the `PcodeStore` (i.e. the store's
5959
/// borrow lifetime). The reducer type is instantiated for that same `'op`
6060
/// lifetime so it can accept `PcodeOpRef<'op>` without cloning.
61-
fn run_cpa<'op, I: Borrow<Self::State>, P: PcodeStore + ?Sized>(
61+
fn run_cpa<'op, I: Borrow<Self::State>, P: PcodeStore<'op> + ?Sized>(
6262
&self,
6363
initial: I,
6464
pcode_store: &'op P,

jingle/src/analysis/cpa/state.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ pub trait LocationState: AbstractState {
203203
/// `PcodeStore` reference only; the state (`&self`) is not required to be
204204
/// borrowed for the same lifetime. This allows callers to obtain an op
205205
/// tied to the store borrow without forcing the state to outlive that borrow.
206-
fn get_operation<'a, T: PcodeStore + ?Sized>(&self, t: &'a T) -> Option<PcodeOpRef<'a>>;
206+
fn get_operation<'op, T: PcodeStore<'op> + ?Sized>(&self, t: &'op T)
207+
-> Option<PcodeOpRef<'op>>;
207208
fn get_location(&self) -> Option<ConcretePcodeAddress>;
208209
}

jingle/src/analysis/location/basic/state.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ impl AbstractState for BasicLocationState {
164164
}
165165

166166
impl LocationState for BasicLocationState {
167-
fn get_operation<'a, T: crate::analysis::pcode_store::PcodeStore + ?Sized>(
167+
fn get_operation<'op, T: crate::analysis::pcode_store::PcodeStore<'op> + ?Sized>(
168168
&self,
169-
t: &'a T,
170-
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'a>> {
169+
t: &'op T,
170+
) -> Option<crate::analysis::pcode_store::PcodeOpRef<'op>> {
171171
self.inner.get_operation(t)
172172
}
173173

jingle/src/analysis/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ where
3232
/// The default implementation uses the standard CPA algorithm and delegates
3333
/// to `make_output` for any post-processing. Types can override this to provide
3434
/// custom run behavior.
35-
fn run<'op, T: PcodeStore + ?Sized, I: IntoState<Self>>(
35+
fn run<'op, T: PcodeStore<'op> + ?Sized, I: IntoState<Self>>(
3636
&self,
3737
store: &'op T,
3838
initial_state: I,
@@ -61,7 +61,7 @@ where
6161
{
6262
}
6363

64-
pub trait AnalyzableEntry: PcodeStore + EntryPoint + Sized {
64+
pub trait AnalyzableEntry: for<'op> PcodeStore<'op> + EntryPoint + Sized {
6565
fn run_analysis<'op, T: Analysis>(
6666
&'op self,
6767
t: T,
@@ -76,4 +76,4 @@ pub trait AnalyzableEntry: PcodeStore + EntryPoint + Sized {
7676
}
7777
}
7878

79-
impl<T: PcodeStore + EntryPoint> AnalyzableEntry for T {}
79+
impl<T: for<'op> PcodeStore<'op> + EntryPoint> AnalyzableEntry for T {}

jingle/src/analysis/pcode_store.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,25 +73,28 @@ impl<'a> Debug for PcodeOpRef<'a> {
7373

7474
/// A store of p-code operations.
7575
///
76-
/// Implementations return `Option<PcodeOpRef<'a>>`. Callers that only need to
76+
/// Implementations return `Option<PcodeOpRef<'op>>`. Callers that only need to
7777
/// observe/borrow the operation should use `op_ref.as_ref()` to get a `&PcodeOperation`.
7878
/// If an owned operation is required, clone via `.as_ref().clone()`.
79-
pub trait PcodeStore {
80-
fn get_pcode_op_at<'a, T: Borrow<ConcretePcodeAddress>>(
81-
&'a self,
79+
///
80+
/// The trait is lifetime-parameterized so stores can tie the returned operation
81+
/// reference lifetime to the borrow of the store, avoiding unnecessary cloning.
82+
pub trait PcodeStore<'op> {
83+
fn get_pcode_op_at<T: Borrow<ConcretePcodeAddress>>(
84+
&'op self,
8285
addr: T,
83-
) -> Option<PcodeOpRef<'a>>;
86+
) -> Option<PcodeOpRef<'op>>;
8487
}
8588

8689
pub trait EntryPoint {
8790
fn get_entry(&self) -> ConcretePcodeAddress;
8891
}
8992

90-
impl<'a> PcodeStore for LoadedSleighContext<'a> {
91-
fn get_pcode_op_at<'b, T: Borrow<ConcretePcodeAddress>>(
92-
&'b self,
93+
impl<'a> PcodeStore<'a> for LoadedSleighContext<'a> {
94+
fn get_pcode_op_at<T: Borrow<ConcretePcodeAddress>>(
95+
&'a self,
9396
addr: T,
94-
) -> Option<PcodeOpRef<'b>> {
97+
) -> Option<PcodeOpRef<'a>> {
9598
let addr = addr.borrow();
9699
// `instruction_at` produces an owned `Instruction` per call. Its `ops`
97100
// are owned inside that `Instruction`, so we cannot return references
@@ -105,11 +108,11 @@ impl<'a> PcodeStore for LoadedSleighContext<'a> {
105108
}
106109
}
107110

108-
impl<T: PcodeStore + ?Sized> PcodeStore for &T {
109-
fn get_pcode_op_at<'a, B: Borrow<ConcretePcodeAddress>>(
110-
&'a self,
111+
impl<'op, T: PcodeStore<'op> + ?Sized> PcodeStore<'op> for &T {
112+
fn get_pcode_op_at<B: Borrow<ConcretePcodeAddress>>(
113+
&'op self,
111114
addr: B,
112-
) -> Option<PcodeOpRef<'a>> {
115+
) -> Option<PcodeOpRef<'op>> {
113116
(*self).get_pcode_op_at(addr)
114117
}
115118
}

0 commit comments

Comments
 (0)