diff --git a/Cargo.lock b/Cargo.lock index 5cd23c4..9b94fc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,12 +91,55 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.82" @@ -406,6 +449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -414,8 +458,22 @@ version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ + "anstream", "anstyle", "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.60", ] [[package]] @@ -424,6 +482,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "colored" version = "2.1.0" @@ -863,6 +927,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -899,6 +969,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "iced-x86" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c447cff8c7f384a7d4f741cfcff32f75f3ad02b406432e8d6c878d56b1edf6b" +dependencies = [ + "lazy_static", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -982,6 +1061,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -1325,7 +1410,7 @@ dependencies = [ [[package]] name = "polkavm" version = "0.10.0" -source = "git+https://github.com/koute/polkavm.git?rev=e2801d9#e2801d9f34211fb5e16aee36a81700ad450c50e5" +source = "git+https://github.com/koute/polkavm.git?rev=266658b#266658b328975ec07ec389f8d966a894f37a8916" dependencies = [ "libc", "log", @@ -1337,7 +1422,7 @@ dependencies = [ [[package]] name = "polkavm-assembler" version = "0.10.0" -source = "git+https://github.com/koute/polkavm.git?rev=e2801d9#e2801d9f34211fb5e16aee36a81700ad450c50e5" +source = "git+https://github.com/koute/polkavm.git?rev=266658b#266658b328975ec07ec389f8d966a894f37a8916" dependencies = [ "log", ] @@ -1345,15 +1430,27 @@ dependencies = [ [[package]] name = "polkavm-common" version = "0.10.0" -source = "git+https://github.com/koute/polkavm.git?rev=e2801d9#e2801d9f34211fb5e16aee36a81700ad450c50e5" +source = "git+https://github.com/koute/polkavm.git?rev=266658b#266658b328975ec07ec389f8d966a894f37a8916" dependencies = [ "log", ] +[[package]] +name = "polkavm-disassembler" +version = "0.10.0" +source = "git+https://github.com/koute/polkavm.git?rev=266658b#266658b328975ec07ec389f8d966a894f37a8916" +dependencies = [ + "clap 4.5.4", + "iced-x86", + "polkavm", + "polkavm-common", + "polkavm-linker", +] + [[package]] name = "polkavm-linker" version = "0.10.0" -source = "git+https://github.com/koute/polkavm.git?rev=e2801d9#e2801d9f34211fb5e16aee36a81700ad450c50e5" +source = "git+https://github.com/koute/polkavm.git?rev=266658b#266658b328975ec07ec389f8d966a894f37a8916" dependencies = [ "gimli", "hashbrown 0.14.5", @@ -1367,7 +1464,7 @@ dependencies = [ [[package]] name = "polkavm-linux-raw" version = "0.10.0" -source = "git+https://github.com/koute/polkavm.git?rev=e2801d9#e2801d9f34211fb5e16aee36a81700ad450c50e5" +source = "git+https://github.com/koute/polkavm.git?rev=266658b#266658b328975ec07ec389f8d966a894f37a8916" [[package]] name = "ppv-lite86" @@ -1707,6 +1804,8 @@ dependencies = [ "num", "once_cell", "path-slash", + "polkavm-common", + "polkavm-disassembler", "rand", "rayon", "regex", @@ -2060,6 +2159,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "structopt" version = "0.3.26" @@ -2266,6 +2371,12 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "valuable" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 9db6a7e..58533cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,9 +27,10 @@ path-slash = "0.2" rayon = "1.8" structopt = { version = "0.3", default-features = false } rand = "0.8" -polkavm-common = { git = "https://github.com/koute/polkavm.git", rev = "e2801d9" } -polkavm-linker = { git = "https://github.com/koute/polkavm.git", rev = "e2801d9" } -polkavm = { git = "https://github.com/koute/polkavm.git", rev = "e2801d9" } +polkavm-common = { git = "https://github.com/koute/polkavm.git", rev = "266658b" } +polkavm-linker = { git = "https://github.com/koute/polkavm.git", rev = "266658b" } +polkavm-disassembler = { git = "https://github.com/koute/polkavm.git", rev = "266658b" } +polkavm = { git = "https://github.com/koute/polkavm.git", rev = "266658b" } alloy-primitives = "0.6" alloy-sol-types = "0.6" env_logger = { version = "0.10.0", default-features = false } diff --git a/crates/benchmarks/benches/execute.rs b/crates/benchmarks/benches/execute.rs index 61594bb..39387b0 100644 --- a/crates/benchmarks/benches/execute.rs +++ b/crates/benchmarks/benches/execute.rs @@ -72,7 +72,7 @@ where group .sample_size(10) .measurement_time(Duration::from_secs(60)); - return group; + group } #[cfg(not(feature = "bench-extensive"))] diff --git a/crates/integration/codesize.json b/crates/integration/codesize.json index efad337..b3eac7a 100644 --- a/crates/integration/codesize.json +++ b/crates/integration/codesize.json @@ -1,7 +1,7 @@ { - "Fibonacci": 5971, + "Computation": 7380, + "ERC20": 51241, "Baseline": 3912, - "ERC20": 53186, - "Flipper": 4354, - "Computation": 7380 + "Fibonacci": 5971, + "Flipper": 4354 } \ No newline at end of file diff --git a/crates/solidity/Cargo.toml b/crates/solidity/Cargo.toml index 2ff421e..7987ade 100644 --- a/crates/solidity/Cargo.toml +++ b/crates/solidity/Cargo.toml @@ -36,6 +36,8 @@ num = { workspace = true } sha3 = { workspace = true } md5 = { workspace = true } inkwell = { workspace = true } +polkavm-disassembler = { workspace = true } +polkavm-common = { workspace = true } revive-common = { path = "../common" } revive-llvm-context = { path = "../llvm-context" } diff --git a/crates/solidity/src/build/contract.rs b/crates/solidity/src/build/contract.rs index d18e582..d29981d 100644 --- a/crates/solidity/src/build/contract.rs +++ b/crates/solidity/src/build/contract.rs @@ -8,6 +8,9 @@ use std::path::Path; use serde::Deserialize; use serde::Serialize; +use polkavm_common::program::ProgramBlob; +use polkavm_disassembler::{Disassembler, DisassemblyFormat}; + use crate::solc::combined_json::contract::Contract as CombinedJsonContract; use crate::solc::standard_json::output::contract::Contract as StandardJsonOutputContract; @@ -53,9 +56,14 @@ impl Contract { overwrite: bool, ) -> anyhow::Result<()> { let file_name = Self::short_path(self.path.as_str()); + let bytescode = self.build.bytecode; if output_assembly { - let file_name = format!("{}.{}", file_name, revive_common::EXTENSION_POLKAVM_ASSEMBLY); + let file_name = format!( + "{}.{}", + file_name, + revive_common::EXTENSION_POLKAVM_ASSEMBLY + ); let mut file_path = path.to_owned(); file_path.push(file_name); @@ -64,11 +72,39 @@ impl Contract { "Refusing to overwrite an existing file {file_path:?} (use --overwrite to force)." ); } else { + let program_blob = ProgramBlob::parse(bytescode.as_slice()).map_err(|error| { + anyhow::anyhow!(format!("Failed to parse program blob: {}", error)) + })?; + + let mut disassembler = Disassembler::new(&program_blob, DisassemblyFormat::Guest) + .map_err(|error| { + anyhow::anyhow!(format!( + "Failed to create disassembler for contract '{:?}'\n\nDue to:\n{}", + &file_path, error + )) + })?; + + let mut disassembled_code = Vec::new(); + disassembler + .disassemble_into(&mut disassembled_code) + .map_err(|error| { + anyhow::anyhow!(format!( + "Failed to disassemble contract '{:?}'\n\nDue to:\n{}\n\nGas details:{:?}\n", + &file_path, error, disassembler.display_gas() + )) + })?; + + let assembly_text = String::from_utf8(disassembled_code) + .map_err(|error| anyhow::anyhow!(format!( + "Failed to convert disassembled code to string for contract '{:?}'\n\nDue to:\n{}", + &file_path, error + )))?; + File::create(&file_path) .map_err(|error| { anyhow::anyhow!("File {:?} creating error: {}", file_path, error) })? - .write_all(self.build.assembly_text.as_bytes()) + .write_all(assembly_text.as_bytes()) .map_err(|error| { anyhow::anyhow!("File {:?} writing error: {}", file_path, error) })?; @@ -89,7 +125,7 @@ impl Contract { .map_err(|error| { anyhow::anyhow!("File {:?} creating error: {}", file_path, error) })? - .write_all(self.build.bytecode.as_slice()) + .write_all(bytescode.as_slice()) .map_err(|error| { anyhow::anyhow!("File {:?} writing error: {}", file_path, error) })?; diff --git a/crates/solidity/src/evmla/ethereal_ir/entry_link.rs b/crates/solidity/src/evmla/ethereal_ir/entry_link.rs index 292913e..ecafd25 100644 --- a/crates/solidity/src/evmla/ethereal_ir/entry_link.rs +++ b/crates/solidity/src/evmla/ethereal_ir/entry_link.rs @@ -23,10 +23,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for EntryLink where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { let target = context .get_function(EtherealIR::DEFAULT_ENTRY_FUNCTION_NAME) .expect("Always exists") diff --git a/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs b/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs index 076f8a6..c702f15 100644 --- a/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs +++ b/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs @@ -1168,8 +1168,7 @@ where .map(Some) } InstructionName::NUMBER => { - revive_llvm_context::polkavm_evm_contract_context::block_number(context) - .map(Some) + revive_llvm_context::polkavm_evm_contract_context::block_number(context).map(Some) } InstructionName::BLOCKHASH => { let arguments = self.pop_arguments_llvm(context); @@ -1244,9 +1243,7 @@ where .to_llvm() .into_pointer_value(); context.build_store( - revive_llvm_context::PolkaVMPointer::new_stack_field( - context, pointer, - ), + revive_llvm_context::PolkaVMPointer::new_stack_field(context, pointer), value, )?; } @@ -1297,9 +1294,7 @@ where assert_eq!(arguments.len(), 1); context.build_store(pointer, arguments.remove(0))?; } - revive_llvm_context::PolkaVMFunctionReturn::Compound { - pointer, .. - } => { + revive_llvm_context::PolkaVMFunctionReturn::Compound { pointer, .. } => { for (index, argument) in arguments.into_iter().enumerate() { let element_pointer = context.build_gep( pointer, diff --git a/crates/solidity/src/evmla/ethereal_ir/function/block/mod.rs b/crates/solidity/src/evmla/ethereal_ir/function/block/mod.rs index b3b75da..9732286 100644 --- a/crates/solidity/src/evmla/ethereal_ir/function/block/mod.rs +++ b/crates/solidity/src/evmla/ethereal_ir/function/block/mod.rs @@ -117,10 +117,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for Block where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { context.set_code_type(self.key.code_type); for element in self.elements.into_iter() { diff --git a/crates/solidity/src/evmla/ethereal_ir/function/mod.rs b/crates/solidity/src/evmla/ethereal_ir/function/mod.rs index ae07430..d1a993b 100644 --- a/crates/solidity/src/evmla/ethereal_ir/function/mod.rs +++ b/crates/solidity/src/evmla/ethereal_ir/function/mod.rs @@ -252,12 +252,10 @@ impl Function { destination.to_owned() - num::BigUint::from(1u64 << 32), ) } - Element::Tag(destination) => { - revive_llvm_context::PolkaVMFunctionBlockKey::new( - code_type, - destination.to_owned(), - ) - } + Element::Tag(destination) => revive_llvm_context::PolkaVMFunctionBlockKey::new( + code_type, + destination.to_owned(), + ), Element::ReturnAddress(output_size) => { block_element.instruction = Instruction::recursive_return(1 + output_size, instruction); @@ -316,12 +314,10 @@ impl Function { destination.to_owned() - num::BigUint::from(1u64 << 32), ) } - Element::Tag(destination) => { - revive_llvm_context::PolkaVMFunctionBlockKey::new( - code_type, - destination.to_owned(), - ) - } + Element::Tag(destination) => revive_llvm_context::PolkaVMFunctionBlockKey::new( + code_type, + destination.to_owned(), + ), element => { return Err(anyhow::anyhow!( "The {} instruction expected a tag or return address, found {}", @@ -346,8 +342,7 @@ impl Function { .. } => { let tag: num::BigUint = tag.parse().expect("Always valid"); - let block_key = - revive_llvm_context::PolkaVMFunctionBlockKey::new(code_type, tag); + let block_key = revive_llvm_context::PolkaVMFunctionBlockKey::new(code_type, tag); queue_element.predecessor = Some((queue_element.block_key.clone(), instance)); queue_element.block_key = block_key.clone(); @@ -1014,21 +1009,16 @@ impl Function { block_stack: &mut Stack, block_element: &mut BlockElement, version: &semver::Version, - ) -> anyhow::Result<( - revive_llvm_context::PolkaVMFunctionBlockKey, - Vec, - )> { + ) -> anyhow::Result<(revive_llvm_context::PolkaVMFunctionBlockKey, Vec)> { let return_address_offset = block_stack.elements.len() - 2 - recursive_function.input_size; let input_arguments_offset = return_address_offset + 1; let callee_tag_offset = input_arguments_offset + recursive_function.input_size; let return_address = match block_stack.elements[return_address_offset] { - Element::Tag(ref return_address) => { - revive_llvm_context::PolkaVMFunctionBlockKey::new( - block_key.code_type, - return_address.to_owned(), - ) - } + Element::Tag(ref return_address) => revive_llvm_context::PolkaVMFunctionBlockKey::new( + block_key.code_type, + return_address.to_owned(), + ), ref element => anyhow::bail!("Expected the function return address, found {}", element), }; let mut stack = Stack::with_capacity(1 + recursive_function.input_size); @@ -1177,17 +1167,16 @@ where output_size, Some(inkwell::module::Linkage::Private), )?; - function.borrow_mut().set_evmla_data( - revive_llvm_context::PolkaVMFunctionEVMLAData::new(self.stack_size), - ); + function + .borrow_mut() + .set_evmla_data(revive_llvm_context::PolkaVMFunctionEVMLAData::new( + self.stack_size, + )); Ok(()) } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { context.set_current_function(self.name.as_str())?; for (key, blocks) in self.blocks.iter() { diff --git a/crates/solidity/src/evmla/ethereal_ir/mod.rs b/crates/solidity/src/evmla/ethereal_ir/mod.rs index dabffa4..4dd229f 100644 --- a/crates/solidity/src/evmla/ethereal_ir/mod.rs +++ b/crates/solidity/src/evmla/ethereal_ir/mod.rs @@ -81,10 +81,7 @@ impl EtherealIR { &instructions[offset..], )?; blocks.insert( - revive_llvm_context::PolkaVMFunctionBlockKey::new( - code_type, - block.key.tag.clone(), - ), + revive_llvm_context::PolkaVMFunctionBlockKey::new(code_type, block.key.tag.clone()), block, ); offset += size; @@ -111,10 +108,7 @@ where Ok(()) } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { context.evmla_mut().stack = vec![]; self.entry_function.into_llvm(context)?; diff --git a/crates/solidity/src/project/contract/ir/evmla.rs b/crates/solidity/src/project/contract/ir/evmla.rs index 36ea7c3..9a1367d 100644 --- a/crates/solidity/src/project/contract/ir/evmla.rs +++ b/crates/solidity/src/project/contract/ir/evmla.rs @@ -41,10 +41,7 @@ where self.assembly.declare(context) } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { self.assembly.into_llvm(context) } } diff --git a/crates/solidity/src/project/contract/ir/mod.rs b/crates/solidity/src/project/contract/ir/mod.rs index 90adeb1..901bacb 100644 --- a/crates/solidity/src/project/contract/ir/mod.rs +++ b/crates/solidity/src/project/contract/ir/mod.rs @@ -83,10 +83,7 @@ where } } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { match self { Self::Yul(inner) => inner.into_llvm(context), Self::EVMLA(inner) => inner.into_llvm(context), diff --git a/crates/solidity/src/project/contract/ir/yul.rs b/crates/solidity/src/project/contract/ir/yul.rs index b15c07c..97aa7ba 100644 --- a/crates/solidity/src/project/contract/ir/yul.rs +++ b/crates/solidity/src/project/contract/ir/yul.rs @@ -42,10 +42,7 @@ where self.object.declare(context) } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { self.object.into_llvm(context) } } diff --git a/crates/solidity/src/project/contract/mod.rs b/crates/solidity/src/project/contract/mod.rs index 602c90e..eae30ad 100644 --- a/crates/solidity/src/project/contract/mod.rs +++ b/crates/solidity/src/project/contract/mod.rs @@ -148,8 +148,7 @@ impl Contract { context.set_yul_data(yul_data); } IR::EVMLA(_) => { - let evmla_data = - revive_llvm_context::PolkaVMContextEVMLAData::new(version.default); + let evmla_data = revive_llvm_context::PolkaVMContextEVMLAData::new(version.default); context.set_evmla_data(evmla_data); } IR::LLVMIR(_) => {} @@ -201,10 +200,7 @@ where self.ir.declare(context) } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { self.ir.into_llvm(context) } } diff --git a/crates/solidity/src/tests/cli-tests/tests/asm.test.ts b/crates/solidity/src/tests/cli-tests/tests/asm.test.ts index 7c88a0c..299bcb9 100644 --- a/crates/solidity/src/tests/cli-tests/tests/asm.test.ts +++ b/crates/solidity/src/tests/cli-tests/tests/asm.test.ts @@ -14,19 +14,23 @@ describe("Run with --asm by default", () => { }); it("--asm output is presented", () => { - expect(result.output).toMatch(/(__entry:)/i); + const expectedPatterns = [/(deploy)/i, /(call)/i, /(seal_return)/i]; + + for (const pattern of expectedPatterns) { + expect(result.output).toMatch(pattern); + } }); - it("solc exit code == zksolc exit code", () => { - const command = `solc ${paths.pathToBasicSolContract} --asm`; - const solcResult = executeCommand(command); - expect(solcResult.exitCode).toBe(result.exitCode); + const command = `solc ${paths.pathToBasicSolContract} --asm`; + const solcResult = executeCommand(command); + expect(solcResult.exitCode).toBe(result.exitCode); }); it("run invalid: zksolc --asm", () => { expect(resultInvalid.output).toMatch(/(No input sources specified|Compilation aborted)/i); }); + it("Invalid command exit code = 1", () => { expect(resultInvalid.exitCode).toBe(1); }); @@ -36,4 +40,4 @@ describe("Run with --asm by default", () => { const solcResult = executeCommand(command); expect(solcResult.exitCode).toBe(resultInvalid.exitCode); }); -}); +}); \ No newline at end of file diff --git a/crates/solidity/src/tests/cli-tests/tsconfig.json b/crates/solidity/src/tests/cli-tests/tsconfig.json index 9a23735..30b9760 100644 --- a/crates/solidity/src/tests/cli-tests/tsconfig.json +++ b/crates/solidity/src/tests/cli-tests/tsconfig.json @@ -3,6 +3,5 @@ "target": "ES6", "module": "CommonJS", "outDir": "./dist", - "rootDir": "./src" } } diff --git a/crates/solidity/src/yul/parser/statement/block.rs b/crates/solidity/src/yul/parser/statement/block.rs index 622c206..ffa2c63 100644 --- a/crates/solidity/src/yul/parser/statement/block.rs +++ b/crates/solidity/src/yul/parser/statement/block.rs @@ -132,10 +132,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for Block where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { let current_function = context.current_function().borrow().name().to_owned(); let current_block = context.basic_block(); diff --git a/crates/solidity/src/yul/parser/statement/code.rs b/crates/solidity/src/yul/parser/statement/code.rs index 1460d00..6910da9 100644 --- a/crates/solidity/src/yul/parser/statement/code.rs +++ b/crates/solidity/src/yul/parser/statement/code.rs @@ -59,10 +59,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for Code where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { self.block.into_llvm(context)?; Ok(()) diff --git a/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs b/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs index 65469bc..fb6c7fe 100644 --- a/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs +++ b/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs @@ -911,9 +911,7 @@ impl FunctionCall { Ok(Some(context.integer_const(256, 0).as_basic_value_enum())) } - Name::CallValue => { - revive_llvm_context::polkavm_evm_ether_gas::value(context).map(Some) - } + Name::CallValue => revive_llvm_context::polkavm_evm_ether_gas::value(context).map(Some), Name::Gas => revive_llvm_context::polkavm_evm_ether_gas::gas(context).map(Some), Name::Balance => { let arguments = self.pop_arguments_llvm::(context)?; @@ -940,8 +938,7 @@ impl FunctionCall { .map(Some) } Name::Number => { - revive_llvm_context::polkavm_evm_contract_context::block_number(context) - .map(Some) + revive_llvm_context::polkavm_evm_contract_context::block_number(context).map(Some) } Name::BlockHash => { let arguments = self.pop_arguments_llvm::(context)?; diff --git a/crates/solidity/src/yul/parser/statement/expression/mod.rs b/crates/solidity/src/yul/parser/statement/expression/mod.rs index 14bb021..10432dc 100644 --- a/crates/solidity/src/yul/parser/statement/expression/mod.rs +++ b/crates/solidity/src/yul/parser/statement/expression/mod.rs @@ -137,9 +137,7 @@ impl Expression { match constant { Some(constant) => Ok(Some( - revive_llvm_context::PolkaVMArgument::new_with_constant( - value, constant, - ), + revive_llvm_context::PolkaVMArgument::new_with_constant(value, constant), )), None => Ok(Some(value.into())), } diff --git a/crates/solidity/src/yul/parser/statement/for_loop.rs b/crates/solidity/src/yul/parser/statement/for_loop.rs index 95c6171..98387ec 100644 --- a/crates/solidity/src/yul/parser/statement/for_loop.rs +++ b/crates/solidity/src/yul/parser/statement/for_loop.rs @@ -64,10 +64,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for ForLoop where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { self.initializer.into_llvm(context)?; let condition_block = context.append_basic_block("for_condition"); diff --git a/crates/solidity/src/yul/parser/statement/function_definition.rs b/crates/solidity/src/yul/parser/statement/function_definition.rs index 2be27c6..14f1fe0 100644 --- a/crates/solidity/src/yul/parser/statement/function_definition.rs +++ b/crates/solidity/src/yul/parser/statement/function_definition.rs @@ -109,9 +109,10 @@ impl FunctionDefinition { arguments.remove(0); } - if identifier.inner.contains( - revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER, - ) && !arguments.is_empty() + if identifier + .inner + .contains(revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER) + && !arguments.is_empty() { return Err(ParserError::InvalidNumberOfArguments { location, diff --git a/crates/solidity/src/yul/parser/statement/if_conditional.rs b/crates/solidity/src/yul/parser/statement/if_conditional.rs index bfdd2da..03fd451 100644 --- a/crates/solidity/src/yul/parser/statement/if_conditional.rs +++ b/crates/solidity/src/yul/parser/statement/if_conditional.rs @@ -52,10 +52,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for IfConditional where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { let condition = self .condition .into_llvm(context)? diff --git a/crates/solidity/src/yul/parser/statement/object.rs b/crates/solidity/src/yul/parser/statement/object.rs index f9cd994..f0ff91b 100644 --- a/crates/solidity/src/yul/parser/statement/object.rs +++ b/crates/solidity/src/yul/parser/statement/object.rs @@ -219,16 +219,11 @@ where Ok(()) } - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { if self.identifier.ends_with("_deployed") { - revive_llvm_context::PolkaVMRuntimeCodeFunction::new(self.code) - .into_llvm(context)?; + revive_llvm_context::PolkaVMRuntimeCodeFunction::new(self.code).into_llvm(context)?; } else { - revive_llvm_context::PolkaVMDeployCodeFunction::new(self.code) - .into_llvm(context)?; + revive_llvm_context::PolkaVMDeployCodeFunction::new(self.code).into_llvm(context)?; } match self.inner_object { diff --git a/crates/solidity/src/yul/parser/statement/switch/mod.rs b/crates/solidity/src/yul/parser/statement/switch/mod.rs index b21a953..e3173e4 100644 --- a/crates/solidity/src/yul/parser/statement/switch/mod.rs +++ b/crates/solidity/src/yul/parser/statement/switch/mod.rs @@ -122,10 +122,7 @@ impl revive_llvm_context::PolkaVMWriteLLVM for Switch where D: revive_llvm_context::PolkaVMDependency + Clone, { - fn into_llvm( - self, - context: &mut revive_llvm_context::PolkaVMContext, - ) -> anyhow::Result<()> { + fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { let scrutinee = self.expression.into_llvm(context)?; if self.cases.is_empty() { diff --git a/crates/solidity/src/zksolc/arguments.rs b/crates/solidity/src/zksolc/arguments.rs index d93a741..5a1acba 100644 --- a/crates/solidity/src/zksolc/arguments.rs +++ b/crates/solidity/src/zksolc/arguments.rs @@ -212,7 +212,9 @@ impl Arguments { if self.yul || self.llvm_ir || self.zkasm { if self.base_path.is_some() { - anyhow::bail!("`base-path` is not used in Yul, LLVM IR and PolkaVM assembly modes."); + anyhow::bail!( + "`base-path` is not used in Yul, LLVM IR and PolkaVM assembly modes." + ); } if !self.include_paths.is_empty() { anyhow::bail!( diff --git a/crates/solidity/src/zksolc/main.rs b/crates/solidity/src/zksolc/main.rs index df199ea..b155007 100644 --- a/crates/solidity/src/zksolc/main.rs +++ b/crates/solidity/src/zksolc/main.rs @@ -6,6 +6,9 @@ use std::str::FromStr; use self::arguments::Arguments; +use polkavm_common::program::ProgramBlob; +use polkavm_disassembler::{Disassembler, DisassemblyFormat}; + /// The rayon worker stack size. const RAYON_WORKER_STACK_SIZE: usize = 16 * 1024 * 1024; @@ -190,18 +193,41 @@ fn main_inner() -> anyhow::Result<()> { ); } else if arguments.output_assembly || arguments.output_binary { for (path, contract) in build.contracts.into_iter() { + let bytescode = contract.build.bytecode; + if arguments.output_assembly { - println!( - "Contract `{}` assembly:\n\n{}", - path, contract.build.assembly_text - ); + let program_blob = ProgramBlob::parse(bytescode.as_slice()).map_err(|error| { + anyhow::anyhow!(format!("Failed to parse program blob: {}", error)) + })?; + + let mut disassembler = Disassembler::new(&program_blob, DisassemblyFormat::Guest) + .map_err(|error| { + anyhow::anyhow!(format!( + "Failed to create disassembler for contract '{}'\n\nDue to:\n{}", + path, error + )) + })?; + + let mut disassembled_code = Vec::new(); + disassembler + .disassemble_into(&mut disassembled_code) + .map_err(|error| { + anyhow::anyhow!(format!( + "Failed to disassemble contract '{}'\n\nDue to:\n{}\n\nGas details:{:?}\n", + path, error, disassembler.display_gas() + )) + })?; + + let assembly_text = String::from_utf8(disassembled_code) + .map_err(|error| anyhow::anyhow!(format!( + "Failed to convert disassembled code to string for contract '{}'\n\nDue to:\n{}", + path, error + )))?; + + println!("Contract `{}` assembly:\n\n{}", path, assembly_text); } if arguments.output_binary { - println!( - "Contract `{}` bytecode: 0x{}", - path, - hex::encode(contract.build.bytecode) - ); + println!("Contract `{}` bytecode: 0x{}", path, hex::encode(bytescode)); } } } else {