1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use crate::{
function_data_builder::FunctionDataBuilder,
function_target::FunctionData,
function_target_pipeline::{FunctionTargetProcessor, FunctionTargetsHolder},
stackless_bytecode::{Bytecode, Operation},
};
use move_model::{exp_generator::ExpGenerator, model::FunctionEnv};
use std::collections::BTreeSet;
pub struct DebugInstrumenter {}
impl DebugInstrumenter {
pub fn new() -> Box<Self> {
Box::new(Self {})
}
}
impl FunctionTargetProcessor for DebugInstrumenter {
fn process(
&self,
_targets: &mut FunctionTargetsHolder,
fun_env: &FunctionEnv<'_>,
data: FunctionData,
) -> FunctionData {
use Bytecode::*;
if fun_env.is_native() {
return data;
}
let mut builder = FunctionDataBuilder::new(fun_env, data);
let code = std::mem::take(&mut builder.data.code);
builder.set_loc(builder.fun_env.get_loc().at_start());
for i in 0..builder.fun_env.get_parameter_count() {
builder.emit_with(|id| Call(id, vec![], Operation::TraceLocal(i), vec![i], None));
}
for bc in code {
match &bc {
Ret(id, locals) => {
builder.set_loc_from_attr(*id);
for (i, l) in locals.iter().enumerate() {
builder.emit_with(|id| {
Call(id, vec![], Operation::TraceReturn(i), vec![*l], None)
});
}
builder.emit(bc);
}
Abort(id, l) => {
builder.set_loc_from_attr(*id);
builder.emit_with(|id| Call(id, vec![], Operation::TraceAbort, vec![*l], None));
builder.emit(bc);
}
Call(_, _, Operation::WriteRef, srcs, _) if srcs[0] < fun_env.get_local_count() => {
builder.set_loc_from_attr(bc.get_attr_id());
builder.emit(bc.clone());
builder.emit_with(|id| {
Call(
id,
vec![],
Operation::TraceLocal(srcs[0]),
vec![srcs[0]],
None,
)
});
}
_ => {
builder.set_loc_from_attr(bc.get_attr_id());
builder.emit(bc.clone());
let (val_targets, mut_targets) = bc.modifies(&builder.get_target());
let affected_variables: BTreeSet<_> = val_targets
.into_iter()
.chain(mut_targets.into_iter().map(|(idx, _)| idx))
.collect();
for idx in affected_variables {
if idx < fun_env.get_local_count() {
builder.emit_with(|id| {
Call(id, vec![], Operation::TraceLocal(idx), vec![idx], None)
});
}
}
}
}
}
builder.data
}
fn name(&self) -> String {
"debug_instrumenter".to_string()
}
}