Skip to content

Commit f5fe3fa

Browse files
authored
Add default values to compiler arguments (#451)
## Description Adds default values to the compiler arguments below when parsed by `clap`. This does not change previous user-facing behavior as these defaults were implemented using different logic, but improves the UX and the visibility of the exact defaults used. **Example output from `resolc --help`:** (Only affected arguments are shown here, and some of their descriptions have been omitted here.) ``` Options: -O, --optimization <OPTIMIZATION> Set the optimization parameter -O[0 | 1 | 2 | 3 | s | z]. Use `3` for best performance and `z` for minimal size [default: z] --metadata-hash <METADATA_HASH> Set the metadata hash type. Available types: `none`, `ipfs`, `keccak256` [default: keccak256] --heap-size <HEAP_SIZE> The emulated EVM linear heap memory static buffer size in bytes. ... [default: 131072] --stack-size <STACK_SIZE> The contracts total stack size in bytes. ... [default: 131072] ``` ## Resolved Issues Closes #446
1 parent 3bcb62a commit f5fe3fa

File tree

4 files changed

+166
-65
lines changed

4 files changed

+166
-65
lines changed

crates/llvm-context/src/optimizer/settings/mod.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,7 @@ impl Settings {
6464
/// Creates settings from a CLI optimization parameter.
6565
pub fn try_from_cli(value: char) -> anyhow::Result<Self> {
6666
Ok(match value {
67-
'0' => Self::new(
68-
// The middle-end optimization level.
69-
inkwell::OptimizationLevel::None,
70-
// The middle-end size optimization level.
71-
SizeLevel::Zero,
72-
// The back-end optimization level.
73-
inkwell::OptimizationLevel::None,
74-
),
67+
'0' => Self::none(),
7568
'1' => Self::new(
7669
inkwell::OptimizationLevel::Less,
7770
SizeLevel::Zero,
@@ -84,23 +77,14 @@ impl Settings {
8477
// The back-end does not currently distinguish between O1, O2, and O3.
8578
inkwell::OptimizationLevel::Default,
8679
),
87-
'3' => Self::new(
88-
inkwell::OptimizationLevel::Aggressive,
89-
SizeLevel::Zero,
90-
inkwell::OptimizationLevel::Aggressive,
91-
),
80+
'3' => Self::cycles(),
9281
's' => Self::new(
9382
// The middle-end optimization level is ignored when SizeLevel is set.
9483
inkwell::OptimizationLevel::Default,
9584
SizeLevel::S,
9685
inkwell::OptimizationLevel::Aggressive,
9786
),
98-
'z' => Self::new(
99-
// The middle-end optimization level is ignored when SizeLevel is set.
100-
inkwell::OptimizationLevel::Default,
101-
SizeLevel::Z,
102-
inkwell::OptimizationLevel::Aggressive,
103-
),
87+
'z' => Self::size(),
10488
char => anyhow::bail!("Unexpected optimization option '{}'", char),
10589
})
10690
}
@@ -126,6 +110,7 @@ impl Settings {
126110
/// Returns the settings for the optimal size.
127111
pub fn size() -> Self {
128112
Self::new(
113+
// The middle-end optimization level is ignored when SizeLevel is set.
129114
inkwell::OptimizationLevel::Default,
130115
SizeLevel::Z,
131116
inkwell::OptimizationLevel::Aggressive,

crates/resolc/src/resolc/arguments.rs

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ use std::collections::BTreeSet;
44
use std::path::Path;
55
use std::path::PathBuf;
66

7-
use clap::Parser;
7+
use clap::{parser::ValueSource, ArgMatches, CommandFactory, Parser};
88
use path_slash::PathExt;
99
use revive_common::MetadataHash;
10-
use revive_solc_json_interface::SolcStandardJsonOutputError;
10+
use revive_solc_json_interface::{
11+
PolkaVMDefaultHeapMemorySize, PolkaVMDefaultStackMemorySize, SolcStandardJsonOutputError,
12+
};
1113

1214
/// Compiles the provided Solidity input files (or use the standard input if no files
1315
/// are given or "-" is specified as a file name). Outputs the components based on the
@@ -57,8 +59,8 @@ pub struct Arguments {
5759

5860
/// Set the optimization parameter -O[0 | 1 | 2 | 3 | s | z].
5961
/// Use `3` for best performance and `z` for minimal size.
60-
#[arg(short = 'O', long = "optimization")]
61-
pub optimization: Option<char>,
62+
#[arg(short = 'O', long = "optimization", default_value = "z")]
63+
pub optimization: char,
6264

6365
/// Disable the `solc` optimizer.
6466
/// Use it if your project uses the `MSIZE` instruction, or in other cases.
@@ -116,9 +118,8 @@ pub struct Arguments {
116118

117119
/// Set the metadata hash type.
118120
/// Available types: `none`, `ipfs`, `keccak256`.
119-
/// The default is `keccak256`.
120-
#[arg(long)]
121-
pub metadata_hash: Option<String>,
121+
#[arg(long, default_value_t = MetadataHash::Keccak256)]
122+
pub metadata_hash: MetadataHash,
122123

123124
/// Output PolkaVM assembly of the contracts.
124125
#[arg(long = "asm")]
@@ -185,9 +186,9 @@ pub struct Arguments {
185186
/// You are incentiviced to keep this value as small as possible:
186187
/// 1.Increasing the heap size will increase startup costs.
187188
/// 2.The heap size contributes to the total memory size a contract can use,
188-
/// which includes the contracts code size
189-
#[arg(long = "heap-size")]
190-
pub heap_size: Option<u32>,
189+
/// which includes the contracts code size.
190+
#[arg(long = "heap-size", default_value_t = PolkaVMDefaultHeapMemorySize)]
191+
pub heap_size: u32,
191192

192193
/// The contracts total stack size in bytes.
193194
///
@@ -198,16 +199,17 @@ pub struct Arguments {
198199
/// eventually revert execution at runtime!
199200
///
200201
/// You are incentiviced to keep this value as small as possible:
201-
/// 1.Increasing the heap size will increase startup costs.
202+
/// 1.Increasing the stack size will increase startup costs.
202203
/// 2.The stack size contributes to the total memory size a contract can use,
203-
/// which includes the contracts code size
204-
#[arg(long = "stack-size")]
205-
pub stack_size: Option<u32>,
204+
/// which includes the contracts code size.
205+
#[arg(long = "stack-size", default_value_t = PolkaVMDefaultStackMemorySize)]
206+
pub stack_size: u32,
206207
}
207208

208209
impl Arguments {
209210
/// Validates the arguments.
210211
pub fn validate(&self) -> Vec<SolcStandardJsonOutputError> {
212+
let argument_matches = Self::command().get_matches();
211213
let mut messages = Vec::new();
212214

213215
if self.version && std::env::args().count() > 2 {
@@ -226,9 +228,13 @@ impl Arguments {
226228
));
227229
}
228230

229-
if self.metadata_hash == Some(MetadataHash::IPFS.to_string()) {
231+
if self.metadata_hash == MetadataHash::IPFS {
230232
messages.push(SolcStandardJsonOutputError::new_error(
231-
"`IPFS` metadata hash type is not supported. Please use `keccak256` instead.",
233+
format!(
234+
"`{}` metadata hash type is not supported. Please use `{}` instead.",
235+
MetadataHash::IPFS,
236+
MetadataHash::Keccak256,
237+
),
232238
None,
233239
None,
234240
));
@@ -350,34 +356,34 @@ impl Arguments {
350356
}
351357
if self.disable_solc_optimizer {
352358
messages.push(SolcStandardJsonOutputError::new_error(
353-
"Disabling the solc optimizer must specified in standard JSON input settings.",
359+
"Disabling the solc optimizer must be specified in standard JSON input settings.",
354360
None,
355361
None,
356362
));
357363
}
358-
if self.optimization.is_some() {
364+
if Self::is_argument("optimization", &argument_matches) {
359365
messages.push(SolcStandardJsonOutputError::new_error(
360-
"LLVM optimizations must specified in standard JSON input settings.",
366+
"LLVM optimizations must be specified in standard JSON input settings.",
361367
None,
362368
None,
363369
));
364370
}
365-
if self.metadata_hash.is_some() {
371+
if Self::is_argument("metadata_hash", &argument_matches) {
366372
messages.push(SolcStandardJsonOutputError::new_error(
367-
"Metadata hash mode must specified in standard JSON input settings.",
373+
"Metadata hash mode must be specified in standard JSON input settings.",
368374
None,
369375
None,
370376
));
371377
}
372378

373-
if self.heap_size.is_some() {
379+
if Self::is_argument("heap_size", &argument_matches) {
374380
messages.push(SolcStandardJsonOutputError::new_error(
375381
"Heap size must be specified in standard JSON input polkavm memory settings.",
376382
None,
377383
None,
378384
));
379385
}
380-
if self.stack_size.is_some() {
386+
if Self::is_argument("stack_size", &argument_matches) {
381387
messages.push(SolcStandardJsonOutputError::new_error(
382388
"Stack size must be specified in standard JSON input polkavm memory settings.",
383389
None,
@@ -403,6 +409,19 @@ impl Arguments {
403409
messages
404410
}
405411

412+
/// Checks whether the value from the argument with the given `argument_id`
413+
/// came from the command line.
414+
///
415+
/// This can be used for determining if a user has explicitly provided an
416+
/// argument, even if it is the same value as the default one.
417+
///
418+
/// Panics if the `id` is not a valid argument id.
419+
fn is_argument(argument_id: &str, argument_matches: &ArgMatches) -> bool {
420+
argument_matches
421+
.value_source(argument_id)
422+
.is_some_and(|source| source == ValueSource::CommandLine)
423+
}
424+
406425
/// Returns remappings from input paths.
407426
pub fn split_input_files_and_remappings(
408427
&self,

crates/resolc/src/resolc/main.rs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
//! Solidity to PolkaVM compiler binary.
22
3-
use std::str::FromStr;
43
use std::{io::Write, path::PathBuf};
54

65
use clap::error::ErrorKind;
76
use resolc::Process;
8-
use revive_common::{
9-
deserialize_from_str, EVMVersion, MetadataHash, EXIT_CODE_FAILURE, EXIT_CODE_SUCCESS,
10-
};
7+
use revive_common::{deserialize_from_str, EVMVersion, EXIT_CODE_FAILURE, EXIT_CODE_SUCCESS};
118
use revive_llvm_context::{initialize_llvm, DebugConfig, OptimizerSettings, PolkaVMTarget};
129
use revive_solc_json_interface::{
1310
ResolcWarning, SolcStandardJsonInputSettingsPolkaVMMemory,
@@ -32,7 +29,7 @@ fn main() -> anyhow::Result<()> {
3229

3330
let is_standard_json = arguments.standard_json.is_some();
3431
let mut messages = arguments.validate();
35-
if messages.iter().all(|error| error.severity != "error") {
32+
if messages.iter().all(|error| !error.is_error()) {
3633
if !is_standard_json {
3734
std::io::stderr()
3835
.write_all(
@@ -170,27 +167,21 @@ fn main_inner(
170167
None => None,
171168
};
172169

173-
let mut optimizer_settings = match arguments.optimization {
174-
Some(mode) => OptimizerSettings::try_from_cli(mode)?,
175-
None => OptimizerSettings::size(),
176-
};
170+
let mut optimizer_settings = OptimizerSettings::try_from_cli(arguments.optimization)?;
177171
optimizer_settings.is_verify_each_enabled = arguments.llvm_verify_each;
178172
optimizer_settings.is_debug_logging_enabled = arguments.llvm_debug_logging;
179173

180-
let metadata_hash = match arguments.metadata_hash {
181-
Some(ref hash_type) => MetadataHash::from_str(hash_type.as_str())?,
182-
None => MetadataHash::Keccak256,
183-
};
184-
185-
let memory_config =
186-
SolcStandardJsonInputSettingsPolkaVMMemory::new(arguments.heap_size, arguments.stack_size);
174+
let memory_config = SolcStandardJsonInputSettingsPolkaVMMemory::new(
175+
Some(arguments.heap_size),
176+
Some(arguments.stack_size),
177+
);
187178

188179
let build = if arguments.yul {
189180
resolc::yul(
190181
&solc,
191182
input_files.as_slice(),
192183
arguments.libraries.as_slice(),
193-
metadata_hash,
184+
arguments.metadata_hash,
194185
messages,
195186
optimizer_settings,
196187
debug_config,
@@ -200,7 +191,7 @@ fn main_inner(
200191
} else if let Some(standard_json) = arguments.standard_json {
201192
resolc::standard_json(
202193
&solc,
203-
metadata_hash,
194+
arguments.metadata_hash,
204195
messages,
205196
standard_json.map(PathBuf::from),
206197
arguments.base_path,
@@ -215,7 +206,7 @@ fn main_inner(
215206
&solc,
216207
input_files.as_slice(),
217208
arguments.libraries.as_slice(),
218-
metadata_hash,
209+
arguments.metadata_hash,
219210
messages,
220211
evm_version,
221212
format,
@@ -240,7 +231,7 @@ fn main_inner(
240231
&solc,
241232
input_files.as_slice(),
242233
arguments.libraries.as_slice(),
243-
metadata_hash,
234+
arguments.metadata_hash,
244235
messages,
245236
evm_version,
246237
!arguments.disable_solc_optimizer,

0 commit comments

Comments
 (0)