mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8718 from ethereum/irConstants
IR generation for constants.
This commit is contained in:
commit
234ffcf278
@ -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);
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
|
@ -1,6 +1,7 @@
|
||||
contract Lotto {
|
||||
uint256 public constant ticketPrice = 555;
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// ticketPrice() -> 555
|
||||
|
@ -5,5 +5,7 @@ contract C {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45
|
||||
|
@ -16,6 +16,8 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0x20, 3, "\x03\x01\x02"
|
||||
// g() -> 0x20, 3, "\x03\x01\x02"
|
||||
|
@ -6,5 +6,7 @@ contract Foo {
|
||||
uint256 constant x = 56;
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// getX() -> 56
|
||||
|
@ -9,5 +9,7 @@ contract B is A {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 7
|
||||
|
@ -6,5 +6,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0x57a
|
||||
|
Loading…
Reference in New Issue
Block a user