mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Do not allow msize in inline assembly if the Yul optimizer is active.
This commit is contained in:
parent
d7b5ea6761
commit
df96648b1c
@ -21,6 +21,9 @@
|
|||||||
#include <libsolidity/ast/ExperimentalFeatures.h>
|
#include <libsolidity/ast/ExperimentalFeatures.h>
|
||||||
#include <libsolidity/interface/Version.h>
|
#include <libsolidity/interface/Version.h>
|
||||||
|
|
||||||
|
#include <libyul/optimiser/Semantics.h>
|
||||||
|
#include <libyul/AsmData.h>
|
||||||
|
|
||||||
#include <liblangutil/ErrorReporter.h>
|
#include <liblangutil/ErrorReporter.h>
|
||||||
#include <liblangutil/SemVerHandler.h>
|
#include <liblangutil/SemVerHandler.h>
|
||||||
|
|
||||||
@ -254,6 +257,23 @@ bool SyntaxChecker::visit(UnaryOperation const& _operation)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||||
|
{
|
||||||
|
if (!m_useYulOptimizer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (yul::SideEffectsCollector(
|
||||||
|
_inlineAssembly.dialect(),
|
||||||
|
_inlineAssembly.operations()
|
||||||
|
).containsMSize())
|
||||||
|
m_errorReporter.syntaxError(
|
||||||
|
_inlineAssembly.location(),
|
||||||
|
"The msize instruction cannot be used when the Yul optimizer is activated because "
|
||||||
|
"it can change its semantics. Either disable the Yul optimizer or do not use the instruction."
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool SyntaxChecker::visit(PlaceholderStatement const&)
|
bool SyntaxChecker::visit(PlaceholderStatement const&)
|
||||||
{
|
{
|
||||||
m_placeholderFound = true;
|
m_placeholderFound = true;
|
||||||
|
@ -39,12 +39,16 @@ namespace solidity
|
|||||||
* - whether a modifier contains at least one '_'
|
* - whether a modifier contains at least one '_'
|
||||||
* - issues deprecation warnings for unary '+'
|
* - issues deprecation warnings for unary '+'
|
||||||
* - issues deprecation warning for throw
|
* - issues deprecation warning for throw
|
||||||
|
* - whether the msize instruction is used and the Yul optimizer is enabled at the same time.
|
||||||
*/
|
*/
|
||||||
class SyntaxChecker: private ASTConstVisitor
|
class SyntaxChecker: private ASTConstVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// @param _errorReporter provides the error logging functionality.
|
/// @param _errorReporter provides the error logging functionality.
|
||||||
SyntaxChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {}
|
SyntaxChecker(langutil::ErrorReporter& _errorReporter, bool _useYulOptimizer):
|
||||||
|
m_errorReporter(_errorReporter),
|
||||||
|
m_useYulOptimizer(_useYulOptimizer)
|
||||||
|
{}
|
||||||
|
|
||||||
bool checkSyntax(ASTNode const& _astRoot);
|
bool checkSyntax(ASTNode const& _astRoot);
|
||||||
|
|
||||||
@ -75,6 +79,8 @@ private:
|
|||||||
|
|
||||||
bool visit(UnaryOperation const& _operation) override;
|
bool visit(UnaryOperation const& _operation) override;
|
||||||
|
|
||||||
|
bool visit(InlineAssembly const& _inlineAssembly) override;
|
||||||
|
|
||||||
bool visit(PlaceholderStatement const& _placeholderStatement) override;
|
bool visit(PlaceholderStatement const& _placeholderStatement) override;
|
||||||
|
|
||||||
bool visit(ContractDefinition const& _contract) override;
|
bool visit(ContractDefinition const& _contract) override;
|
||||||
@ -88,6 +94,8 @@ private:
|
|||||||
|
|
||||||
langutil::ErrorReporter& m_errorReporter;
|
langutil::ErrorReporter& m_errorReporter;
|
||||||
|
|
||||||
|
bool m_useYulOptimizer = false;
|
||||||
|
|
||||||
/// Flag that indicates whether a function modifier actually contains '_'.
|
/// Flag that indicates whether a function modifier actually contains '_'.
|
||||||
bool m_placeholderFound = false;
|
bool m_placeholderFound = false;
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ bool CompilerStack::analyze()
|
|||||||
bool noErrors = true;
|
bool noErrors = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SyntaxChecker syntaxChecker(m_errorReporter);
|
SyntaxChecker syntaxChecker(m_errorReporter, m_optimiserSettings.runYulOptimiser);
|
||||||
for (Source const* source: m_sourceOrder)
|
for (Source const* source: m_sourceOrder)
|
||||||
if (!syntaxChecker.checkSyntax(*source->ast))
|
if (!syntaxChecker.checkSyntax(*source->ast))
|
||||||
noErrors = false;
|
noErrors = false;
|
||||||
|
@ -10082,8 +10082,11 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
if (!m_optimiserSettings.runYulOptimiser)
|
||||||
|
{
|
||||||
compileAndRun(sourceCode);
|
compileAndRun(sourceCode);
|
||||||
ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256, 0x260));
|
ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256, 0x260));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes)
|
BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes)
|
||||||
@ -11273,8 +11276,12 @@ BOOST_AUTO_TEST_CASE(correctly_initialize_memory_array_in_constructor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
// Cannot run against yul optimizer because of msize
|
||||||
|
if (!m_optimiserSettings.runYulOptimiser)
|
||||||
|
{
|
||||||
compileAndRun(sourceCode, 0, "C");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
ABI_CHECK(callContractFunction("success()"), encodeArgs(u256(1)));
|
ABI_CHECK(callContractFunction("success()"), encodeArgs(u256(1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier)
|
BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier)
|
||||||
|
@ -60,6 +60,12 @@ SyntaxTest::SyntaxTest(string const& _filename, langutil::EVMVersion _evmVersion
|
|||||||
file.exceptions(ios::badbit);
|
file.exceptions(ios::badbit);
|
||||||
|
|
||||||
m_source = parseSourceAndSettings(file);
|
m_source = parseSourceAndSettings(file);
|
||||||
|
if (m_settings.count("optimize-yul"))
|
||||||
|
{
|
||||||
|
m_optimiseYul = true;
|
||||||
|
m_validatedSettings["optimize-yul"] = "true";
|
||||||
|
m_settings.erase("optimize-yul");
|
||||||
|
}
|
||||||
m_expectations = parseExpectations(file);
|
m_expectations = parseExpectations(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +75,11 @@ TestCase::TestResult SyntaxTest::run(ostream& _stream, string const& _linePrefix
|
|||||||
compiler().reset();
|
compiler().reset();
|
||||||
compiler().setSources({{"", versionPragma + m_source}});
|
compiler().setSources({{"", versionPragma + m_source}});
|
||||||
compiler().setEVMVersion(m_evmVersion);
|
compiler().setEVMVersion(m_evmVersion);
|
||||||
|
compiler().setOptimiserSettings(
|
||||||
|
m_optimiseYul ?
|
||||||
|
OptimiserSettings::full() :
|
||||||
|
OptimiserSettings::minimal()
|
||||||
|
);
|
||||||
if (compiler().parse())
|
if (compiler().parse())
|
||||||
compiler().analyze();
|
compiler().analyze();
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ protected:
|
|||||||
std::string m_source;
|
std::string m_source;
|
||||||
std::vector<SyntaxTestError> m_expectations;
|
std::vector<SyntaxTestError> m_expectations;
|
||||||
std::vector<SyntaxTestError> m_errorList;
|
std::vector<SyntaxTestError> m_errorList;
|
||||||
|
bool m_optimiseYul = false;
|
||||||
langutil::EVMVersion const m_evmVersion;
|
langutil::EVMVersion const m_evmVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
function f() pure public {
|
||||||
|
assembly {
|
||||||
|
let x := msize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// optimize-yul: true
|
||||||
|
// ----
|
||||||
|
// Warning: The Yul optimiser is still experimental. Do not use it in production unless correctness of generated code is verified with extensive tests.
|
||||||
|
// SyntaxError: (52-101): The msize instruction cannot be used when the Yul optimizer is activated because it can change its semantics. Either disable the Yul optimizer or do not use the instruction.
|
@ -0,0 +1,8 @@
|
|||||||
|
contract C {
|
||||||
|
function f() pure public {
|
||||||
|
assembly {
|
||||||
|
let x := msize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
12
test/libyul/yulOptimizerTests/unusedPruner/keccak.yul
Normal file
12
test/libyul/yulOptimizerTests/unusedPruner/keccak.yul
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
let a := 1
|
||||||
|
let b := keccak256(1, 1)
|
||||||
|
sstore(0, msize())
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// step: unusedPruner
|
||||||
|
// ----
|
||||||
|
// {
|
||||||
|
// pop(keccak256(1, 1))
|
||||||
|
// sstore(0, msize())
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user