mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-10-27 14:09:54 +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 parent
13faedf08a
commit
94ec34c4d5
169 files changed
+6288
-5206
No files matched your search
@@ -1,33 +1,40 @@
|
||||
//! The `solc --standard-json` output.
|
||||
|
||||
pub mod contract;
|
||||
pub mod error;
|
||||
pub mod source;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::warning::Warning;
|
||||
use crate::standard_json::input::settings::warning::Warning;
|
||||
use crate::standard_json::output::error::error_handler::ErrorHandler;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::SolcStandardJsonInputSettingsSelection;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::SolcStandardJsonInputSource;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
|
||||
use self::contract::Contract;
|
||||
use self::error::Error as SolcStandardJsonOutputError;
|
||||
use self::source::Source;
|
||||
|
||||
pub mod contract;
|
||||
pub mod error;
|
||||
pub mod source;
|
||||
|
||||
/// The `solc --standard-json` output.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Output {
|
||||
/// The file-contract hashmap.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub contracts: Option<BTreeMap<String, BTreeMap<String, Contract>>>,
|
||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||
pub contracts: BTreeMap<String, BTreeMap<String, Contract>>,
|
||||
/// The source code mapping data.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub sources: Option<BTreeMap<String, Source>>,
|
||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||
pub sources: BTreeMap<String, Source>,
|
||||
/// The compilation errors and warnings.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub errors: Option<Vec<SolcStandardJsonOutputError>>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub errors: Vec<SolcStandardJsonOutputError>,
|
||||
/// The `solc` compiler version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<String>,
|
||||
@@ -39,33 +46,156 @@ pub struct Output {
|
||||
pub revive_version: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "resolc")]
|
||||
impl Output {
|
||||
/// Traverses the AST and returns the list of additional errors and warnings.
|
||||
#[cfg(feature = "resolc")]
|
||||
pub fn preprocess_ast(&mut self, suppressed_warnings: &[Warning]) -> anyhow::Result<()> {
|
||||
let sources = match self.sources.as_ref() {
|
||||
Some(sources) => sources,
|
||||
None => return Ok(()),
|
||||
};
|
||||
/// Initializes a standard JSON output.
|
||||
///
|
||||
/// Is used for projects compiled without `solc`.
|
||||
pub fn new(
|
||||
sources: &BTreeMap<String, SolcStandardJsonInputSource>,
|
||||
messages: &mut Vec<SolcStandardJsonOutputError>,
|
||||
) -> Self {
|
||||
let sources = sources
|
||||
.keys()
|
||||
.enumerate()
|
||||
.map(|(index, path)| (path.to_owned(), Source::new(index)))
|
||||
.collect::<BTreeMap<String, Source>>();
|
||||
|
||||
let mut messages = Vec::new();
|
||||
for (path, source) in sources.iter() {
|
||||
if let Some(ast) = source.ast.as_ref() {
|
||||
let mut polkavm_messages = Source::get_messages(ast, suppressed_warnings);
|
||||
for message in polkavm_messages.iter_mut() {
|
||||
message.push_contract_path(path.as_str());
|
||||
}
|
||||
messages.extend(polkavm_messages);
|
||||
Self {
|
||||
contracts: BTreeMap::new(),
|
||||
sources,
|
||||
errors: std::mem::take(messages),
|
||||
|
||||
version: None,
|
||||
long_version: None,
|
||||
revive_version: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes a standard JSON output with messages.
|
||||
///
|
||||
/// Is used to emit errors in standard JSON mode.
|
||||
pub fn new_with_messages(messages: Vec<SolcStandardJsonOutputError>) -> Self {
|
||||
Self {
|
||||
contracts: BTreeMap::new(),
|
||||
sources: BTreeMap::new(),
|
||||
errors: messages,
|
||||
|
||||
version: None,
|
||||
long_version: None,
|
||||
revive_version: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Prunes the output JSON and prints it to stdout.
|
||||
pub fn write_and_exit(
|
||||
mut self,
|
||||
selection_to_prune: SolcStandardJsonInputSettingsSelection,
|
||||
) -> ! {
|
||||
let sources = self.sources.values_mut().collect::<Vec<&mut Source>>();
|
||||
for source in sources.into_iter() {
|
||||
if selection_to_prune
|
||||
.contains(&crate::SolcStandardJsonInputSettingsSelectionFileFlag::AST)
|
||||
{
|
||||
source.ast = None;
|
||||
}
|
||||
}
|
||||
self.errors = match self.errors.take() {
|
||||
Some(mut errors) => {
|
||||
errors.extend(messages);
|
||||
Some(errors)
|
||||
|
||||
let contracts = self
|
||||
.contracts
|
||||
.values_mut()
|
||||
.flat_map(|contracts| contracts.values_mut())
|
||||
.collect::<Vec<&mut Contract>>();
|
||||
for contract in contracts.into_iter() {
|
||||
if selection_to_prune
|
||||
.contains(&crate::SolcStandardJsonInputSettingsSelectionFileFlag::Metadata)
|
||||
{
|
||||
contract.metadata = serde_json::Value::Null;
|
||||
}
|
||||
None => Some(messages),
|
||||
};
|
||||
if selection_to_prune
|
||||
.contains(&crate::SolcStandardJsonInputSettingsSelectionFileFlag::Yul)
|
||||
{
|
||||
contract.ir_optimized = String::new();
|
||||
}
|
||||
if let Some(ref mut evm) = contract.evm {
|
||||
if selection_to_prune.contains(
|
||||
&crate::SolcStandardJsonInputSettingsSelectionFileFlag::MethodIdentifiers,
|
||||
) {
|
||||
evm.method_identifiers.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.contracts.retain(|_, contracts| {
|
||||
contracts.retain(|_, contract| !contract.is_empty());
|
||||
!contracts.is_empty()
|
||||
});
|
||||
|
||||
serde_json::to_writer(std::io::stdout(), &self).expect("Stdout writing error");
|
||||
std::process::exit(revive_common::EXIT_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
/// Traverses the AST and returns the list of additional errors and warnings.
|
||||
pub fn preprocess_ast(
|
||||
&mut self,
|
||||
sources: &BTreeMap<String, SolcStandardJsonInputSource>,
|
||||
suppressed_warnings: &[Warning],
|
||||
) -> anyhow::Result<()> {
|
||||
let id_paths: BTreeMap<usize, &String> = self
|
||||
.sources
|
||||
.iter()
|
||||
.map(|(path, source)| (source.id, path))
|
||||
.collect();
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
let iter = self.sources.par_iter();
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let iter = self.sources.iter();
|
||||
|
||||
let messages: Vec<SolcStandardJsonOutputError> = iter
|
||||
.flat_map(|(_path, source)| {
|
||||
source
|
||||
.ast
|
||||
.as_ref()
|
||||
.map(|ast| Source::get_messages(ast, &id_paths, sources, suppressed_warnings))
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.collect();
|
||||
self.errors.extend(messages);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Pushes an arbitrary error with path.
|
||||
///
|
||||
/// Please do not push project-general errors without paths here.
|
||||
pub fn push_error(&mut self, path: Option<String>, error: anyhow::Error) {
|
||||
use crate::standard_json::output::error::source_location::SourceLocation;
|
||||
|
||||
self.errors.push(SolcStandardJsonOutputError::new_error(
|
||||
error,
|
||||
path.map(SourceLocation::new),
|
||||
None,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorHandler for Output {
|
||||
fn errors(&self) -> Vec<&SolcStandardJsonOutputError> {
|
||||
self.errors
|
||||
.iter()
|
||||
.filter(|error| error.is_error())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn take_warnings(&mut self) -> Vec<SolcStandardJsonOutputError> {
|
||||
let warnings = self
|
||||
.errors
|
||||
.iter()
|
||||
.filter(|message| message.is_warning())
|
||||
.cloned()
|
||||
.collect();
|
||||
self.errors.retain(|message| !message.is_warning());
|
||||
warnings
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user