Merge pull request #8718 from ethereum/irConstants

IR generation for constants.
This commit is contained in:
Daniel Kirchner 2020-05-06 16:05:17 +02:00 committed by GitHub
commit 234ffcf278
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 52 additions and 7 deletions

View File

@ -202,11 +202,11 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
Type const* type = _varDecl.annotation().type;
solAssert(!_varDecl.isConstant(), "");
solAssert(_varDecl.isStateVariable(), "");
if (auto const* mappingType = dynamic_cast<MappingType const*>(type))
return m_context.functionCollector().createFunction(functionName, [&]() {
solAssert(!_varDecl.isConstant(), "");
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);
solAssert(slot_offset.second == 0, "");
FunctionType funType(_varDecl);
@ -268,6 +268,16 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
("id", to_string(_varDecl.id()))
.render();
}
else if (_varDecl.isConstant())
return Whiskers(R"(
function <functionName>() -> <ret> {
<ret> := <constantValueFunction>()
}
)")
("functionName", functionName)
("constantValueFunction", IRGeneratorForStatements(m_context, m_utils).constantValueFunction(_varDecl))
("ret", suffixedVariableNameList("ret_", 0, _varDecl.type()->sizeOnStack()))
.render();
else
{
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);

View File

@ -178,6 +178,28 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre
return variable;
}
string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant)
{
string functionName = "constant_" + _constant.name() + "_" + to_string(_constant.id());
return m_context.functionCollector().createFunction(functionName, [&] {
Whiskers templ(R"(
function <functionName>() -> <ret> {
<code>
<ret> := <value>
}
)");
templ("functionName", functionName);
IRGeneratorForStatements generator(m_context, m_utils);
solAssert(_constant.value(), "");
Type const& constantType = *_constant.type();
templ("value", generator.evaluateExpression(*_constant.value(), constantType).commaSeparatedList());
templ("code", generator.code());
templ("ret", IRVariable("ret", constantType).commaSeparatedList());
return templ.render();
});
}
void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement)
{
if (Expression const* expression = _varDeclStatement.initialValue())
@ -1576,11 +1598,9 @@ void IRGeneratorForStatements::handleVariableReference(
Expression const& _referencingExpression
)
{
// TODO for the constant case, we have to be careful:
// If the value is visited twice, `defineExpression` is called twice on
// the same expression.
solUnimplementedAssert(!_variable.isConstant(), "");
if (_variable.isStateVariable() && _variable.immutable())
if (_variable.isStateVariable() && _variable.isConstant())
define(_referencingExpression) << constantValueFunction(_variable) << "()\n";
else if (_variable.isStateVariable() && _variable.immutable())
setLValue(_referencingExpression, IRLValue{
*_variable.annotation().type,
IRLValue::Immutable{&_variable}

View File

@ -54,6 +54,10 @@ public:
/// Calculates expression's value and returns variable where it was stored
IRVariable evaluateExpression(Expression const& _expression, Type const& _to);
/// @returns the name of a function that computes the value of the given constant
/// and also generates the function.
std::string constantValueFunction(VariableDeclaration const& _constant);
void endVisit(VariableDeclarationStatement const& _variableDeclaration) override;
bool visit(Conditional const& _conditional) override;
bool visit(Assignment const& _assignment) override;

View File

@ -1,6 +1,7 @@
contract Lotto {
uint256 public constant ticketPrice = 555;
}
// ====
// compileViaYul: also
// ----
// ticketPrice() -> 555

View File

@ -5,5 +5,7 @@ contract C {
return x;
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45

View File

@ -16,6 +16,8 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0x20, 3, "\x03\x01\x02"
// g() -> 0x20, 3, "\x03\x01\x02"

View File

@ -6,5 +6,7 @@ contract Foo {
uint256 constant x = 56;
}
// ====
// compileViaYul: also
// ----
// getX() -> 56

View File

@ -9,5 +9,7 @@ contract B is A {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 7

View File

@ -6,5 +6,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0x57a