Skip to content

[decompiler] New testing framework and enable recompilation evaluation #17099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: jun/astfier-opt-enhancement
Choose a base branch
from

Conversation

junxzm1990
Copy link
Contributor

@junxzm1990 junxzm1990 commented Jul 18, 2025

Description

This PR upgrade the decompiler testing framework to allow configurable compilation, decompilation, and testing.

It also enables testing of recompilation of decompiled code.

How Has This Been Tested?

  • Existing decompiler test cases

Type of Change

  • New feature
  • Bug fix
  • Breaking change
  • Performance improvement
  • Refactoring
  • Dependency update
  • Documentation update
  • Tests

Which Components or Systems Does This Change Impact?

  • Validator Node
  • Full Node (API, Indexer, etc.)
  • Move/Aptos Virtual Machine
  • Aptos Framework
  • Aptos CLI/SDK
  • Developer Infrastructure
  • Move Compiler
  • Other (Move Decompiler)

Copy link
Contributor Author

junxzm1990 commented Jul 18, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@junxzm1990 junxzm1990 changed the title update test case [decompiler] Improve testing framework and fix control flow recovery bugs Jul 18, 2025
@junxzm1990 junxzm1990 changed the title [decompiler] Improve testing framework and fix control flow recovery bugs [decompiler] New testing framework Jul 18, 2025
@junxzm1990 junxzm1990 changed the title [decompiler] New testing framework [decompiler] New testing framework and enable recompilation evaluation Jul 18, 2025
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch 4 times, most recently from f383b1a to 90d14a9 Compare July 18, 2025 05:46
@junxzm1990 junxzm1990 requested review from Copilot, wrwg, vineethk, rahxephon89 and JakeSilverman and removed request for Copilot July 18, 2025 05:46
@junxzm1990 junxzm1990 marked this pull request as ready for review July 18, 2025 05:47
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR upgrades the Move decompiler testing framework to enable configurable compilation, decompilation, and testing workflows. The key enhancement is adding recompilation testing to verify that decompiled code can be successfully compiled again.

  • Replaces the old datatest-stable harness with a new flexible testing framework using libtest-mimic
  • Introduces configurable test levels (Decompile vs Recompile) with multiple test configurations
  • Adds recompilation validation that attempts to compile decompiled code and reports results

Reviewed Changes

Copilot reviewed 18 out of 32 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
testsuite.rs Complete rewrite of test framework with configurable testing pipeline and recompilation support
lib.rs Adds builder methods to Options struct for configuring decompiler behavior
Cargo.toml Adds new dependencies for the enhanced testing framework
*.exp files Updated baseline files showing recompilation test results
cfg_bugs.move New test case file for control flow recovery testing

}
}

/// Represent an instance of a decompiler. The decompiler can be run end-to-end operating
Copy link
Preview

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word 'Represent' should be 'Represents' to match the grammatical structure of the sentence.

Suggested change
/// Represent an instance of a decompiler. The decompiler can be run end-to-end operating
/// Represents an instance of a decompiler. The decompiler can be run end-to-end operating

Copilot uses AI. Check for mistakes.

Comment on lines +121 to +122
#[allow(clippy::declare_interior_mutable_const)]
const TEST_CONFIGS: Lazy<BTreeMap<&str, TestConfig>> = Lazy::new(|| {
Copy link
Preview

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The clippy attribute suggests potential issues with interior mutability. Consider using a different approach like std::sync::OnceLock or lazy initialization to avoid this warning.

Suggested change
#[allow(clippy::declare_interior_mutable_const)]
const TEST_CONFIGS: Lazy<BTreeMap<&str, TestConfig>> = Lazy::new(|| {
static TEST_CONFIGS: OnceLock<BTreeMap<&'static str, TestConfig>> = OnceLock::new();
fn initialize_test_configs() -> BTreeMap<&'static str, TestConfig> {

Copilot uses AI. Check for mistakes.

Comment on lines +188 to +192
configs.into_iter().map(|c| (c.name, c)).collect()
});

/// A function which gets a copy of a TestConfig by name.
#[allow(clippy::borrow_interior_mutable_const)]
Copy link
Preview

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Similar to the previous clippy warning, this suggests potential issues with borrowing interior mutable data. Consider refactoring to use a safer pattern.

Suggested change
configs.into_iter().map(|c| (c.name, c)).collect()
});
/// A function which gets a copy of a TestConfig by name.
#[allow(clippy::borrow_interior_mutable_const)]
configs.into_iter().map(|c| (c.name, c)).collect()
};
configs
};
/// A function which gets a copy of a TestConfig by name.

Copilot uses AI. Check for mistakes.

/// combination. This errors if not configuration is found for a given test path.
/// TODO: we may want to add some filters here based on env vars (like the prover does),
/// which allow e.g. to filter by configuration name.
#[allow(clippy::borrow_interior_mutable_const)]
Copy link
Preview

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This is the third instance of the same clippy warning. Consider consolidating the configuration management to avoid repeated suppression of this warning.

