mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-12 22:11:01 +00:00
Merge branch 'main' into cl/optsize
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
pub mod ir_type;
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::Deserialize;
|
||||
@@ -16,6 +17,14 @@ pub struct DebugConfig {
|
||||
pub output_directory: Option<PathBuf>,
|
||||
/// Whether debug info should be emitted.
|
||||
pub emit_debug_info: bool,
|
||||
/// The YUL debug output file path.
|
||||
///
|
||||
/// Is expected to be configured when running in YUL mode.
|
||||
pub contract_path: Option<PathBuf>,
|
||||
/// The YUL input file path.
|
||||
///
|
||||
/// Is expected to be configured when not running in YUL mode.
|
||||
pub yul_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl DebugConfig {
|
||||
@@ -24,15 +33,41 @@ impl DebugConfig {
|
||||
Self {
|
||||
output_directory,
|
||||
emit_debug_info,
|
||||
contract_path: None,
|
||||
yul_path: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the current YUL path.
|
||||
pub fn set_yul_path(&mut self, yul_path: &Path) {
|
||||
self.yul_path = yul_path.to_path_buf().into();
|
||||
}
|
||||
|
||||
/// Set the current contract path.
|
||||
pub fn set_contract_path(&mut self, contract_path: &str) {
|
||||
self.contract_path = self.yul_source_path(contract_path);
|
||||
}
|
||||
|
||||
/// Returns with the following precedence:
|
||||
/// 1. The YUL source path if it was configured.
|
||||
/// 2. The source YUL path from the debug output dir if it was configured.
|
||||
/// 3. `None` if there is no debug output directory.
|
||||
pub fn yul_source_path(&self, contract_path: &str) -> Option<PathBuf> {
|
||||
if let Some(path) = self.yul_path.as_ref() {
|
||||
return Some(path.clone());
|
||||
}
|
||||
|
||||
self.output_directory.as_ref().map(|output_directory| {
|
||||
let mut file_path = output_directory.to_owned();
|
||||
let full_file_name = Self::full_file_name(contract_path, None, IRType::Yul);
|
||||
file_path.push(full_file_name);
|
||||
file_path
|
||||
})
|
||||
}
|
||||
|
||||
/// Dumps the Yul IR.
|
||||
pub fn dump_yul(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
|
||||
if let Some(output_directory) = self.output_directory.as_ref() {
|
||||
let mut file_path = output_directory.to_owned();
|
||||
let full_file_name = Self::full_file_name(contract_path, None, IRType::Yul);
|
||||
file_path.push(full_file_name);
|
||||
if let Some(file_path) = self.yul_source_path(contract_path) {
|
||||
std::fs::write(file_path, code)?;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,11 +51,20 @@ pub struct DebugInfo<'ctx> {
|
||||
|
||||
impl<'ctx> DebugInfo<'ctx> {
|
||||
/// A shortcut constructor.
|
||||
pub fn new(module: &inkwell::module::Module<'ctx>) -> Self {
|
||||
pub fn new(
|
||||
module: &inkwell::module::Module<'ctx>,
|
||||
debug_config: &crate::debug_config::DebugConfig,
|
||||
) -> Self {
|
||||
let module_name = module.get_name().to_string_lossy();
|
||||
let yul_name = debug_config
|
||||
.contract_path
|
||||
.as_ref()
|
||||
.map(|path| path.display().to_string());
|
||||
|
||||
let (builder, compile_unit) = module.create_debug_info_builder(
|
||||
true,
|
||||
inkwell::debug_info::DWARFSourceLanguage::C,
|
||||
module.get_name().to_string_lossy().as_ref(),
|
||||
yul_name.as_deref().unwrap_or_else(|| module_name.as_ref()),
|
||||
"",
|
||||
"",
|
||||
false,
|
||||
|
||||
@@ -247,7 +247,7 @@ where
|
||||
let intrinsics = Intrinsics::new(llvm, &module);
|
||||
let llvm_runtime = LLVMRuntime::new(llvm, &module, &optimizer);
|
||||
let debug_info = debug_config.emit_debug_info.then(|| {
|
||||
let debug_info = DebugInfo::new(&module);
|
||||
let debug_info = DebugInfo::new(&module, &debug_config);
|
||||
debug_info.initialize_module(llvm, &module);
|
||||
debug_info
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ pub fn yul<T: Compiler>(
|
||||
solc: &mut T,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
mut debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||
) -> anyhow::Result<Build> {
|
||||
@@ -77,6 +77,7 @@ pub fn yul<T: Compiler>(
|
||||
let solc_validator = Some(&*solc);
|
||||
let project = Project::try_from_yul_path(path, solc_validator)?;
|
||||
|
||||
debug_config.set_yul_path(path);
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
|
||||
@@ -77,7 +77,7 @@ impl Contract {
|
||||
project: Project,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
mut debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||
) -> anyhow::Result<ContractBuild> {
|
||||
@@ -117,6 +117,7 @@ impl Contract {
|
||||
_ => llvm.create_module(self.path.as_str()),
|
||||
};
|
||||
|
||||
debug_config.set_contract_path(&self.path);
|
||||
let mut context = revive_llvm_context::PolkaVMContext::new(
|
||||
&llvm,
|
||||
module,
|
||||
|
||||
@@ -45,8 +45,6 @@ impl Compiler for SolcCompiler {
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
) -> anyhow::Result<SolcStandardJsonOutput> {
|
||||
let version = self.version()?.validate(&include_paths)?.default;
|
||||
|
||||
let mut command = std::process::Command::new(self.executable.as_str());
|
||||
command.stdin(std::process::Stdio::piped());
|
||||
command.stdout(std::process::Stdio::piped());
|
||||
@@ -65,7 +63,7 @@ impl Compiler for SolcCompiler {
|
||||
command.arg(allow_paths);
|
||||
}
|
||||
|
||||
input.normalize(&version);
|
||||
input.normalize();
|
||||
|
||||
let suppressed_warnings = input.suppressed_warnings.take().unwrap_or_default();
|
||||
|
||||
|
||||
@@ -40,8 +40,7 @@ impl Compiler for SoljsonCompiler {
|
||||
anyhow::bail!("configuring allow paths is not supported with solJson")
|
||||
}
|
||||
|
||||
let version = self.version()?.validate(&include_paths)?.default;
|
||||
input.normalize(&version);
|
||||
input.normalize();
|
||||
|
||||
let suppressed_warnings = input.suppressed_warnings.take().unwrap_or_default();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pub use self::combined_json::contract::Contract as CombinedJsonContract;
|
||||
pub use self::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
|
||||
pub use self::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
pub use self::standard_json::input::settings::metadata_hash::MetadataHash as SolcStandardJsonInputSettingsMetadataHash;
|
||||
pub use self::standard_json::input::settings::optimizer::yul_details::YulDetails as SolcStandardJsonInputSettingsYulOptimizerDetails;
|
||||
pub use self::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
pub use self::standard_json::input::settings::polkavm::memory::MemoryConfig as SolcStandardJsonInputSettingsPolkaVMMemory;
|
||||
pub use self::standard_json::input::settings::polkavm::memory::DEFAULT_HEAP_SIZE as PolkaVMDefaultHeapMemorySize;
|
||||
|
||||
@@ -140,7 +140,7 @@ impl Input {
|
||||
}
|
||||
|
||||
/// Sets the necessary defaults.
|
||||
pub fn normalize(&mut self, version: &semver::Version) {
|
||||
self.settings.normalize(version);
|
||||
pub fn normalize(&mut self) {
|
||||
self.settings.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ impl Settings {
|
||||
}
|
||||
|
||||
/// Sets the necessary defaults.
|
||||
pub fn normalize(&mut self, version: &semver::Version) {
|
||||
pub fn normalize(&mut self) {
|
||||
self.polkavm = None;
|
||||
self.optimizer.normalize(version);
|
||||
self.optimizer.normalize();
|
||||
}
|
||||
|
||||
/// Parses the library list and returns their double hashmap with path and name as keys.
|
||||
|
||||
@@ -3,37 +3,54 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::standard_json::input::settings::optimizer::yul_details::YulDetails;
|
||||
|
||||
/// The `solc --standard-json` input settings optimizer details.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Details {
|
||||
/// Whether the pass is enabled.
|
||||
pub peephole: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub peephole: Option<bool>,
|
||||
/// Whether the pass is enabled.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub inliner: Option<bool>,
|
||||
/// Whether the pass is enabled.
|
||||
pub jumpdest_remover: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub jumpdest_remover: Option<bool>,
|
||||
/// Whether the pass is enabled.
|
||||
pub order_literals: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub order_literals: Option<bool>,
|
||||
/// Whether the pass is enabled.
|
||||
pub deduplicate: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub deduplicate: Option<bool>,
|
||||
/// Whether the pass is enabled.
|
||||
pub cse: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub cse: Option<bool>,
|
||||
/// Whether the pass is enabled.
|
||||
pub constant_optimizer: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub constant_optimizer: Option<bool>,
|
||||
/// Whether the YUL optimizer is enabled.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub yul: Option<bool>,
|
||||
/// The YUL optimizer configuration.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub yul_details: Option<YulDetails>,
|
||||
}
|
||||
|
||||
impl Details {
|
||||
/// A shortcut constructor.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
peephole: bool,
|
||||
peephole: Option<bool>,
|
||||
inliner: Option<bool>,
|
||||
jumpdest_remover: bool,
|
||||
order_literals: bool,
|
||||
deduplicate: bool,
|
||||
cse: bool,
|
||||
constant_optimizer: bool,
|
||||
jumpdest_remover: Option<bool>,
|
||||
order_literals: Option<bool>,
|
||||
deduplicate: Option<bool>,
|
||||
cse: Option<bool>,
|
||||
constant_optimizer: Option<bool>,
|
||||
yul: Option<bool>,
|
||||
yul_details: Option<YulDetails>,
|
||||
) -> Self {
|
||||
Self {
|
||||
peephole,
|
||||
@@ -43,10 +60,11 @@ impl Details {
|
||||
deduplicate,
|
||||
cse,
|
||||
constant_optimizer,
|
||||
yul,
|
||||
yul_details,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a set of disabled optimizations.
|
||||
pub fn disabled(version: &semver::Version) -> Self {
|
||||
let inliner = if version >= &semver::Version::new(0, 8, 5) {
|
||||
Some(false)
|
||||
@@ -54,6 +72,16 @@ impl Details {
|
||||
None
|
||||
};
|
||||
|
||||
Self::new(false, inliner, false, false, false, false, false)
|
||||
Self::new(
|
||||
Some(false),
|
||||
inliner,
|
||||
Some(false),
|
||||
Some(false),
|
||||
Some(false),
|
||||
Some(false),
|
||||
Some(false),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! The `solc --standard-json` input settings optimizer.
|
||||
|
||||
pub mod details;
|
||||
pub mod yul_details;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -41,13 +42,8 @@ impl Optimizer {
|
||||
}
|
||||
|
||||
/// Sets the necessary defaults.
|
||||
pub fn normalize(&mut self, version: &semver::Version) {
|
||||
pub fn normalize(&mut self) {
|
||||
self.mode = None;
|
||||
self.fallback_to_optimizing_for_size = None;
|
||||
self.details = if version >= &semver::Version::new(0, 5, 5) {
|
||||
Some(Details::disabled(version))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//! The `solc --standard-json` input settings YUL optimizer details.
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
/// The `solc --standard-json` input settings optimizer YUL details.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct YulDetails {
|
||||
/// Whether the stack allocation pass is enabled.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub stack_allocation: Option<bool>,
|
||||
/// The optimization step sequence string.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub optimizer_steps: Option<String>,
|
||||
}
|
||||
|
||||
impl YulDetails {
|
||||
/// A shortcut constructor.
|
||||
pub fn new(stack_allocation: Option<bool>, optimizer_steps: Option<String>) -> Self {
|
||||
Self {
|
||||
stack_allocation,
|
||||
optimizer_steps,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,6 +124,7 @@ impl FunctionCall {
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
let location = self.location;
|
||||
context.set_debug_location(location.line, 0, None)?;
|
||||
|
||||
match self.name {
|
||||
Name::UserDefined(name) => {
|
||||
|
||||
@@ -54,6 +54,7 @@ where
|
||||
{
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
let binding_pointer = context.build_alloca(context.word_type(), "if_condition");
|
||||
context.set_debug_location(self.location.line, 0, None)?;
|
||||
let condition = self
|
||||
.condition
|
||||
.into_llvm(&[("todo".to_string(), binding_pointer)], context)?
|
||||
|
||||
Reference in New Issue
Block a user