diff --git a/cli/liblisa-libcli/src/synthesize_encoding.rs b/cli/liblisa-libcli/src/synthesize_encoding.rs
index 133988c..44b8546 100644
--- a/cli/liblisa-libcli/src/synthesize_encoding.rs
+++ b/cli/liblisa-libcli/src/synthesize_encoding.rs
@@ -8,6 +8,9 @@ use liblisa::arch::Arch;
use liblisa::encoding::Encoding;
use liblisa::instr::Instruction;
use liblisa::oracle::Oracle;
+use liblisa::semantics::default::smtgen::{StorageLocations, Z3Model};
+use liblisa::smt::z3::Z3Solver;
+use liblisa::smt::{SmtBV, SmtSolver};
use liblisa_enc::infer_encoding;
use liblisa_synth::{
determine_overlapping_write_order, merge_semantics_into_encoding, prepare_templates, DefaultTreeTemplateSynthesizer, Output,
@@ -57,6 +60,16 @@ pub struct SynthesizeEncodingCommand {
_phantom: PhantomData,
}
+fn shortest_smt<'ctx, S: SmtSolver<'ctx>>(smt: S::BV) -> String {
+ let simplified_str = smt.clone().simplify().to_string();
+ let normal_str = smt.to_string();
+ if simplified_str.len() < normal_str.len() {
+ simplified_str
+ } else {
+ normal_str
+ }
+}
+
impl SimpleCommand for SynthesizeEncodingCommand {
type Setup = Encoding;
@@ -129,13 +142,42 @@ impl SimpleCommand for SynthesizeEncodingCommand {
}
if self.print_smt {
- for df in semantics.dataflows.output_dataflows() {
- if let Some(_computation) = &df.computation {
- todo!("Use Z3 codegen instead");
- // let smt = codegen_computation(&mut SmtCodeGen::new(), computation);
- // println!("%{:?}: {smt}", df.target());
+ Z3Solver::with_thread_local(Duration::from_secs(30), |mut context| {
+ let mut storage = StorageLocations::new(&mut context);
+ let model = Z3Model::of(&semantics, &mut storage, &mut context);
+ let concrete = model.compute_concrete_outputs(&semantics, &mut storage, &mut context);
+
+ println!();
+
+ for item in model.constraints() {
+ println!("constraint: {item}");
}
- }
+
+ for &index in concrete.intermediate_values_needed() {
+ let intermediate = &model.intermediate_outputs()[index];
+ if let Some(smt) = intermediate.smt() {
+ println!("intermediate: {:?} = {}", intermediate.name(), shortest_smt::(smt.clone()))
+ } else {
+ println!("intermediate: {:?} = ", intermediate.name())
+ }
+ }
+
+ println!();
+
+ for part_name in concrete.part_names().iter() {
+ println!("part: {:?} = {:?}", part_name.name(), part_name.smt())
+ }
+
+ println!();
+
+ for output in concrete.concrete_outputs().iter() {
+ if let Some(smt) = output.smt() {
+ println!("output: {:?} = {}", output.target(), shortest_smt::(smt.clone()))
+ } else {
+ println!("output: {:?} = ", output.target())
+ }
+ }
+ });
}
if self.print_json {