Skip to content

Commit 90fe195

Browse files
authored
[move][move-compiler] Add debugging flags and support to the compiler (#17076)
## Description This introduces a `debug_print` macro to the compiler, plus adds some flags in HLIR. These are to enable reusable debugging in a concise, extensible way. Note that `debug_print` is currently feature-flagged so it only occurs when `debug_assertions` are enabled. ## Test plan Manually enabling the flags and running tests locally does the printing, but otherwise it does nothing. --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK:
1 parent f95d1a6 commit 90fe195

File tree

3 files changed

+179
-93
lines changed

3 files changed

+179
-93
lines changed

crates/move-compiler/src/hlir/match_compilation.rs

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
parser::ast::{BinOp_, DatatypeName, Field, VariantName},
1111
shared::{
1212
ast_debug::{AstDebug, AstWriter},
13-
format_oxford_list,
13+
debug_print, format_oxford_list,
1414
unique_map::UniqueMap,
1515
},
1616
typing::ast::{self as T, MatchArm_, MatchPattern, UnannotatedPat_ as TP},
@@ -526,7 +526,6 @@ fn combine_pattern_fields(
526526
fn combine_recur(vec: &mut VVFields) -> Vec<VFields> {
527527
if let Some((f, (ndx, (ty, pats)))) = vec.pop() {
528528
let rec_fields = combine_recur(vec);
529-
// println!("rec fields: {:?}", rec_fields);
530529
let mut output = vec![];
531530
for entry in rec_fields {
532531
for pat in pats.clone() {
@@ -535,7 +534,6 @@ fn combine_pattern_fields(
535534
output.push(entry);
536535
}
537536
}
538-
// println!("output: {:?}", output);
539537
output
540538
} else {
541539
// Base case: a single match of no fields. We must have at least one, or else we would
@@ -544,11 +542,8 @@ fn combine_pattern_fields(
544542
}
545543
}
546544

547-
// println!("init fields: {:?}", fields);
548545
let mut vvfields: VVFields = fields.into_iter().collect::<Vec<_>>();
549-
// println!("vv fields: {:?}", vvfields);
550546
let output_vec = combine_recur(&mut vvfields);
551-
// println!("output: {:?}", output_vec);
552547
output_vec
553548
.into_iter()
554549
.map(|vfields| UniqueMap::maybe_from_iter(vfields.into_iter()).unwrap())
@@ -676,14 +671,12 @@ pub fn compile_match(
676671
};
677672

678673
while let Some((cur_id, init_fringe, matrix)) = work_queue.pop() {
679-
// println!("---\nwork queue entry: {}", cur_id);
680-
// println!("fringe:");
681-
// for elem in &init_fringe {
682-
// print!(" ");
683-
// elem.print_verbose();
684-
// }
685-
// println!("matrix:");
686-
// matrix.print_verbose();
674+
debug_print!(
675+
context.debug.match_work_queue,
676+
("work queue entry" => cur_id; fmt),
677+
(lines "fringe" => &init_fringe; sdbg),
678+
("matrix" => matrix; verbose)
679+
);
687680
let redefined: Option<WorkResult> =
688681
match compile_match_head(context, init_fringe.clone(), matrix) {
689682
MatchStep::Leaf(leaf) => compilation_results.insert(cur_id, WorkResult::Leaf(leaf)),
@@ -769,8 +762,10 @@ fn compile_match_head(
769762
mut fringe: VecDeque<FringeEntry>,
770763
mut matrix: PatternMatrix,
771764
) -> MatchStep {
772-
// println!("------\ncompilning with fringe:");
773-
// println!("{:#?}", fringe);
765+
debug_print!(
766+
context.debug.match_specialization,
767+
("-----\ncompiling with fringe dueue entry" => fringe; dbg)
768+
);
774769
if matrix.is_empty() {
775770
MatchStep::Failure
776771
} else if let Some(leaf) = matrix.wild_arm_opt(&fringe) {
@@ -785,12 +780,13 @@ fn compile_match_head(
785780
let mut arms = BTreeMap::new();
786781
for lit in lits {
787782
let lit_loc = lit.loc;
788-
// println!("specializing to {:?}", lit);
783+
debug_print!(context.debug.match_specialization, ("specializing to" => lit ; fmt));
789784
let (mut new_binders, inner_matrix) = matrix.specialize_literal(&lit);
790-
// println!("binders: {:#?}", new_binders);
785+
debug_print!(
786+
context.debug.match_specialization,
787+
("binders" => &new_binders; dbg), ("specialized" => inner_matrix)
788+
);
791789
subject_binders.append(&mut new_binders);
792-
// println!("specialized:");
793-
// inner_matrix.print();
794790
ice_assert!(
795791
context.env,
796792
arms.insert(lit, inner_matrix).is_none(),
@@ -799,7 +795,7 @@ fn compile_match_head(
799795
);
800796
}
801797
let (mut new_binders, default) = matrix.specialize_default();
802-
// println!("default binders: {:#?}", new_binders);
798+
debug_print!(context.debug.match_specialization, ("default binders" => &new_binders; dbg));
803799
subject_binders.append(&mut new_binders);
804800
MatchStep::LiteralSwitch {
805801
subject,
@@ -813,12 +809,11 @@ fn compile_match_head(
813809
.pop_front()
814810
.expect("ICE empty fringe in match compilation");
815811
let mut subject_binders = vec![];
816-
// println!("------\nsubject:");
817-
// subject.print();
818-
// println!("--\ncompile match head:");
819-
// subject.print();
820-
// println!("--\nmatrix;");
821-
// matrix.print();
812+
debug_print!(
813+
context.debug.match_specialization,
814+
("subject" => subject),
815+
("matrix" => matrix)
816+
);
822817

823818
let (mident, datatype_name) = subject
824819
.ty
@@ -837,9 +832,8 @@ fn compile_match_head(
837832
}
838833

839834
let tyargs = subject.ty.value.type_arguments().unwrap().clone();
840-
// treat it as a head constructor
841-
// assert!(!ctors.is_empty());
842835

836+
// treat it as a head constructor
843837
let mut unmatched_variants = context
844838
.enum_variants(&mident, &datatype_name)
845839
.into_iter()
@@ -860,12 +854,13 @@ fn compile_match_head(
860854
.iter()
861855
.map(|(_, _, ty)| ty)
862856
.collect::<Vec<_>>();
863-
// println!("specializing to {:?}", ctor);
857+
debug_print!(context.debug.match_specialization, ("specializing to" => ctor; dbg));
864858
let (mut new_binders, inner_matrix) = matrix.specialize(context, &ctor, bind_tys);
865-
// println!("binders: {:#?}", new_binders);
859+
debug_print!(
860+
context.debug.match_specialization,
861+
("binders" => &new_binders; dbg), ("specialized" => inner_matrix)
862+
);
866863
subject_binders.append(&mut new_binders);
867-
// println!("specialized:");
868-
// inner_matrix.print();
869864
ice_assert!(
870865
context.env,
871866
arms.insert(ctor, (fringe_binders, inner_fringe, inner_matrix))
@@ -1717,11 +1712,10 @@ fn find_counterexample(
17171712
mident: ModuleIdent,
17181713
datatype_name: DatatypeName,
17191714
) -> Option<Vec<CounterExample>> {
1720-
// println!("matrix types:");
1721-
// for ty in &matrix.tys {
1722-
// ty.print_verbose();
1723-
// }
1724-
1715+
debug_print!(
1716+
context.debug.match_counterexample,
1717+
(lines "matrix types" => &matrix.tys; verbose)
1718+
);
17251719
// TODO: if we ever want to match against structs, this needs to behave differently
17261720
if context.is_struct(&mident, &datatype_name) {
17271721
let (_, default) = matrix.specialize_default();
@@ -1829,8 +1823,7 @@ fn find_counterexample(
18291823
arity: u32,
18301824
ndx: &mut u32,
18311825
) -> Option<Vec<CounterExample>> {
1832-
// println!("checking matrix");
1833-
// matrix.print_verbose();
1826+
debug_print!(context.debug.match_counterexample, ("checking matrix" => matrix; verbose));
18341827
let result = if matrix.patterns_empty() {
18351828
None
18361829
} else if let Some(ty) = matrix.tys.first() {
@@ -1863,21 +1856,17 @@ fn find_counterexample(
18631856
assert!(matrix.is_empty());
18641857
Some(make_wildcards(arity as usize))
18651858
};
1866-
// print!("result:");
1867-
// match result {
1868-
// Some(ref n) => println!("{:#?}", n),
1869-
// None => println!("NONE"),
1870-
// }
1871-
// println!();
1859+
debug_print!(context.debug.match_counterexample, (opt "result" => &result; sdbg));
18721860
result
18731861
}
18741862

18751863
let mut ndx = 0;
18761864
if let Some(mut counterexample) = find_counterexample(context, matrix, 1, &mut ndx) {
1877-
// println!("counterexamples: {}", counterexample.len());
1878-
// for ce in &counterexample {
1879-
// println!("{}", ce);
1880-
// }
1865+
debug_print!(
1866+
context.debug.match_counterexample,
1867+
("counterexamples #" => counterexample.len(); fmt),
1868+
(lines "counterexamples" => &counterexample; fmt)
1869+
);
18811870
assert!(counterexample.len() == 1);
18821871
let counterexample = counterexample.remove(0);
18831872
let msg = format!("Pattern '{}' not covered", counterexample);

crates/move-compiler/src/hlir/translate.rs

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,18 @@ type VariantFieldIndicies = UniqueMap<
122122

123123
type VariantPositionalMap =
124124
UniqueMap<ModuleIdent, UniqueMap<DatatypeName, UniqueMap<VariantName, bool>>>;
125-
pub struct Context<'env> {
125+
126+
pub(super) struct HLIRDebugFlags {
127+
pub(super) match_translation: bool,
128+
pub(super) match_variant_translation: bool,
129+
pub(super) match_specialization: bool,
130+
pub(super) match_counterexample: bool,
131+
pub(super) match_work_queue: bool,
132+
}
133+
134+
pub(super) struct Context<'env> {
126135
pub env: &'env mut CompilationEnv,
136+
pub debug: HLIRDebugFlags,
127137
current_package: Option<Symbol>,
128138
structs: UniqueMap<ModuleIdent, UniqueMap<DatatypeName, UniqueMap<Field, usize>>>,
129139
enum_variants: UniqueMap<ModuleIdent, UniqueMap<DatatypeName, Vec<VariantName>>>,
@@ -277,8 +287,16 @@ impl<'env> Context<'env> {
277287
&mdef.enums,
278288
);
279289
}
290+
let debug = HLIRDebugFlags {
291+
match_translation: false,
292+
match_variant_translation: false,
293+
match_specialization: false,
294+
match_counterexample: false,
295+
match_work_queue: false,
296+
};
280297
Context {
281298
env,
299+
debug,
282300
current_package: None,
283301
structs,
284302
enum_variants,
@@ -1027,28 +1045,16 @@ fn tail(
10271045
}
10281046
}
10291047

1030-
// FIXME: print is left intentionally for development.
1031-
// Remove before merging into main.
10321048
E::Match(subject, arms) => {
1033-
// println!("compiling match!");
1034-
// print!("subject:");
1035-
// subject.print_verbose();
1036-
// println!("\narms:");
1037-
// for arm in &arms.value {
1038-
// arm.value.print_verbose();
1039-
// }
1040-
// let compiled = match_compilation::compile_match(context, in_type, *subject, arms);
1041-
// println!("-----\ncompiled:");
1042-
// compiled.print();
1043-
// let result = tail(context, block, expected_type, compiled);
1044-
// println!("-----\nblock:");
1045-
// block.print();
1046-
// print!("result: ");
1047-
// result.clone().unwrap().print_verbose();
1048-
// result
1049-
1049+
debug_print!(context.debug.match_translation,
1050+
("subject" => subject),
1051+
(lines "arms" => &arms.value)
1052+
);
10501053
let compiled = match_compilation::compile_match(context, in_type, *subject, arms);
1051-
tail(context, block, expected_type, compiled)
1054+
debug_print!(context.debug.match_translation, ("compiled" => compiled));
1055+
let result = tail(context, block, expected_type, compiled);
1056+
debug_print!(context.debug.match_variant_translation, (opt "result" => &result));
1057+
result
10521058
}
10531059

10541060
E::VariantMatch(subject, enum_name, arms) => {
@@ -1377,19 +1383,16 @@ fn value(
13771383
}
13781384
}
13791385

1380-
// FIXME: print is left intentionally for development.
13811386
E::Match(subject, arms) => {
1382-
// println!("compiling match!");
1383-
// print!("subject:");
1384-
// subject.print_verbose();
1385-
// println!("\narms:");
1386-
// for arm in &arms.value {
1387-
// arm.value.print_verbose();
1388-
// }
1387+
debug_print!(context.debug.match_translation,
1388+
("subject" => subject),
1389+
(lines "arms" => &arms.value)
1390+
);
13891391
let compiled = match_compilation::compile_match(context, in_type, *subject, arms);
1390-
// println!("-----\ncompiled:");
1391-
// compiled.print_verbose();
1392-
value(context, block, None, compiled)
1392+
debug_print!(context.debug.match_translation, ("compiled" => compiled));
1393+
let result = value(context, block, None, compiled);
1394+
debug_print!(context.debug.match_variant_translation, ("result" => &result));
1395+
result
13931396
}
13941397

13951398
E::VariantMatch(subject, enum_name, arms) => {
@@ -2012,20 +2015,16 @@ fn statement(context: &mut Context, block: &mut Block, e: T::Exp) {
20122015
},
20132016
));
20142017
}
2015-
// FIXME: print is left intentionally for development.
20162018
E::Match(subject, arms) => {
2017-
// println!("compiling match!");
2018-
// print!("subject:");
2019-
// subject.print_verbose();
2020-
// println!("\narms:");
2021-
// for arm in &arms.value {
2022-
// arm.value.print_verbose();
2023-
// }
2019+
debug_print!(context.debug.match_translation,
2020+
("subject" => subject),
2021+
(lines "arms" => &arms.value)
2022+
);
20242023
let subject_type = subject.ty.clone();
20252024
let compiled = match_compilation::compile_match(context, &subject_type, *subject, arms);
2026-
// println!("-----\ncompiled:");
2027-
// compiled.print_verbose();
2028-
statement(context, block, compiled)
2025+
debug_print!(context.debug.match_translation, ("compiled" => compiled));
2026+
statement(context, block, compiled);
2027+
debug_print!(context.debug.match_variant_translation, (lines "block" => block));
20292028
}
20302029
E::VariantMatch(subject, enum_name, arms) => {
20312030
let subject = Box::new(value(context, block, None, *subject));

0 commit comments

Comments
 (0)