mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-15 09:11:04 +00:00
Separate compilation and linker phases (#376)
Separate between compilation and linker phases to allow deploy time linking and back-porting era compiler changes to fix #91. Unlinked contract binaries (caused by missing libraries or missing factory dependencies in turn) are emitted as raw ELF object. Few drive by fixes: - #98 - A compiler panic on missing libraries definitions. - Fixes some incosistent type forwarding in JSON output (empty string vs. null object). - Remove the unused fallback for size optimization setting. - Remove the broken `--lvm-ir` mode. - CI workflow fixes. --------- Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by: xermicus <bigcyrill@hotmail.com> Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -1,29 +1,39 @@
|
||||
//! The `solc --standard-json` input.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
#[cfg(feature = "resolc")]
|
||||
use std::collections::BTreeSet;
|
||||
#[cfg(feature = "resolc")]
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "resolc")]
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(all(feature = "parallel", feature = "resolc"))]
|
||||
use rayon::iter::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator};
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::SolcStandardJsonInputSettingsLibraries;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::SolcStandardJsonInputSettingsPolkaVM;
|
||||
|
||||
use self::language::Language;
|
||||
#[cfg(feature = "resolc")]
|
||||
use self::settings::warning::Warning;
|
||||
use self::settings::Settings;
|
||||
use self::source::Source;
|
||||
|
||||
pub mod language;
|
||||
pub mod settings;
|
||||
pub mod source;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(all(feature = "parallel", feature = "resolc"))]
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::warning::Warning;
|
||||
use crate::SolcStandardJsonInputSettingsPolkaVM;
|
||||
|
||||
use self::language::Language;
|
||||
use self::settings::Settings;
|
||||
use self::source::Source;
|
||||
|
||||
/// The `solc --standard-json` input.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -36,93 +46,88 @@ pub struct Input {
|
||||
pub settings: Settings,
|
||||
/// The suppressed warnings.
|
||||
#[cfg(feature = "resolc")]
|
||||
#[serde(skip_serializing)]
|
||||
pub suppressed_warnings: Option<Vec<Warning>>,
|
||||
#[serde(default, skip_serializing)]
|
||||
pub suppressed_warnings: Vec<Warning>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "resolc")]
|
||||
impl Input {
|
||||
/// A shortcut constructor from stdin.
|
||||
pub fn try_from_stdin() -> anyhow::Result<Self> {
|
||||
let mut input: Self = serde_json::from_reader(std::io::BufReader::new(std::io::stdin()))?;
|
||||
input
|
||||
.settings
|
||||
.output_selection
|
||||
.get_or_insert_with(SolcStandardJsonInputSettingsSelection::default)
|
||||
.extend_with_required();
|
||||
Ok(input)
|
||||
/// A shortcut constructor.
|
||||
///
|
||||
/// If the `path` is `None`, the input is read from the stdin.
|
||||
pub fn try_from(path: Option<&Path>) -> anyhow::Result<Self> {
|
||||
let input_json = match path {
|
||||
Some(path) => std::fs::read_to_string(path)
|
||||
.map_err(|error| anyhow::anyhow!("Standard JSON file {path:?} reading: {error}")),
|
||||
None => std::io::read_to_string(std::io::stdin())
|
||||
.map_err(|error| anyhow::anyhow!("Standard JSON reading from stdin: {error}")),
|
||||
}?;
|
||||
revive_common::deserialize_from_str::<Self>(input_json.as_str())
|
||||
.map_err(|error| anyhow::anyhow!("Standard JSON parsing: {error}"))
|
||||
}
|
||||
|
||||
/// A shortcut constructor from paths.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn try_from_paths(
|
||||
language: Language,
|
||||
pub fn try_from_solidity_paths(
|
||||
evm_version: Option<revive_common::EVMVersion>,
|
||||
paths: &[PathBuf],
|
||||
library_map: Vec<String>,
|
||||
remappings: Option<BTreeSet<String>>,
|
||||
libraries: &[String],
|
||||
remappings: BTreeSet<String>,
|
||||
output_selection: SolcStandardJsonInputSettingsSelection,
|
||||
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
||||
metadata: Option<SolcStandardJsonInputSettingsMetadata>,
|
||||
#[cfg(feature = "resolc")] suppressed_warnings: Option<Vec<Warning>>,
|
||||
polkavm: Option<SolcStandardJsonInputSettingsPolkaVM>,
|
||||
metadata: SolcStandardJsonInputSettingsMetadata,
|
||||
suppressed_warnings: Vec<Warning>,
|
||||
polkavm: SolcStandardJsonInputSettingsPolkaVM,
|
||||
llvm_arguments: Vec<String>,
|
||||
detect_missing_libraries: bool,
|
||||
) -> anyhow::Result<Self> {
|
||||
let mut paths: BTreeSet<PathBuf> = paths.iter().cloned().collect();
|
||||
let libraries = Settings::parse_libraries(library_map)?;
|
||||
for library_file in libraries.keys() {
|
||||
let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?;
|
||||
for library_file in libraries.as_inner().keys() {
|
||||
paths.insert(PathBuf::from(library_file));
|
||||
}
|
||||
|
||||
let sources = paths
|
||||
.iter()
|
||||
.map(|path| {
|
||||
let source = Source::try_from(path.as_path()).unwrap_or_else(|error| {
|
||||
panic!("Source code file {path:?} reading error: {error}")
|
||||
});
|
||||
(path.to_string_lossy().to_string(), source)
|
||||
})
|
||||
.collect();
|
||||
#[cfg(feature = "parallel")]
|
||||
let iter = paths.into_par_iter(); // Parallel iterator
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let iter = paths.into_iter(); // Sequential iterator
|
||||
|
||||
Ok(Self {
|
||||
language,
|
||||
let sources = iter
|
||||
.map(|path| {
|
||||
let source = Source::try_read(path.as_path())?;
|
||||
Ok((path.to_string_lossy().to_string(), source))
|
||||
})
|
||||
.collect::<anyhow::Result<BTreeMap<String, Source>>>()?;
|
||||
|
||||
Self::try_from_solidity_sources(
|
||||
evm_version,
|
||||
sources,
|
||||
settings: Settings::new(
|
||||
evm_version,
|
||||
libraries,
|
||||
remappings,
|
||||
output_selection,
|
||||
optimizer,
|
||||
metadata,
|
||||
polkavm,
|
||||
),
|
||||
#[cfg(feature = "resolc")]
|
||||
libraries,
|
||||
remappings,
|
||||
output_selection,
|
||||
optimizer,
|
||||
metadata,
|
||||
suppressed_warnings,
|
||||
})
|
||||
polkavm,
|
||||
llvm_arguments,
|
||||
detect_missing_libraries,
|
||||
)
|
||||
}
|
||||
|
||||
/// A shortcut constructor from source code.
|
||||
/// Only for the integration test purposes.
|
||||
#[cfg(feature = "resolc")]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn try_from_sources(
|
||||
pub fn try_from_solidity_sources(
|
||||
evm_version: Option<revive_common::EVMVersion>,
|
||||
sources: BTreeMap<String, String>,
|
||||
libraries: BTreeMap<String, BTreeMap<String, String>>,
|
||||
remappings: Option<BTreeSet<String>>,
|
||||
sources: BTreeMap<String, Source>,
|
||||
libraries: SolcStandardJsonInputSettingsLibraries,
|
||||
remappings: BTreeSet<String>,
|
||||
output_selection: SolcStandardJsonInputSettingsSelection,
|
||||
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
||||
metadata: Option<SolcStandardJsonInputSettingsMetadata>,
|
||||
suppressed_warnings: Option<Vec<Warning>>,
|
||||
polkavm: Option<SolcStandardJsonInputSettingsPolkaVM>,
|
||||
metadata: SolcStandardJsonInputSettingsMetadata,
|
||||
suppressed_warnings: Vec<Warning>,
|
||||
polkavm: SolcStandardJsonInputSettingsPolkaVM,
|
||||
llvm_arguments: Vec<String>,
|
||||
detect_missing_libraries: bool,
|
||||
) -> anyhow::Result<Self> {
|
||||
#[cfg(feature = "parallel")]
|
||||
let iter = sources.into_par_iter(); // Parallel iterator
|
||||
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let iter = sources.into_iter(); // Sequential iterator
|
||||
let sources = iter
|
||||
.map(|(path, content)| (path, Source::from(content)))
|
||||
.collect();
|
||||
|
||||
Ok(Self {
|
||||
language: Language::Solidity,
|
||||
sources,
|
||||
@@ -134,13 +139,75 @@ impl Input {
|
||||
optimizer,
|
||||
metadata,
|
||||
polkavm,
|
||||
suppressed_warnings.clone(),
|
||||
llvm_arguments,
|
||||
detect_missing_libraries,
|
||||
),
|
||||
suppressed_warnings,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the necessary defaults.
|
||||
pub fn normalize(&mut self) {
|
||||
self.settings.normalize();
|
||||
/// A shortcut constructor from paths to Yul source files.
|
||||
pub fn from_yul_paths(
|
||||
paths: &[PathBuf],
|
||||
libraries: SolcStandardJsonInputSettingsLibraries,
|
||||
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
||||
llvm_options: Vec<String>,
|
||||
) -> Self {
|
||||
let sources = paths
|
||||
.iter()
|
||||
.map(|path| {
|
||||
(
|
||||
path.to_string_lossy().to_string(),
|
||||
Source::from(path.as_path()),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
Self::from_yul_sources(sources, libraries, optimizer, llvm_options)
|
||||
}
|
||||
|
||||
/// A shortcut constructor from Yul source code.
|
||||
pub fn from_yul_sources(
|
||||
sources: BTreeMap<String, Source>,
|
||||
libraries: SolcStandardJsonInputSettingsLibraries,
|
||||
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
||||
llvm_arguments: Vec<String>,
|
||||
) -> Self {
|
||||
let output_selection = SolcStandardJsonInputSettingsSelection::new_yul_validation();
|
||||
|
||||
Self {
|
||||
language: Language::Yul,
|
||||
sources,
|
||||
settings: Settings::new(
|
||||
None,
|
||||
libraries,
|
||||
Default::default(),
|
||||
output_selection,
|
||||
optimizer,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
vec![],
|
||||
llvm_arguments,
|
||||
false,
|
||||
),
|
||||
suppressed_warnings: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Extends the output selection with another one.
|
||||
pub fn extend_selection(&mut self, selection: SolcStandardJsonInputSettingsSelection) {
|
||||
self.settings.extend_selection(selection);
|
||||
}
|
||||
|
||||
/// Tries to resolve all sources.
|
||||
pub fn resolve_sources(&mut self) {
|
||||
#[cfg(feature = "parallel")]
|
||||
let iter = self.sources.par_iter_mut();
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let iter = self.sources.iter_mut();
|
||||
|
||||
iter.for_each(|(_path, source)| {
|
||||
let _ = source.try_resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user