mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6787 from ethereum/sol2yul-ctor-code
Improve constructor-code codegen (wrt. state variable initialization)
This commit is contained in:
commit
9b375edfe3
@ -39,6 +39,9 @@
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
@ -177,19 +180,45 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
|
||||
string IRGenerator::constructorCode(ContractDefinition const& _contract)
|
||||
{
|
||||
// TODO initialize state variables in base to derived order.
|
||||
// TODO base constructors
|
||||
// TODO callValueCheck if there is no constructor.
|
||||
if (FunctionDefinition const* constructor = _contract.constructor())
|
||||
// Initialization of state variables in base-to-derived order.
|
||||
solAssert(!_contract.isLibrary(), "Tried to initialize state variables of library.");
|
||||
|
||||
using boost::adaptors::reverse;
|
||||
|
||||
ostringstream out;
|
||||
|
||||
FunctionDefinition const* constructor = _contract.constructor();
|
||||
if (constructor && !constructor->isPayable())
|
||||
out << callValueCheck();
|
||||
|
||||
for (ContractDefinition const* contract: reverse(_contract.annotation().linearizedBaseContracts))
|
||||
{
|
||||
string out;
|
||||
if (!constructor->isPayable())
|
||||
out = callValueCheck();
|
||||
solUnimplementedAssert(constructor->parameters().empty(), "");
|
||||
return move(out) + m_context.functionName(*constructor) + "()\n";
|
||||
out <<
|
||||
"\n// Begin state variable initialization for contract \"" <<
|
||||
contract->name() <<
|
||||
"\" (" <<
|
||||
contract->stateVariables().size() <<
|
||||
" variables)\n";
|
||||
|
||||
IRGeneratorForStatements generator{m_context, m_utils};
|
||||
for (VariableDeclaration const* variable: contract->stateVariables())
|
||||
if (!variable->isConstant())
|
||||
generator.initializeStateVar(*variable);
|
||||
out << generator.code();
|
||||
|
||||
out << "// End state variable initialization for contract \"" << contract->name() << "\".\n";
|
||||
}
|
||||
|
||||
return {};
|
||||
if (constructor)
|
||||
{
|
||||
solUnimplementedAssert(constructor->parameters().empty(), "");
|
||||
|
||||
// TODO base constructors
|
||||
|
||||
out << m_context.functionName(*constructor) + "()\n";
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
|
@ -133,6 +133,21 @@ string IRGeneratorForStatements::code() const
|
||||
return m_code.str();
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
solAssert(m_context.isStateVariable(_varDecl), "Must be a state variable.");
|
||||
solAssert(!_varDecl.isConstant(), "");
|
||||
if (_varDecl.value())
|
||||
{
|
||||
_varDecl.value()->accept(*this);
|
||||
string value = m_context.newYulVariable();
|
||||
Type const& varType = *_varDecl.type();
|
||||
|
||||
m_code << "let " << value << " := " << expressionAsType(*_varDecl.value(), varType) << "\n";
|
||||
m_code << IRStorageItem{m_context, _varDecl}.storeValue(value, varType);
|
||||
}
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement)
|
||||
{
|
||||
for (auto const& decl: _varDeclStatement.declarations())
|
||||
|
@ -45,6 +45,9 @@ public:
|
||||
|
||||
std::string code() const;
|
||||
|
||||
/// Generates code to initialize the given state variable.
|
||||
void initializeStateVar(VariableDeclaration const& _varDecl);
|
||||
|
||||
void endVisit(VariableDeclarationStatement const& _variableDeclaration) override;
|
||||
bool visit(Assignment const& _assignment) override;
|
||||
bool visit(TupleExpression const& _tuple) override;
|
||||
|
@ -10,6 +10,9 @@ object \"C_6\" {
|
||||
code {
|
||||
mstore(64, 128)
|
||||
|
||||
// Begin state variable initialization for contract \"C\" (0 variables)
|
||||
// End state variable initialization for contract \"C\".
|
||||
|
||||
|
||||
codecopy(0, dataoffset(\"C_6_deployed\"), datasize(\"C_6_deployed\"))
|
||||
return(0, datasize(\"C_6_deployed\"))
|
||||
|
@ -7921,8 +7921,10 @@ BOOST_AUTO_TEST_CASE(accessor_for_state_variable)
|
||||
}
|
||||
)";
|
||||
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500)));
|
||||
ALSO_VIA_YUL(
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500)));
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable)
|
||||
|
14
test/libsolidity/semanticTests/state_var_initialization.sol
Normal file
14
test/libsolidity/semanticTests/state_var_initialization.sol
Normal file
@ -0,0 +1,14 @@
|
||||
contract C {
|
||||
uint public i = 1;
|
||||
uint public k = 2;
|
||||
|
||||
constructor() public {
|
||||
i = i + i;
|
||||
k = k - i;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// i() -> 2
|
||||
// k() -> 0
|
Loading…
Reference in New Issue
Block a user