diff --git a/Changelog.md b/Changelog.md index 97fd17763..3f7ea97c5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,7 +7,7 @@ Language Features: Compiler Features: * Commandline Interface: Accept nested brackets in step sequences passed to ``--yul-optimizations``. * Commandline Interface: Add ``--debug-info`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code. - * Commandline Interface: Support ``--asm``, ``--bin``, ``--ir-optimized`` and ``--ewasm`` output selection options in assembler mode. + * Commandline Interface: Support ``--asm``, ``--bin``, ``--ir-optimized``, ``--ewasm`` and ``--ewasm-ir`` output selection options in assembler mode. * Commandline Interface: Use different colors when printing errors, warnings and infos. * SMTChecker: Output values for ``block.*``, ``msg.*`` and ``tx.*`` variables that are present in the called functions. * SMTChecker: Report contract invariants and reentrancy properties. This can be enabled via the CLI option ``--model-checker-invariants`` or the Standard JSON option ``settings.modelChecker.invariants``. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 49aa1b87f..1d069f925 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -1055,9 +1055,7 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: stack.translate(yul::AssemblyStack::Language::Ewasm); stack.optimize(); - // TODO: This isn't ewasm but it's only present when we're doing Yul->EWASM translation. - // It should get its own output flag in the future. - if (m_options.compiler.outputs.ewasm) + if (m_options.compiler.outputs.ewasmIR) { sout() << endl << "==========================" << endl; sout() << endl << "Translated source:" << endl; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 4bb5dfce6..9356c9662 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -446,15 +446,17 @@ bool CommandLineParser::parseOutputSelection() { static auto outputSupported = [](InputMode _mode, string_view _outputName) { - static set const compilerModeOutputs = + static set const compilerModeOutputs = ( CompilerOutputs::componentMap() | ranges::views::keys | - ranges::to(); + ranges::to() + ) - set{CompilerOutputs::componentName(&CompilerOutputs::ewasmIR)}; static set const assemblerModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), CompilerOutputs::componentName(&CompilerOutputs::binary), CompilerOutputs::componentName(&CompilerOutputs::irOptimized), CompilerOutputs::componentName(&CompilerOutputs::ewasm), + CompilerOutputs::componentName(&CompilerOutputs::ewasmIR), }; switch (_mode) @@ -487,6 +489,7 @@ bool CommandLineParser::parseOutputSelection() m_options.compiler.outputs.binary = true; m_options.compiler.outputs.irOptimized = true; m_options.compiler.outputs.ewasm = true; + m_options.compiler.outputs.ewasmIR = true; } vector unsupportedOutputs; @@ -709,6 +712,7 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::ir).c_str(), "Intermediate Representation (IR) of all contracts (EXPERIMENTAL).") (CompilerOutputs::componentName(&CompilerOutputs::irOptimized).c_str(), "Optimized intermediate Representation (IR) of all contracts (EXPERIMENTAL).") (CompilerOutputs::componentName(&CompilerOutputs::ewasm).c_str(), "Ewasm text representation of all contracts (EXPERIMENTAL).") + (CompilerOutputs::componentName(&CompilerOutputs::ewasmIR).c_str(), "Intermediate representation (IR) converted to a form that can be translated directly into Ewasm text representation (EXPERIMENTAL).") (CompilerOutputs::componentName(&CompilerOutputs::signatureHashes).c_str(), "Function signature hashes of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecUser).c_str(), "Natspec user documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecDev).c_str(), "Natspec developer documentation of all contracts.") @@ -923,11 +927,12 @@ bool CommandLineParser::processArgs() if (!checkMutuallyExclusive({g_strColor, g_strNoColor})) return false; - array const conflictingWithStopAfter{ + array const conflictingWithStopAfter{ CompilerOutputs::componentName(&CompilerOutputs::binary), CompilerOutputs::componentName(&CompilerOutputs::ir), CompilerOutputs::componentName(&CompilerOutputs::irOptimized), CompilerOutputs::componentName(&CompilerOutputs::ewasm), + CompilerOutputs::componentName(&CompilerOutputs::ewasmIR), g_strGas, CompilerOutputs::componentName(&CompilerOutputs::asm_), CompilerOutputs::componentName(&CompilerOutputs::asmJson), diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 27a64c7b9..a1d13c690 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -78,6 +78,7 @@ struct CompilerOutputs {"ir", &CompilerOutputs::ir}, {"ir-optimized", &CompilerOutputs::irOptimized}, {"ewasm", &CompilerOutputs::ewasm}, + {"ewasm-ir", &CompilerOutputs::ewasmIR}, {"hashes", &CompilerOutputs::signatureHashes}, {"userdoc", &CompilerOutputs::natspecUser}, {"devdoc", &CompilerOutputs::natspecDev}, @@ -97,6 +98,7 @@ struct CompilerOutputs bool ir = false; bool irOptimized = false; bool ewasm = false; + bool ewasmIR = false; bool signatureHashes = false; bool natspecUser = false; bool natspecDev = false; diff --git a/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/args b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/args new file mode 100644 index 000000000..7c6526b56 --- /dev/null +++ b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/args @@ -0,0 +1 @@ +--assemble --optimize --yul-dialect evm --machine ewasm --ewasm-ir diff --git a/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/err b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/err new file mode 100644 index 000000000..014a1178f --- /dev/null +++ b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/input.yul b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/input.yul new file mode 100644 index 000000000..4fa5ef66f --- /dev/null +++ b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/input.yul @@ -0,0 +1,4 @@ +{ + let x := 42 + sstore(0, x) +} diff --git a/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/output b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/output new file mode 100644 index 000000000..3124db17d --- /dev/null +++ b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_ir_only/output @@ -0,0 +1,34 @@ + +======= evm_to_wasm_output_selection_ewasm_ir_only/input.yul (Ewasm) ======= + +========================== + +Translated source: +object "object" { + code { + function main() + { + let hi := i64.shl(i64.extend_i32_u(bswap32(i32.wrap_i64(0))), 32) + let y := i64.or(hi, i64.extend_i32_u(bswap32(i32.wrap_i64(i64.shr_u(0, 32))))) + i64.store(0:i32, y) + i64.store(i32.add(0:i32, 8:i32), y) + i64.store(i32.add(0:i32, 16:i32), y) + i64.store(i32.add(0:i32, 24:i32), y) + i64.store(32:i32, y) + i64.store(i32.add(32:i32, 8:i32), y) + i64.store(i32.add(32:i32, 16:i32), y) + let hi_1 := i64.shl(i64.extend_i32_u(bswap32(i32.wrap_i64(42))), 32) + i64.store(i32.add(32:i32, 24:i32), i64.or(hi_1, i64.extend_i32_u(bswap32(i32.wrap_i64(i64.shr_u(42, 32)))))) + eth.storageStore(0:i32, 32:i32) + } + function bswap16(x:i32) -> y:i32 + { + y := i32.or(i32.and(i32.shl(x, 8:i32), 0xff00:i32), i32.and(i32.shr_u(x, 8:i32), 0xff:i32)) + } + function bswap32(x:i32) -> y:i32 + { + let hi:i32 := i32.shl(bswap16(x), 16:i32) + y := i32.or(hi, bswap16(i32.shr_u(x, 16:i32))) + } + } +} diff --git a/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_only/output b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_only/output index 5f9a6c0fb..e8b306260 100644 --- a/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_only/output +++ b/test/cmdlineTests/evm_to_wasm_output_selection_ewasm_only/output @@ -1,39 +1,6 @@ ======= evm_to_wasm_output_selection_ewasm_only/input.yul (Ewasm) ======= -========================== - -Translated source: -object "object" { - code { - function main() - { - let hi := i64.shl(i64.extend_i32_u(bswap32(i32.wrap_i64(0))), 32) - let y := i64.or(hi, i64.extend_i32_u(bswap32(i32.wrap_i64(i64.shr_u(0, 32))))) - i64.store(0:i32, y) - i64.store(i32.add(0:i32, 8:i32), y) - i64.store(i32.add(0:i32, 16:i32), y) - i64.store(i32.add(0:i32, 24:i32), y) - i64.store(32:i32, y) - i64.store(i32.add(32:i32, 8:i32), y) - i64.store(i32.add(32:i32, 16:i32), y) - let hi_1 := i64.shl(i64.extend_i32_u(bswap32(i32.wrap_i64(42))), 32) - i64.store(i32.add(32:i32, 24:i32), i64.or(hi_1, i64.extend_i32_u(bswap32(i32.wrap_i64(i64.shr_u(42, 32)))))) - eth.storageStore(0:i32, 32:i32) - } - function bswap16(x:i32) -> y:i32 - { - y := i32.or(i32.and(i32.shl(x, 8:i32), 0xff00:i32), i32.and(i32.shr_u(x, 8:i32), 0xff:i32)) - } - function bswap32(x:i32) -> y:i32 - { - let hi:i32 := i32.shl(bswap16(x), 16:i32) - y := i32.or(hi, bswap16(i32.shr_u(x, 16:i32))) - } - } -} - - Text representation: (module (import "ethereum" "storageStore" (func $eth.storageStore (param i32 i32))) diff --git a/test/cmdlineTests/output_selection_ewasm_ir_only/args b/test/cmdlineTests/output_selection_ewasm_ir_only/args new file mode 100644 index 000000000..bccff6085 --- /dev/null +++ b/test/cmdlineTests/output_selection_ewasm_ir_only/args @@ -0,0 +1 @@ +--optimize --ewasm-ir diff --git a/test/cmdlineTests/output_selection_ewasm_ir_only/err b/test/cmdlineTests/output_selection_ewasm_ir_only/err new file mode 100644 index 000000000..52dd265b5 --- /dev/null +++ b/test/cmdlineTests/output_selection_ewasm_ir_only/err @@ -0,0 +1 @@ +The following outputs are not supported in compiler mode: --ewasm-ir. diff --git a/test/cmdlineTests/output_selection_ewasm_ir_only/exit b/test/cmdlineTests/output_selection_ewasm_ir_only/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/output_selection_ewasm_ir_only/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/output_selection_ewasm_ir_only/input.sol b/test/cmdlineTests/output_selection_ewasm_ir_only/input.sol new file mode 100644 index 000000000..9755e16e7 --- /dev/null +++ b/test/cmdlineTests/output_selection_ewasm_ir_only/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/standard_cli_output_selection_invalid/args b/test/cmdlineTests/standard_cli_output_selection_invalid/args index f2deb3847..538c87097 100644 --- a/test/cmdlineTests/standard_cli_output_selection_invalid/args +++ b/test/cmdlineTests/standard_cli_output_selection_invalid/args @@ -1 +1 @@ ---ast-compact-json --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout +--ast-compact-json --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --ewasm-ir --hashes --userdoc --devdoc --metadata --storage-layout diff --git a/test/cmdlineTests/standard_cli_output_selection_invalid/err b/test/cmdlineTests/standard_cli_output_selection_invalid/err index d6ed4d572..e9d24e61d 100644 --- a/test/cmdlineTests/standard_cli_output_selection_invalid/err +++ b/test/cmdlineTests/standard_cli_output_selection_invalid/err @@ -1 +1 @@ -The following outputs are not supported in standard JSON mode: --abi, --asm, --asm-json, --ast-compact-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc. +The following outputs are not supported in standard JSON mode: --abi, --asm, --asm-json, --ast-compact-json, --bin, --bin-runtime, --devdoc, --ewasm, --ewasm-ir, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc. diff --git a/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/args b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/args new file mode 100644 index 000000000..647c63654 --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/args @@ -0,0 +1 @@ +--strict-assembly --optimize --ewasm-ir diff --git a/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/err b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/err new file mode 100644 index 000000000..014a1178f --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/input.yul b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/input.yul new file mode 100644 index 000000000..4fa5ef66f --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/input.yul @@ -0,0 +1,4 @@ +{ + let x := 42 + sstore(0, x) +} diff --git a/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/output b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/output new file mode 100644 index 000000000..8026a6e83 --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_ewasm_ir_only/output @@ -0,0 +1,2 @@ + +======= strict_asm_output_selection_ewasm_ir_only/input.yul (EVM) ======= diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index dd5696c68..23ea1efb1 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -198,7 +198,9 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, + true, }; + expectedOptions.compiler.outputs.ewasmIR = false; expectedOptions.compiler.estimateGas = true; expectedOptions.compiler.combinedJsonRequests = { true, true, true, true, true, @@ -301,6 +303,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) "--bin", "--ir-optimized", "--ewasm", + "--ewasm-ir", }; commandLine += assemblyOptions; if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm) @@ -341,6 +344,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.compiler.outputs.binary = true; expectedOptions.compiler.outputs.irOptimized = true; expectedOptions.compiler.outputs.ewasm = true; + expectedOptions.compiler.outputs.ewasmIR = true; if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm) { expectedOptions.optimizer.enabled = true;