mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-26 01:47:56 +00:00
Make native version to compaile again
This commit is contained in:
Generated
+1
@@ -7980,6 +7980,7 @@ dependencies = [
|
||||
"colored",
|
||||
"hex",
|
||||
"inkwell",
|
||||
"libc",
|
||||
"md5",
|
||||
"mimalloc",
|
||||
"num",
|
||||
|
||||
@@ -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(':', ".");
|
||||
|
||||
@@ -19,7 +19,6 @@ doctest = false
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true }
|
||||
structopt = { workspace = true }
|
||||
colored = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
||||
@@ -5,9 +5,9 @@ pub mod contract;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::solc::combined_json::CombinedJson;
|
||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
||||
use crate::solc::version::Version as SolcVersion;
|
||||
use crate::compiler::combined_json::CombinedJson;
|
||||
use crate::compiler::standard_json::output::Output as StandardJsonOutput;
|
||||
use crate::compiler::version::Version as SolcVersion;
|
||||
use crate::ResolcVersion;
|
||||
|
||||
use self::contract::Contract;
|
||||
|
||||
@@ -8,7 +8,6 @@ pub(crate) mod evmla;
|
||||
pub(crate) mod missing_libraries;
|
||||
pub(crate) mod process;
|
||||
pub(crate) mod project;
|
||||
pub(crate) mod solc;
|
||||
pub(crate) mod version;
|
||||
pub(crate) mod warning;
|
||||
pub(crate) mod yul;
|
||||
@@ -48,24 +47,6 @@ pub use self::process::Process;
|
||||
pub use self::project::contract::Contract as ProjectContract;
|
||||
pub use self::project::Project;
|
||||
pub use self::r#const::*;
|
||||
pub use self::solc::combined_json::contract::Contract as SolcCombinedJsonContract;
|
||||
pub use self::solc::combined_json::CombinedJson as SolcCombinedJson;
|
||||
pub use self::solc::pipeline::Pipeline as SolcPipeline;
|
||||
pub use self::solc::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
|
||||
pub use self::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
pub use self::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
pub use self::solc::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag;
|
||||
pub use self::solc::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile;
|
||||
pub use self::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
pub use self::solc::standard_json::input::settings::Settings as SolcStandardJsonInputSettings;
|
||||
pub use self::solc::standard_json::input::source::Source as SolcStandardJsonInputSource;
|
||||
pub use self::solc::standard_json::input::Input as SolcStandardJsonInput;
|
||||
pub use self::solc::standard_json::output::contract::evm::bytecode::Bytecode as SolcStandardJsonOutputContractEVMBytecode;
|
||||
pub use self::solc::standard_json::output::contract::evm::EVM as SolcStandardJsonOutputContractEVM;
|
||||
pub use self::solc::standard_json::output::contract::Contract as SolcStandardJsonOutputContract;
|
||||
pub use self::solc::standard_json::output::Output as SolcStandardJsonOutput;
|
||||
pub use self::solc::version::Version as SolcVersion;
|
||||
pub use self::solc::Compiler as SolcCompiler;
|
||||
pub use self::version::Version as ResolcVersion;
|
||||
pub use self::warning::Warning;
|
||||
#[cfg(target_os = "emscripten")]
|
||||
@@ -94,7 +75,7 @@ pub fn yul<T: Compiler>(
|
||||
),
|
||||
};
|
||||
|
||||
if solc.version()?.default != SolcCompiler::LAST_SUPPORTED_VERSION {
|
||||
if solc.version()?.default != compiler::LAST_SUPPORTED_VERSION {
|
||||
anyhow::bail!(
|
||||
"The Yul mode is only supported with the most recent version of the Solidity compiler: {}",
|
||||
compiler::LAST_SUPPORTED_VERSION,
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
||||
use crate::solc::version::Version as SolcVersion;
|
||||
use crate::compiler::standard_json::output::Output as StandardJsonOutput;
|
||||
use crate::compiler::version::Version as SolcVersion;
|
||||
use crate::ResolcVersion;
|
||||
|
||||
/// The missing Solidity libraries.
|
||||
|
||||
@@ -11,6 +11,6 @@ use self::input::Input;
|
||||
use self::output::Output;
|
||||
|
||||
pub trait Process {
|
||||
fn run() -> anyhow::Result<()>;
|
||||
fn run(input_file: Option<&mut std::fs::File>) -> anyhow::Result<()>;
|
||||
fn call(input: Input) -> anyhow::Result<Output>;
|
||||
}
|
||||
|
||||
@@ -18,26 +18,36 @@ pub struct NativeProcess;
|
||||
|
||||
impl Process for NativeProcess {
|
||||
/// Read input from `stdin`, compile a contract, and write the output to `stdout`.
|
||||
fn run() -> anyhow::Result<()> {
|
||||
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");
|
||||
|
||||
let input: Input = revive_common::deserialize_from_slice(buffer.as_slice())?;
|
||||
if input.enable_test_encoding {
|
||||
todo!()
|
||||
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())?;
|
||||
let result = input.contract.compile(
|
||||
input.project,
|
||||
input.optimizer_settings,
|
||||
input.is_system_mode,
|
||||
input.include_metadata_hash,
|
||||
input.debug_config,
|
||||
);
|
||||
|
||||
|
||||
match result {
|
||||
Ok(build) => {
|
||||
let output = Output::new(build);
|
||||
@@ -56,16 +66,16 @@ impl Process for NativeProcess {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Runs this process recursively to compile a single contract.
|
||||
fn call(input: Input) -> anyhow::Result<Output> {
|
||||
let input_json = serde_json::to_vec(&input).expect("Always valid");
|
||||
|
||||
|
||||
let executable = match EXECUTABLE.get() {
|
||||
Some(executable) => executable.to_owned(),
|
||||
None => std::env::current_exe()?,
|
||||
};
|
||||
|
||||
|
||||
let mut command = Command::new(executable.as_path());
|
||||
command.stdin(std::process::Stdio::piped());
|
||||
command.stdout(std::process::Stdio::piped());
|
||||
@@ -74,15 +84,26 @@ impl Process for NativeProcess {
|
||||
let process = command.spawn().map_err(|error| {
|
||||
anyhow::anyhow!("{:?} subprocess spawning error: {:?}", executable, error)
|
||||
})?;
|
||||
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
if let Some(dbg_config) = &input.debug_config {
|
||||
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()
|
||||
.ok_or_else(|| anyhow::anyhow!("{:?} stdin getting error", executable))?
|
||||
.write_all(input_json.as_slice())
|
||||
.map_err(|error| {
|
||||
anyhow::anyhow!("{:?} stdin writing error: {:?}", executable, error)
|
||||
})?;
|
||||
.map_err(|error| anyhow::anyhow!("{:?} stdin writing error: {:?}", executable, error))?;
|
||||
let output = process.wait_with_output().map_err(|error| {
|
||||
anyhow::anyhow!("{:?} subprocess output error: {:?}", executable, error)
|
||||
})?;
|
||||
@@ -92,9 +113,9 @@ impl Process for NativeProcess {
|
||||
String::from_utf8_lossy(output.stderr.as_slice()).to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
let output: Output = revive_common::deserialize_from_slice(output.stdout.as_slice())
|
||||
.map_err(|error| {
|
||||
|
||||
let output: Output =
|
||||
revive_common::deserialize_from_slice(output.stdout.as_slice()).map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
"{:?} subprocess output parsing error: {}",
|
||||
executable,
|
||||
|
||||
@@ -4,21 +4,25 @@ use std::collections::BTreeSet;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use path_slash::PathExt;
|
||||
use structopt::StructOpt;
|
||||
|
||||
/// Compiles the provided Solidity input files (or use the standard input if no files
|
||||
/// are given or "-" is specified as a file name). Outputs the components based on the
|
||||
/// chosen options, either to the standard output or to files within the designated
|
||||
/// output directory.
|
||||
/// Example: resolc ERC20.sol -O3 --bin --output-dir './build/'
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[derive(Debug, Parser)]
|
||||
#[structopt(name = "The PolkaVM Solidity compiler")]
|
||||
pub struct Arguments {
|
||||
/// Print the version and exit.
|
||||
#[structopt(long = "version")]
|
||||
pub version: bool,
|
||||
|
||||
/// Print the licence and exit.
|
||||
#[structopt(long = "license")]
|
||||
pub license: bool,
|
||||
|
||||
/// Specify the input paths and remappings.
|
||||
/// If an argument contains a '=', it is considered a remapping.
|
||||
/// Multiple Solidity files can be passed in the default Solidity mode.
|
||||
@@ -42,7 +46,7 @@ pub struct Arguments {
|
||||
pub allow_paths: Option<String>,
|
||||
|
||||
/// Create one file per component and contract/file at the specified directory, if given.
|
||||
#[structopt(short = "o", long = "output-dir")]
|
||||
#[structopt(short = 'o', long = "output-dir")]
|
||||
pub output_directory: Option<PathBuf>,
|
||||
|
||||
/// Overwrite existing files (used together with -o).
|
||||
@@ -51,7 +55,7 @@ pub struct Arguments {
|
||||
|
||||
/// Set the optimization parameter -O[0 | 1 | 2 | 3 | s | z].
|
||||
/// Use `3` for best performance and `z` for minimal size.
|
||||
#[structopt(short = "O", long = "optimization")]
|
||||
#[structopt(short = 'O', long = "optimization")]
|
||||
pub optimization: Option<char>,
|
||||
|
||||
/// Try to recompile with -Oz if the bytecode is too large.
|
||||
@@ -77,7 +81,7 @@ pub struct Arguments {
|
||||
|
||||
/// Specify addresses of deployable libraries. Syntax: `<libraryName>=<address> [, or whitespace] ...`.
|
||||
/// Addresses are interpreted as hexadecimal strings prefixed with `0x`.
|
||||
#[structopt(short = "l", long = "libraries")]
|
||||
#[structopt(short = 'l', long = "libraries")]
|
||||
pub libraries: Vec<String>,
|
||||
|
||||
/// Output a single JSON document containing the specified information.
|
||||
@@ -153,6 +157,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 {
|
||||
@@ -164,7 +174,7 @@ impl Default for Arguments {
|
||||
impl Arguments {
|
||||
/// A shortcut constructor.
|
||||
pub fn new() -> Self {
|
||||
Self::from_args()
|
||||
Self::parse()
|
||||
}
|
||||
|
||||
/// Validates the arguments.
|
||||
|
||||
@@ -41,6 +41,14 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if arguments.license {
|
||||
let license_mit = include_str!("../../../../LICENSE-MIT");
|
||||
let license_apache = include_str!("../../../../LICENSE-APACHE");
|
||||
|
||||
println!("{}\n{}\n", license_mit, license_apache);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.stack_size(RAYON_WORKER_STACK_SIZE)
|
||||
@@ -50,13 +58,25 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM); // TODO: pass from CLI
|
||||
|
||||
if arguments.recursive_process {
|
||||
#[cfg(debug_assertions)]
|
||||
if let Some(fname) = arguments.recursive_process_input {
|
||||
let mut infile = std::fs::File::open(fname)?;
|
||||
#[cfg(target_os = "emscripten")]
|
||||
{
|
||||
return revive_solidity::WorkerProcess::run(Some(&mut infile));
|
||||
}
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
{
|
||||
return revive_solidity::NativeProcess::run(Some(&mut infile));
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "emscripten")]
|
||||
{
|
||||
return revive_solidity::WorkerProcess::run();
|
||||
return revive_solidity::WorkerProcess::run(None);
|
||||
}
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
{
|
||||
return revive_solidity::NativeProcess::run();
|
||||
return revive_solidity::NativeProcess::run(None);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use self::version::Version;
|
||||
const FIRST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 4, 12);
|
||||
|
||||
/// The first version of `solc`, where Yul codegen is considered robust enough.
|
||||
const FIRST_YUL_VERSION: semver::Version = semver::Version::new(0, 8, 0);
|
||||
pub(crate) const FIRST_YUL_VERSION: semver::Version = semver::Version::new(0, 8, 0);
|
||||
|
||||
/// The first version of `solc`, where `--via-ir` codegen mode is supported.
|
||||
const FIRST_VIA_IR_VERSION: semver::Version = semver::Version::new(0, 8, 13);
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
//! The Solidity compiler.
|
||||
|
||||
pub mod combined_json;
|
||||
pub mod pipeline;
|
||||
pub mod standard_json;
|
||||
pub mod version;
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use self::combined_json::CombinedJson;
|
||||
use self::pipeline::Pipeline;
|
||||
use self::standard_json::input::Input as StandardJsonInput;
|
||||
use self::standard_json::output::Output as StandardJsonOutput;
|
||||
use self::version::Version;
|
||||
|
||||
/// The Solidity compiler.
|
||||
pub struct Compiler {
|
||||
/// The binary executable name.
|
||||
pub executable: String,
|
||||
/// The lazily-initialized compiler version.
|
||||
pub version: Option<Version>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
/// The default executable name.
|
||||
pub const DEFAULT_EXECUTABLE_NAME: &'static str = "solc";
|
||||
|
||||
/// The first version of `solc` with the support of standard JSON interface.
|
||||
pub const FIRST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 4, 12);
|
||||
|
||||
/// The first version of `solc`, where Yul codegen is considered robust enough.
|
||||
pub const FIRST_YUL_VERSION: semver::Version = semver::Version::new(0, 8, 0);
|
||||
|
||||
/// The first version of `solc`, where `--via-ir` codegen mode is supported.
|
||||
pub const FIRST_VIA_IR_VERSION: semver::Version = semver::Version::new(0, 8, 13);
|
||||
|
||||
/// The last supported version of `solc`.
|
||||
pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 28);
|
||||
|
||||
/// A shortcut constructor.
|
||||
/// Different tools may use different `executable` names. For example, the integration tester
|
||||
/// uses `solc-<version>` format.
|
||||
pub fn new(executable: String) -> anyhow::Result<Self> {
|
||||
if let Err(error) = which::which(executable.as_str()) {
|
||||
anyhow::bail!(
|
||||
"The `{executable}` executable not found in ${{PATH}}: {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
Ok(Self {
|
||||
executable,
|
||||
version: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||
pub fn standard_json(
|
||||
&mut self,
|
||||
mut input: StandardJsonInput,
|
||||
pipeline: Pipeline,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
) -> anyhow::Result<StandardJsonOutput> {
|
||||
let version = self.version()?;
|
||||
|
||||
let mut command = std::process::Command::new(self.executable.as_str());
|
||||
command.stdin(std::process::Stdio::piped());
|
||||
command.stdout(std::process::Stdio::piped());
|
||||
command.arg("--standard-json");
|
||||
|
||||
if let Some(base_path) = base_path {
|
||||
command.arg("--base-path");
|
||||
command.arg(base_path);
|
||||
}
|
||||
for include_path in include_paths.into_iter() {
|
||||
command.arg("--include-path");
|
||||
command.arg(include_path);
|
||||
}
|
||||
if let Some(allow_paths) = allow_paths {
|
||||
command.arg("--allow-paths");
|
||||
command.arg(allow_paths);
|
||||
}
|
||||
|
||||
input.normalize(&version.default);
|
||||
|
||||
let suppressed_warnings = input.suppressed_warnings.take().unwrap_or_default();
|
||||
|
||||
let input_json = serde_json::to_vec(&input).expect("Always valid");
|
||||
|
||||
let process = command.spawn().map_err(|error| {
|
||||
anyhow::anyhow!("{} subprocess spawning error: {:?}", self.executable, error)
|
||||
})?;
|
||||
process
|
||||
.stdin
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!("{} stdin getting error", self.executable))?
|
||||
.write_all(input_json.as_slice())
|
||||
.map_err(|error| {
|
||||
anyhow::anyhow!("{} stdin writing error: {:?}", self.executable, error)
|
||||
})?;
|
||||
|
||||
let output = process.wait_with_output().map_err(|error| {
|
||||
anyhow::anyhow!("{} subprocess output error: {:?}", self.executable, error)
|
||||
})?;
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"{} error: {}",
|
||||
self.executable,
|
||||
String::from_utf8_lossy(output.stderr.as_slice()).to_string()
|
||||
);
|
||||
}
|
||||
|
||||
let mut output: StandardJsonOutput =
|
||||
revive_common::deserialize_from_slice(output.stdout.as_slice()).map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
"{} subprocess output parsing error: {}\n{}",
|
||||
self.executable,
|
||||
error,
|
||||
revive_common::deserialize_from_slice::<serde_json::Value>(
|
||||
output.stdout.as_slice()
|
||||
)
|
||||
.map(|json| serde_json::to_string_pretty(&json).expect("Always valid"))
|
||||
.unwrap_or_else(
|
||||
|_| String::from_utf8_lossy(output.stdout.as_slice()).to_string()
|
||||
),
|
||||
)
|
||||
})?;
|
||||
output.preprocess_ast(&version, pipeline, suppressed_warnings.as_slice())?;
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
/// The `solc --combined-json abi,hashes...` mirror.
|
||||
pub fn combined_json(
|
||||
&self,
|
||||
paths: &[PathBuf],
|
||||
combined_json_argument: &str,
|
||||
) -> anyhow::Result<CombinedJson> {
|
||||
let mut command = std::process::Command::new(self.executable.as_str());
|
||||
command.args(paths);
|
||||
|
||||
let mut combined_json_flags = Vec::new();
|
||||
let mut combined_json_fake_flag_pushed = false;
|
||||
let mut filtered_flags = Vec::with_capacity(3);
|
||||
for flag in combined_json_argument.split(',') {
|
||||
match flag {
|
||||
flag @ "asm" | flag @ "bin" | flag @ "bin-runtime" => filtered_flags.push(flag),
|
||||
flag => combined_json_flags.push(flag),
|
||||
}
|
||||
}
|
||||
if combined_json_flags.is_empty() {
|
||||
combined_json_flags.push("ast");
|
||||
combined_json_fake_flag_pushed = true;
|
||||
}
|
||||
command.arg("--combined-json");
|
||||
command.arg(combined_json_flags.join(","));
|
||||
|
||||
let output = command.output().map_err(|error| {
|
||||
anyhow::anyhow!("{} subprocess error: {:?}", self.executable, error)
|
||||
})?;
|
||||
if !output.status.success() {
|
||||
println!("{}", String::from_utf8_lossy(output.stdout.as_slice()));
|
||||
println!("{}", String::from_utf8_lossy(output.stderr.as_slice()));
|
||||
anyhow::bail!(
|
||||
"{} error: {}",
|
||||
self.executable,
|
||||
String::from_utf8_lossy(output.stdout.as_slice()).to_string()
|
||||
);
|
||||
}
|
||||
|
||||
let mut combined_json: CombinedJson =
|
||||
revive_common::deserialize_from_slice(output.stdout.as_slice()).map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
"{} subprocess output parsing error: {}\n{}",
|
||||
self.executable,
|
||||
error,
|
||||
revive_common::deserialize_from_slice::<serde_json::Value>(
|
||||
output.stdout.as_slice()
|
||||
)
|
||||
.map(|json| serde_json::to_string_pretty(&json).expect("Always valid"))
|
||||
.unwrap_or_else(
|
||||
|_| String::from_utf8_lossy(output.stdout.as_slice()).to_string()
|
||||
),
|
||||
)
|
||||
})?;
|
||||
for filtered_flag in filtered_flags.into_iter() {
|
||||
for (_path, contract) in combined_json.contracts.iter_mut() {
|
||||
match filtered_flag {
|
||||
"asm" => contract.asm = Some(serde_json::Value::Null),
|
||||
"bin" => contract.bin = Some("".to_owned()),
|
||||
"bin-runtime" => contract.bin_runtime = Some("".to_owned()),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
if combined_json_fake_flag_pushed {
|
||||
combined_json.source_list = None;
|
||||
combined_json.sources = None;
|
||||
}
|
||||
combined_json.remove_evm();
|
||||
|
||||
Ok(combined_json)
|
||||
}
|
||||
|
||||
/// The `solc` Yul validator.
|
||||
pub fn validate_yul(&self, path: &Path) -> anyhow::Result<()> {
|
||||
let mut command = std::process::Command::new(self.executable.as_str());
|
||||
command.arg("--strict-assembly");
|
||||
command.arg(path);
|
||||
|
||||
let output = command.output().map_err(|error| {
|
||||
anyhow::anyhow!("{} subprocess error: {:?}", self.executable, error)
|
||||
})?;
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"{} error: {}",
|
||||
self.executable,
|
||||
String::from_utf8_lossy(output.stderr.as_slice()).to_string()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The `solc --version` mini-parser.
|
||||
pub fn version(&mut self) -> anyhow::Result<Version> {
|
||||
if let Some(version) = self.version.as_ref() {
|
||||
return Ok(version.to_owned());
|
||||
}
|
||||
|
||||
let mut command = std::process::Command::new(self.executable.as_str());
|
||||
command.arg("--version");
|
||||
let output = command.output().map_err(|error| {
|
||||
anyhow::anyhow!("{} subprocess error: {:?}", self.executable, error)
|
||||
})?;
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"{} error: {}",
|
||||
self.executable,
|
||||
String::from_utf8_lossy(output.stderr.as_slice()).to_string()
|
||||
);
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8_lossy(output.stdout.as_slice());
|
||||
let long = stdout
|
||||
.lines()
|
||||
.nth(1)
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!("{} version parsing: not enough lines", self.executable)
|
||||
})?
|
||||
.split(' ')
|
||||
.nth(1)
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!(
|
||||
"{} version parsing: not enough words in the 2nd line",
|
||||
self.executable
|
||||
)
|
||||
})?
|
||||
.to_owned();
|
||||
let default: semver::Version = long
|
||||
.split('+')
|
||||
.next()
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!("{} version parsing: metadata dropping", self.executable)
|
||||
})?
|
||||
.parse()
|
||||
.map_err(|error| anyhow::anyhow!("{} version parsing: {}", self.executable, error))?;
|
||||
|
||||
let l2_revision: Option<semver::Version> = stdout
|
||||
.lines()
|
||||
.nth(2)
|
||||
.and_then(|line| line.split(' ').nth(1))
|
||||
.and_then(|line| line.split('-').nth(1))
|
||||
.and_then(|version| version.parse().ok());
|
||||
|
||||
let version = Version::new(long, default, l2_revision);
|
||||
if version.default < Self::FIRST_SUPPORTED_VERSION {
|
||||
anyhow::bail!(
|
||||
"`solc` versions <{} are not supported, found {}",
|
||||
Self::FIRST_SUPPORTED_VERSION,
|
||||
version.default
|
||||
);
|
||||
}
|
||||
if version.default > Self::LAST_SUPPORTED_VERSION {
|
||||
anyhow::bail!(
|
||||
"`solc` versions >{} are not supported, found {}",
|
||||
Self::LAST_SUPPORTED_VERSION,
|
||||
version.default
|
||||
);
|
||||
}
|
||||
|
||||
self.version = Some(version.clone());
|
||||
|
||||
Ok(version)
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::solc::version::Version as SolcVersion;
|
||||
use crate::solc::Compiler as SolcCompiler;
|
||||
use crate::compiler::version::Version as SolcVersion;
|
||||
|
||||
/// The Solidity compiler pipeline type.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
@@ -19,7 +18,7 @@ pub enum Pipeline {
|
||||
impl Pipeline {
|
||||
/// We always use EVMLA for Solidity <=0.7, or if the user does not want to compile via Yul.
|
||||
pub fn new(solc_version: &SolcVersion, force_evmla: bool) -> Self {
|
||||
if solc_version.default < compiler::FIRST_YUL_VERSION || force_evmla {
|
||||
if solc_version.default < crate::compiler::FIRST_YUL_VERSION || force_evmla {
|
||||
Self::EVMLA
|
||||
} else {
|
||||
Self::Yul
|
||||
|
||||
@@ -42,8 +42,8 @@ impl SolcCompiler {
|
||||
}
|
||||
|
||||
impl Compiler for SolcCompiler {
|
||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||
fn standard_json(
|
||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||
fn standard_json(
|
||||
&mut self,
|
||||
mut input: StandardJsonInput,
|
||||
pipeline: Pipeline,
|
||||
@@ -116,7 +116,6 @@ impl Compiler for SolcCompiler {
|
||||
)
|
||||
})?;
|
||||
output.preprocess_ast(&version, pipeline, suppressed_warnings.as_slice())?;
|
||||
output.remove_evm();
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! Common utility used for in frontend and integration tests.
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
@@ -16,14 +16,7 @@ use crate::compiler::standard_json::output::contract::evm::bytecode::DeployedByt
|
||||
use crate::compiler::standard_json::output::Output as SolcStandardJsonOutput;
|
||||
use crate::compiler::Compiler;
|
||||
use crate::project::Project;
|
||||
use crate::solc::pipeline::Pipeline as SolcPipeline;
|
||||
use crate::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
use crate::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
use crate::solc::standard_json::input::Input as SolcStandardJsonInput;
|
||||
use crate::solc::standard_json::output::contract::evm::bytecode::Bytecode;
|
||||
use crate::solc::standard_json::output::contract::evm::bytecode::DeployedBytecode;
|
||||
use crate::solc::standard_json::output::Output as SolcStandardJsonOutput;
|
||||
use crate::solc::Compiler as SolcCompiler;
|
||||
use crate::compiler::standard_json::output::contract::evm::bytecode::Bytecode;
|
||||
use crate::warning::Warning;
|
||||
|
||||
static PVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[package]
|
||||
name = "revive-stdlib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
version.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
repository.workspace = true
|
||||
description = "revive compiler stdlib components"
|
||||
|
||||
[dependencies]
|
||||
inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-0"] }
|
||||
|
||||
Reference in New Issue
Block a user