aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/interface/AssemblyStack.cpp9
-rw-r--r--libsolidity/interface/AssemblyStack.h3
-rw-r--r--solc/CommandLineInterface.cpp25
-rw-r--r--solc/CommandLineInterface.h2
-rwxr-xr-xtest/cmdlineTests.sh43
6 files changed, 73 insertions, 10 deletions
diff --git a/Changelog.md b/Changelog.md
index 7aa5a6be..72d51bff 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -7,6 +7,7 @@ Language Features:
Compiler Features:
* Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`.
* Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata.
+ * Commandline interface: Experimental ``--optimize`` option for assembly mode.
* SMTChecker: SMTLib2 queries and responses passed via standard JSON compiler interface.
* SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables.
* SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions.
diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp
index 66ba42ee..f5eb7e41 100644
--- a/libsolidity/interface/AssemblyStack.cpp
+++ b/libsolidity/interface/AssemblyStack.cpp
@@ -34,6 +34,8 @@
#include <libevmasm/Assembly.h>
+#include <libyul/optimiser/Suite.h>
+
using namespace std;
using namespace dev;
using namespace langutil;
@@ -79,6 +81,13 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string
return analyzeParsed();
}
+void AssemblyStack::optimize()
+{
+ solAssert(m_language != Language::Assembly, "Optimization requested for loose assembly.");
+ yul::OptimiserSuite::run(*m_parserResult->code, *m_parserResult->analysisInfo);
+ solAssert(analyzeParsed(), "Invalid source code after optimization.");
+}
+
bool AssemblyStack::analyzeParsed()
{
solAssert(m_parserResult, "");
diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h
index 7ae0592e..0d04ffec 100644
--- a/libsolidity/interface/AssemblyStack.h
+++ b/libsolidity/interface/AssemblyStack.h
@@ -69,6 +69,9 @@ public:
/// Multiple calls overwrite the previous state.
bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source);
+ /// Run the optimizer suite. Can only be used with Yul or strict assembly.
+ void optimize();
+
/// Run the assembly step (should only be called after parseAndAnalyze).
MachineAssemblyObject assemble(Machine _machine) const;
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index e2baca7f..38e778c6 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -626,15 +626,15 @@ Allowed options)",
)
(
g_argAssemble.c_str(),
- "Switch to assembly mode, ignoring all options except --machine and assumes input is assembly."
+ "Switch to assembly mode, ignoring all options except --machine and --optimize and assumes input is assembly."
)
(
g_argYul.c_str(),
- "Switch to Yul mode, ignoring all options except --machine and assumes input is Yul."
+ "Switch to Yul mode, ignoring all options except --machine and --optimize and assumes input is Yul."
)
(
g_argStrictAssembly.c_str(),
- "Switch to strict assembly mode, ignoring all options except --machine and assumes input is strict assembly."
+ "Switch to strict assembly mode, ignoring all options except --machine and --optimize and assumes input is strict assembly."
)
(
g_argMachine.c_str(),
@@ -820,6 +820,7 @@ bool CommandLineInterface::processInput()
using Machine = AssemblyStack::Machine;
Input inputLanguage = m_args.count(g_argYul) ? Input::Yul : (m_args.count(g_argStrictAssembly) ? Input::StrictAssembly : Input::Assembly);
Machine targetMachine = Machine::EVM;
+ bool optimize = m_args.count(g_argOptimize);
if (m_args.count(g_argMachine))
{
string machine = m_args[g_argMachine].as<string>();
@@ -835,7 +836,18 @@ bool CommandLineInterface::processInput()
return false;
}
}
- return assemble(inputLanguage, targetMachine);
+ if (optimize && inputLanguage == Input::Assembly)
+ {
+ serr() <<
+ "Optimizer cannot be used for loose assembly. Use --" <<
+ g_strStrictAssembly <<
+ " or --" <<
+ g_strYul <<
+ "." <<
+ endl;
+ return false;
+ }
+ return assemble(inputLanguage, targetMachine, optimize);
}
if (m_args.count(g_argLink))
{
@@ -1179,7 +1191,8 @@ string CommandLineInterface::objectWithLinkRefsHex(eth::LinkerObject const& _obj
bool CommandLineInterface::assemble(
AssemblyStack::Language _language,
- AssemblyStack::Machine _targetMachine
+ AssemblyStack::Machine _targetMachine,
+ bool _optimize
)
{
bool successful = true;
@@ -1191,6 +1204,8 @@ bool CommandLineInterface::assemble(
{
if (!stack.parseAndAnalyze(src.first, src.second))
successful = false;
+ else if (_optimize)
+ stack.optimize();
}
catch (Exception const& _exception)
{
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index 8dc00370..0b22ca29 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -59,7 +59,7 @@ private:
/// @returns the full object with library placeholder hints in hex.
static std::string objectWithLinkRefsHex(eth::LinkerObject const& _obj);
- bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine);
+ bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine, bool _optimize);
void outputCompilationResults();
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index 4838d088..fdc9fbe3 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -262,10 +262,45 @@ SOLTMPDIR=$(mktemp -d)
)
rm -rf "$SOLTMPDIR"
-printTask "Testing assemble, yul, strict-assembly..."
-echo '{}' | "$SOLC" - --assemble &>/dev/null
-echo '{}' | "$SOLC" - --yul &>/dev/null
-echo '{}' | "$SOLC" - --strict-assembly &>/dev/null
+test_solc_assembly_output() {
+ local input="${1}"
+ local expected="${2}"
+ local solc_args="${3}"
+
+ local expected_object="object \"object\" { code "${expected}" }"
+
+ output=$(echo "${input}" | "$SOLC" - ${solc_args} 2>/dev/null)
+ empty=$(echo $output | sed -ne '/'"${expected_object}"'/p')
+ if [ -z "$empty" ]
+ then
+ printError "Incorrect assembly output. Expected: "
+ echo -e ${expected}
+ printError "with arguments ${solc_args}, but got:"
+ echo "${output}"
+ exit 1
+ fi
+}
+
+printTask "Testing assemble, yul, strict-assembly and optimize..."
+(
+ echo '{}' | "$SOLC" - --assemble &>/dev/null
+ echo '{}' | "$SOLC" - --yul &>/dev/null
+ echo '{}' | "$SOLC" - --strict-assembly &>/dev/null
+
+ # Test options above in conjunction with --optimize.
+ # Using both, --assemble and --optimize should fail.
+ ! echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null
+
+ # Test yul and strict assembly output
+ # Non-empty code results in non-empty binary representation with optimizations turned off,
+ # while it results in empty binary representation with optimizations turned on.
+ test_solc_assembly_output "{ let x:u256 := 0:u256 }" "{ let x:u256 := 0:u256 }" "--yul"
+ test_solc_assembly_output "{ let x:u256 := 0:u256 }" "{ }" "--yul --optimize"
+
+ test_solc_assembly_output "{ let x := 0 }" "{ let x := 0 }" "--strict-assembly"
+ test_solc_assembly_output "{ let x := 0 }" "{ }" "--strict-assembly --optimize"
+)
+
printTask "Testing standard input..."
SOLTMPDIR=$(mktemp -d)