Suggested change
#[allow(clippy::borrow_interior_mutable_const)]

Copilot uses AI. Check for mistakes.

Comment on lines 287 to 296
fn recompile_decompiled_code(path: &Path, config: &TestConfig, decompiled_code: &str) -> String {
let temp_dir = tempdir().expect("temp dir creation for recompilation expected");
let temp_file_path = temp_dir
.path()
.join(path.file_name().expect("test case must have a file name"));
let mut temp_file = File::create(&temp_file_path)
.expect("temp file creation for saving decompiled code expected");
temp_file
.write_all(decompiled_code.as_bytes())
.expect("saving decompiled code for recompilation must succeed");
Copy link
Preview

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function performs file I/O operations that can fail but uses expect() for error handling. Consider returning Result<String, Error> to provide better error information when recompilation testing fails.

Suggested change
fn recompile_decompiled_code(path: &Path, config: &TestConfig, decompiled_code: &str) -> String {
let temp_dir = tempdir().expect("temp dir creation for recompilation expected");
let temp_file_path = temp_dir
.path()
.join(path.file_name().expect("test case must have a file name"));
let mut temp_file = File::create(&temp_file_path)
.expect("temp file creation for saving decompiled code expected");
temp_file
.write_all(decompiled_code.as_bytes())
.expect("saving decompiled code for recompilation must succeed");
fn recompile_decompiled_code(path: &Path, config: &TestConfig, decompiled_code: &str) -> anyhow::Result<String> {
let temp_dir = tempdir().map_err(|e| anyhow::anyhow!("Failed to create temp dir: {}", e))?;
let temp_file_path = temp_dir
.path()
.join(path.file_name().ok_or_else(|| anyhow::anyhow!("Test case must have a file name"))?);
let mut temp_file = File::create(&temp_file_path)
.map_err(|e| anyhow::anyhow!("Failed to create temp file: {}", e))?;
temp_file
.write_all(decompiled_code.as_bytes())
.map_err(|e| anyhow::anyhow!("Failed to write decompiled code to temp file: {}", e))?;

Copilot uses AI. Check for mistakes.

@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from 90d14a9 to 7b28956 Compare July 18, 2025 17:01
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from 7b28956 to 3ad7354 Compare July 21, 2025 17:16
@junxzm1990 junxzm1990 force-pushed the jun/astfier-opt-enhancement branch from 0d88c59 to ae6e4ab Compare July 22, 2025 03:16
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from 3ad7354 to 0bd67b8 Compare July 22, 2025 03:17
@junxzm1990 junxzm1990 force-pushed the jun/astfier-opt-enhancement branch from ae6e4ab to b3cbec9 Compare July 22, 2025 15:41
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from 0bd67b8 to 4a581e5 Compare July 22, 2025 15:41
@junxzm1990 junxzm1990 force-pushed the jun/astfier-opt-enhancement branch from b3cbec9 to bf03c95 Compare July 22, 2025 15:44
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from 4a581e5 to 6a1fdf6 Compare July 22, 2025 15:44
@junxzm1990 junxzm1990 force-pushed the jun/astfier-opt-enhancement branch from bf03c95 to 32167ce Compare July 22, 2025 15:48
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from 6a1fdf6 to be9f1c6 Compare July 22, 2025 15:48
@junxzm1990 junxzm1990 force-pushed the jun/astfier-opt-enhancement branch from 32167ce to d93a1a3 Compare July 22, 2025 15:50
Copy link
Contributor

@wrwg wrwg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach looks good for now, though we may want to refactor this and add it as a more general feature directly to the txn framework. No need to worry about this, I will look at this later for the assembler.

}
}

/// Represent an instance of a decompiler. The decompiler can be run end-to-end operating
/// on files, or incrementally without already deserialized modules and scripts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was meant to be 'with' instead of 'without'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, should be "with". Will fix!

@@ -70,3 +69,23 @@ module 0x99::noexit_loops {
loop continue
}
}

--- unable to recompile the decompiled code:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a bug for this? Could also reuse a cover bug which we mention by bug number in noexit_loops.move. Those things can otherwise easily get forgotten in the noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have tracked those issues, and I am fixing them at this point.

@@ -71,3 +70,14 @@ module 0x1::fixed_point32 {
_t2
}
}

--- unable to recompile the decompiled code:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here and elswhere, lets use a cover bug to track? Also ok to not track if you feel comfortable with just remembering it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Contributor Author

This approach looks good for now, though we may want to refactor this and add it as a more general feature directly to the txn framework. No need to worry about this, I will look at this later for the assembler.

That would be much appreciated! I expect to fix all recompilation issues and then switch to transactional tests next week the latest.

@junxzm1990 junxzm1990 force-pushed the jun/astfier-opt-enhancement branch from d93a1a3 to c1dc305 Compare July 28, 2025 22:21
@junxzm1990 junxzm1990 force-pushed the jun/fix-decompiled-return branch from f1f7dc9 to 636926d Compare July 28, 2025 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants