Skip to content

Commit

Permalink
[solidity,llvm-context] Improve support for debugging the compiler (#32)
Browse files Browse the repository at this point in the history
Add option --recursive-process-input <filename> for use with
--recursive-process to specify the name of a file to use instead of
reading from stdin.

If --debug-output-dir is set, dump the file passed to the recursive
invocation of the compiler as a JSON file suitable for use with
--recursive-process-input.

These changes are intended to support debugging the compiler and are
only available with DEBUG builds.
  • Loading branch information
wpt967 authored Aug 23, 2024
1 parent 184d40d commit bb4a4dd
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 3 deletions.
5 changes: 5 additions & 0 deletions crates/llvm-context/src/debug_config/ir_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub enum IRType {
LLVM,
/// Whether to dump the assembly code.
Assembly,
/// Whether to jump JSON
#[cfg(debug_assertions)]
JSON,
}

impl IRType {
Expand All @@ -26,6 +29,8 @@ impl IRType {
Self::EVMLA => revive_common::EXTENSION_EVMLA,
Self::LLVM => revive_common::EXTENSION_LLVM_SOURCE,
Self::Assembly => revive_common::EXTENSION_POLKAVM_ASSEMBLY,
#[cfg(debug_assertions)]
Self::JSON => revive_common::EXTENSION_JSON,
}
}
}
16 changes: 16 additions & 0 deletions crates/llvm-context/src/debug_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,22 @@ impl DebugConfig {
Ok(())
}

/// Dumps the stage output as a json file suitable for use with --recursive-process
#[cfg(debug_assertions)]
pub fn dump_stage_output(
&self,
contract_path: &str,
contract_suffix: Option<&str>,
stage_json: &Vec<u8>,
) -> anyhow::Result<()> {
let mut file_path = self.output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, contract_suffix, IRType::JSON);
file_path.push(full_file_name);
std::fs::write(file_path, stage_json)?;

Ok(())
}

/// Creates a full file name, given the contract full path, suffix, and extension.
fn full_file_name(contract_path: &str, suffix: Option<&str>, ir_type: IRType) -> String {
let mut full_file_name = contract_path.replace('/', "_").replace(':', ".");
Expand Down
31 changes: 29 additions & 2 deletions crates/solidity/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,27 @@ use self::output::Output;
pub static EXECUTABLE: OnceCell<PathBuf> = OnceCell::new();

/// Read input from `stdin`, compile a contract, and write the output to `stdout`.
pub fn run() -> anyhow::Result<()> {
pub fn run(input_file: Option<&mut std::fs::File>) -> anyhow::Result<()> {
let mut stdin = std::io::stdin();
let mut stdout = std::io::stdout();
let mut stderr = std::io::stderr();

let mut buffer = Vec::with_capacity(16384);
stdin.read_to_end(&mut buffer).expect("Stdin reading error");
match input_file {
Some(ins) => {
if let Err(error) = ins.read_to_end(&mut buffer) {
anyhow::bail!("Failed to read recursive process input file: {:?}", error);
}
}
None => {
if let Err(error) = stdin.read_to_end(&mut buffer) {
anyhow::bail!(
"Failed to read recursive process input from stdin: {:?}",
error
)
}
}
}

let input: Input = revive_common::deserialize_from_slice(buffer.as_slice())?;
if input.enable_test_encoding {
Expand Down Expand Up @@ -74,6 +88,19 @@ pub fn call(input: Input) -> anyhow::Result<Output> {
anyhow::anyhow!("{:?} subprocess spawning error: {:?}", executable, error)
})?;

#[cfg(debug_assertions)]
if let Some(dbg_config) = &input.debug_config {
let _ = dbg_config
.dump_stage_output(&input.contract.path, Some("stage"), &input_json)
.map_err(|error| {
anyhow::anyhow!(
"{:?} failed to log the recursive process output: {:?}",
executable,
error,
)
})?;
}

process
.stdin
.as_ref()
Expand Down
20 changes: 20 additions & 0 deletions crates/solidity/src/resolc/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ pub struct Arguments {
/// Only for usage from within the compiler.
#[structopt(long = "recursive-process")]
pub recursive_process: bool,

/// Specify the input file to use instead of stdin when --recursive-process is given.
/// This is only intended for use when developing the compiler.
#[cfg(debug_assertions)]
#[structopt(long = "recursive-process-input")]
pub recursive_process_input: Option<String>,
}

impl Default for Arguments {
Expand All @@ -185,6 +191,20 @@ impl Arguments {
anyhow::bail!("No other options are allowed while getting the compiler version.");
}

#[cfg(debug_assertions)]
if self.recursive_process_input != None && !self.recursive_process {
anyhow::bail!("--process-input can be only used when --recursive-process is given");
}

#[cfg(debug_assertions)]
if self.recursive_process
&& ((self.recursive_process_input == None && std::env::args().count() > 2)
|| (self.recursive_process_input != None && std::env::args().count() > 4))
{
anyhow::bail!("No other options are allowed in recursive mode.");
}

#[cfg(not(debug_assertions))]
if self.recursive_process && std::env::args().count() > 2 {
anyhow::bail!("No other options are allowed in recursive mode.");
}
Expand Down
8 changes: 7 additions & 1 deletion crates/solidity/src/resolc/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ fn main_inner() -> anyhow::Result<()> {
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM); // TODO: pass from CLI

if arguments.recursive_process {
return revive_solidity::run_process();
#[cfg(debug_assertions)]
if let Some(fname) = arguments.recursive_process_input {
let mut infile = std::fs::File::open(fname)?;
return revive_solidity::run_process(Some(&mut infile));
}

return revive_solidity::run_process(None);
}

let debug_config = match arguments.debug_output_directory {
Expand Down

0 comments on commit bb4a4dd

Please sign in to comment.