Merge pull request #6063 from ethereum/stackCompressorBuiltin

Take builtin functions into account in the compilability checker.
This commit is contained in:
chriseth 2019-02-21 14:40:56 +01:00 committed by GitHub
commit 52df027afe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 123 additions and 4 deletions

View File

@ -18,6 +18,7 @@ Bugfixes:
* Optimizer: Fix internal error related to unused tag removal across assemblies. This never generated any invalid code.
* SMTChecker: Fixed crash when used with fixed-sized arrays.
* Yul: Properly detect name clashes with functions before their declaration.
* Yul: Take builtin functions into account in the compilability checker.
Build System:

View File

@ -40,13 +40,15 @@ std::map<YulString, int> CompilabilityChecker::run(std::shared_ptr<Dialect> _dia
solAssert(_dialect->flavour == AsmFlavour::Strict, "");
EVMDialect const& evmDialect = dynamic_cast<EVMDialect const&>(*_dialect);
solAssert(dynamic_cast<EVMDialect const*>(_dialect.get()), "");
shared_ptr<NoOutputEVMDialect> noOutputDialect = make_shared<NoOutputEVMDialect>(dynamic_pointer_cast<EVMDialect>(_dialect));
bool optimize = true;
yul::AsmAnalysisInfo analysisInfo =
yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, EVMVersion(), _ast);
yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, EVMVersion(), _ast);
NoOutputAssembly assembly;
CodeTransform transform(assembly, analysisInfo, _ast, evmDialect, optimize);
CodeTransform transform(assembly, analysisInfo, _ast, *noOutputDialect, optimize);
try
{
transform(_ast);

View File

@ -66,7 +66,7 @@ struct EVMDialect: public Dialect
/// Sets the current object. Used during code generation.
void setCurrentObject(Object const* _object);
private:
protected:
void addFunction(
std::string _name,
size_t _params,

View File

@ -141,3 +141,22 @@ AbstractAssembly::SubID NoOutputAssembly::appendData(bytes const&)
{
return 1;
}
NoOutputEVMDialect::NoOutputEVMDialect(shared_ptr<EVMDialect> const& _copyFrom):
EVMDialect(_copyFrom->flavour, _copyFrom->providesObjectAccess())
{
for (auto& fun: m_functions)
{
size_t parameters = fun.second.parameters.size();
size_t returns = fun.second.returns.size();
fun.second.generateCode = [=](FunctionCall const&, AbstractAssembly& _asm, std::function<void()> _visitArguments)
{
_visitArguments();
for (size_t i = 0; i < parameters; i++)
_asm.appendInstruction(dev::solidity::Instruction::POP);
for (size_t i = 0; i < returns; i++)
_asm.appendConstant(u256(0));
};
}
}

View File

@ -22,6 +22,8 @@
#include <libyul/backends/evm/AbstractAssembly.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libevmasm/LinkerObject.h>
#include <map>
@ -34,6 +36,7 @@ struct SourceLocation;
namespace yul
{
/**
* Assembly class that just ignores everything and only performs stack counting.
* The purpose is to use this assembly for compilation dry-runs.
@ -72,4 +75,14 @@ private:
int m_stackHeight = 0;
};
/**
* EVM dialect that does not generate any code.
*/
struct NoOutputEVMDialect: public EVMDialect
{
explicit NoOutputEVMDialect(std::shared_ptr<EVMDialect> const& _copyFrom);
};
}

View File

@ -0,0 +1 @@
--strict-assembly --optimize

View File

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,17 @@
object "MyContract" {
code {
// this is the constructor.
// store the creator in the first storage slot
sstore(0, caller())
// now return the runtime code using the special functions
datacopy(0, dataoffset("Runtime"), datasize("Runtime"))
return(0, datasize("Runtime"))
}
object "Runtime" {
code {
// runtime - just return the creator
mstore(0, sload(0))
return(0, 0x20)
}
}
}

View File

@ -0,0 +1,65 @@
======= object_compiler/input.sol (EVM) =======
Pretty printed source:
object "MyContract" {
code {
sstore(0, caller())
let _3 := datasize("Runtime")
datacopy(0, dataoffset("Runtime"), _3)
return(0, _3)
}
object "Runtime" {
code {
mstore(0, sload(0))
return(0, 0x20)
}
}
}
Binary representation:
33600055600b806012600039806000f350fe60005460005260206000f3
Text representation:
/* "object_compiler/input.sol":128:136 */
caller
/* "object_compiler/input.sol":125:126 */
0x00
/* "object_compiler/input.sol":118:137 */
sstore
dataSize(sub_0)
/* "object_compiler/input.sol":240:259 */
dup1
dataOffset(sub_0)
/* "object_compiler/input.sol":125:126 */
0x00
/* "object_compiler/input.sol":205:260 */
codecopy
/* "object_compiler/input.sol":275:294 */
dup1
/* "object_compiler/input.sol":125:126 */
0x00
/* "object_compiler/input.sol":265:295 */
return
/* "object_compiler/input.sol":29:299 */
pop
stop
sub_0: assembly {
/* "object_compiler/input.sol":397:398 */
0x00
/* "object_compiler/input.sol":391:399 */
sload
/* "object_compiler/input.sol":397:398 */
0x00
/* "object_compiler/input.sol":381:400 */
mstore
/* "object_compiler/input.sol":417:421 */
0x20
/* "object_compiler/input.sol":397:398 */
0x00
/* "object_compiler/input.sol":407:422 */
return
}