mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-24 19:27:58 +00:00
[solidity,llvm-context] Improve support for debugging the compiler (#32)
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.
This commit is contained in:
@@ -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 {
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(':', ".");
|
||||
|
||||
@@ -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 {
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user