mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #5341 from ethereum/optimizeAssemblyCommandline
Apply the optimize commandline parameter to assembly mode.
This commit is contained in:
commit
4b98946e5a
@ -7,6 +7,7 @@ Language Features:
|
|||||||
Compiler Features:
|
Compiler Features:
|
||||||
* Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`.
|
* 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.
|
* 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: SMTLib2 queries and responses passed via standard JSON compiler interface.
|
||||||
* SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables.
|
* SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables.
|
||||||
* SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions.
|
* SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions.
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
#include <libevmasm/Assembly.h>
|
#include <libevmasm/Assembly.h>
|
||||||
|
|
||||||
|
#include <libyul/optimiser/Suite.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
using namespace langutil;
|
using namespace langutil;
|
||||||
@ -79,6 +81,13 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string
|
|||||||
return analyzeParsed();
|
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()
|
bool AssemblyStack::analyzeParsed()
|
||||||
{
|
{
|
||||||
solAssert(m_parserResult, "");
|
solAssert(m_parserResult, "");
|
||||||
|
@ -69,6 +69,9 @@ public:
|
|||||||
/// Multiple calls overwrite the previous state.
|
/// Multiple calls overwrite the previous state.
|
||||||
bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source);
|
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).
|
/// Run the assembly step (should only be called after parseAndAnalyze).
|
||||||
MachineAssemblyObject assemble(Machine _machine) const;
|
MachineAssemblyObject assemble(Machine _machine) const;
|
||||||
|
|
||||||
|
@ -626,15 +626,15 @@ Allowed options)",
|
|||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_argAssemble.c_str(),
|
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(),
|
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(),
|
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(),
|
g_argMachine.c_str(),
|
||||||
@ -820,6 +820,7 @@ bool CommandLineInterface::processInput()
|
|||||||
using Machine = AssemblyStack::Machine;
|
using Machine = AssemblyStack::Machine;
|
||||||
Input inputLanguage = m_args.count(g_argYul) ? Input::Yul : (m_args.count(g_argStrictAssembly) ? Input::StrictAssembly : Input::Assembly);
|
Input inputLanguage = m_args.count(g_argYul) ? Input::Yul : (m_args.count(g_argStrictAssembly) ? Input::StrictAssembly : Input::Assembly);
|
||||||
Machine targetMachine = Machine::EVM;
|
Machine targetMachine = Machine::EVM;
|
||||||
|
bool optimize = m_args.count(g_argOptimize);
|
||||||
if (m_args.count(g_argMachine))
|
if (m_args.count(g_argMachine))
|
||||||
{
|
{
|
||||||
string machine = m_args[g_argMachine].as<string>();
|
string machine = m_args[g_argMachine].as<string>();
|
||||||
@ -835,7 +836,18 @@ bool CommandLineInterface::processInput()
|
|||||||
return false;
|
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))
|
if (m_args.count(g_argLink))
|
||||||
{
|
{
|
||||||
@ -1179,7 +1191,8 @@ string CommandLineInterface::objectWithLinkRefsHex(eth::LinkerObject const& _obj
|
|||||||
|
|
||||||
bool CommandLineInterface::assemble(
|
bool CommandLineInterface::assemble(
|
||||||
AssemblyStack::Language _language,
|
AssemblyStack::Language _language,
|
||||||
AssemblyStack::Machine _targetMachine
|
AssemblyStack::Machine _targetMachine,
|
||||||
|
bool _optimize
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
@ -1191,6 +1204,8 @@ bool CommandLineInterface::assemble(
|
|||||||
{
|
{
|
||||||
if (!stack.parseAndAnalyze(src.first, src.second))
|
if (!stack.parseAndAnalyze(src.first, src.second))
|
||||||
successful = false;
|
successful = false;
|
||||||
|
else if (_optimize)
|
||||||
|
stack.optimize();
|
||||||
}
|
}
|
||||||
catch (Exception const& _exception)
|
catch (Exception const& _exception)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ private:
|
|||||||
/// @returns the full object with library placeholder hints in hex.
|
/// @returns the full object with library placeholder hints in hex.
|
||||||
static std::string objectWithLinkRefsHex(eth::LinkerObject const& _obj);
|
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();
|
void outputCompilationResults();
|
||||||
|
|
||||||
|
@ -262,11 +262,46 @@ SOLTMPDIR=$(mktemp -d)
|
|||||||
)
|
)
|
||||||
rm -rf "$SOLTMPDIR"
|
rm -rf "$SOLTMPDIR"
|
||||||
|
|
||||||
printTask "Testing assemble, yul, strict-assembly..."
|
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" - --assemble &>/dev/null
|
||||||
echo '{}' | "$SOLC" - --yul &>/dev/null
|
echo '{}' | "$SOLC" - --yul &>/dev/null
|
||||||
echo '{}' | "$SOLC" - --strict-assembly &>/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..."
|
printTask "Testing standard input..."
|
||||||
SOLTMPDIR=$(mktemp -d)
|
SOLTMPDIR=$(mktemp -d)
|
||||||
(
|
(
|
||||||
|
Loading…
Reference in New Issue
Block a user