Skip to content

Commit cbf1c3a

Browse files
authored
Merge pull request #11512 from ethereum/issue_10342
[yul] Functions: Remove dependency on AST ID.
2 parents e4cf371 + 8accf42 commit cbf1c3a

File tree

6 files changed

+64
-24
lines changed

6 files changed

+64
-24
lines changed

libsolidity/codegen/ir/IRGenerationContext.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,17 @@ ABIFunctions IRGenerationContext::abiFunctions()
177177
{
178178
return ABIFunctions(m_evmVersion, m_revertStrings, m_functions);
179179
}
180+
181+
uint64_t IRGenerationContext::internalFunctionID(FunctionDefinition const& _function, bool _requirePresent)
182+
{
183+
auto [iterator, inserted] = m_functionIDs.try_emplace(_function.id(), m_functionIDs.size() + 1);
184+
if (_requirePresent)
185+
solAssert(!inserted, "");
186+
return iterator->second;
187+
}
188+
189+
void IRGenerationContext::copyFunctionIDsFrom(IRGenerationContext const& _other)
190+
{
191+
solAssert(m_functionIDs.empty(), "");
192+
m_functionIDs = _other.m_functionIDs;
193+
}

libsolidity/codegen/ir/IRGenerationContext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ class IRGenerationContext
152152
bool inlineAssemblySeen() const { return m_inlineAssemblySeen; }
153153
void setInlineAssemblySeen() { m_inlineAssemblySeen = true; }
154154

155+
/// @returns the runtime ID to be used for the function in the dispatch routine
156+
/// and for internal function pointers.
157+
/// @param _requirePresent if false, generates a new ID if not yet done.
158+
uint64_t internalFunctionID(FunctionDefinition const& _function, bool _requirePresent);
159+
/// Copies the internal function IDs from the @a _other. For use in transferring
160+
/// function IDs from constructor code to deployed code.
161+
void copyFunctionIDsFrom(IRGenerationContext const& _other);
162+
155163
std::map<std::string, unsigned> const& sourceIndices() const { return m_sourceIndices; }
156164

157165
private:
@@ -191,6 +199,8 @@ class IRGenerationContext
191199
/// the code contains a call via a pointer even though a specific function is never assigned to it.
192200
/// It will fail at runtime but the code must still compile.
193201
InternalDispatchMap m_internalDispatchMap;
202+
/// Map used by @a internalFunctionID.
203+
std::map<int64_t, uint64_t> m_functionIDs;
194204

195205
std::set<ContractDefinition const*, ASTNode::CompareByID> m_subObjects;
196206
};

libsolidity/codegen/ir/IRGenerator.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
299299
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
300300

301301
cases.emplace_back(map<string, string>{
302-
{"funID", to_string(function->id())},
302+
{"funID", to_string(m_context.internalFunctionID(*function, true))},
303303
{"name", IRNames::function(*function)}
304304
});
305305
}
@@ -1013,7 +1013,9 @@ void IRGenerator::resetContext(ContractDefinition const& _contract)
10131013
m_context.internalDispatchClean(),
10141014
"Reset internal dispatch map without consuming it."
10151015
);
1016-
m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices());
1016+
IRGenerationContext newContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices());
1017+
newContext.copyFunctionIDsFrom(m_context);
1018+
m_context = move(newContext);
10171019

10181020
m_context.setMostDerivedContract(_contract);
10191021
for (auto const& var: ContractType(_contract).stateVariables())

libsolidity/codegen/ir/IRGeneratorForStatements.cpp

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,12 +1575,10 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
15751575
define(IRVariable(_memberAccess).part("self"), _memberAccess.expression());
15761576
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
15771577
if (memberFunctionType->kind() == FunctionType::Kind::Internal)
1578-
{
1579-
auto const& functionDefinition = dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration());
1580-
define(IRVariable(_memberAccess).part("functionIdentifier")) << to_string(functionDefinition.id()) << "\n";
1581-
if (!_memberAccess.annotation().calledDirectly)
1582-
m_context.addToInternalDispatch(functionDefinition);
1583-
}
1578+
assignInternalFunctionIDIfNotCalledDirectly(
1579+
_memberAccess,
1580+
dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration())
1581+
);
15841582
else if (
15851583
memberFunctionType->kind() == FunctionType::Kind::ArrayPush ||
15861584
memberFunctionType->kind() == FunctionType::Kind::ArrayPop
@@ -1918,11 +1916,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
19181916
*_memberAccess.annotation().referencedDeclaration
19191917
).resolveVirtual(m_context.mostDerivedContract(), super);
19201918

1921-
define(_memberAccess) << to_string(resolvedFunctionDef.id()) << "\n";
19221919
solAssert(resolvedFunctionDef.functionType(true), "");
19231920
solAssert(resolvedFunctionDef.functionType(true)->kind() == FunctionType::Kind::Internal, "");
1924-
if (!_memberAccess.annotation().calledDirectly)
1925-
m_context.addToInternalDispatch(resolvedFunctionDef);
1921+
assignInternalFunctionIDIfNotCalledDirectly(_memberAccess, resolvedFunctionDef);
19261922
}
19271923
else if (auto const* variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
19281924
handleVariableReference(*variable, _memberAccess);
@@ -1934,11 +1930,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
19341930
break;
19351931
case FunctionType::Kind::Internal:
19361932
if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
1937-
{
1938-
define(_memberAccess) << to_string(function->id()) << "\n";
1939-
if (!_memberAccess.annotation().calledDirectly)
1940-
m_context.addToInternalDispatch(*function);
1941-
}
1933+
assignInternalFunctionIDIfNotCalledDirectly(_memberAccess, *function);
19421934
else
19431935
solAssert(false, "Function not found in member access");
19441936
break;
@@ -2021,10 +2013,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
20212013
solAssert(funType->kind() == FunctionType::Kind::Internal, "");
20222014
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
20232015

2024-
define(_memberAccess) << to_string(function->id()) << "\n";
2025-
2026-
if (!_memberAccess.annotation().calledDirectly)
2027-
m_context.addToInternalDispatch(*function);
2016+
assignInternalFunctionIDIfNotCalledDirectly(_memberAccess, *function);
20282017
}
20292018
else if (auto const* contract = dynamic_cast<ContractDefinition const*>(_memberAccess.annotation().referencedDeclaration))
20302019
{
@@ -2268,12 +2257,10 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
22682257
{
22692258
solAssert(*_identifier.annotation().requiredLookup == VirtualLookup::Virtual, "");
22702259
FunctionDefinition const& resolvedFunctionDef = functionDef->resolveVirtual(m_context.mostDerivedContract());
2271-
define(_identifier) << to_string(resolvedFunctionDef.id()) << "\n";
22722260

22732261
solAssert(resolvedFunctionDef.functionType(true), "");
22742262
solAssert(resolvedFunctionDef.functionType(true)->kind() == FunctionType::Kind::Internal, "");
2275-
if (!_identifier.annotation().calledDirectly)
2276-
m_context.addToInternalDispatch(resolvedFunctionDef);
2263+
assignInternalFunctionIDIfNotCalledDirectly(_identifier, resolvedFunctionDef);
22772264
}
22782265
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
22792266
handleVariableReference(*varDecl, _identifier);
@@ -2592,6 +2579,25 @@ void IRGeneratorForStatements::appendBareCall(
25922579
appendCode() << templ.render();
25932580
}
25942581

2582+
void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
2583+
Expression const& _expression,
2584+
FunctionDefinition const& _referencedFunction
2585+
)
2586+
{
2587+
solAssert(
2588+
dynamic_cast<MemberAccess const*>(&_expression) ||
2589+
dynamic_cast<Identifier const*>(&_expression),
2590+
""
2591+
);
2592+
if (_expression.annotation().calledDirectly)
2593+
return;
2594+
2595+
define(IRVariable(_expression).part("functionIdentifier")) <<
2596+
to_string(m_context.internalFunctionID(_referencedFunction, false)) <<
2597+
"\n";
2598+
m_context.addToInternalDispatch(_referencedFunction);
2599+
}
2600+
25952601
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to)
25962602
{
25972603
if (_from.type() == _to)

libsolidity/codegen/ir/IRGeneratorForStatements.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase
153153
std::vector<ASTPointer<Expression const>> const& _arguments
154154
);
155155

156+
/// Requests and assigns the internal ID of the referenced function to the referencing
157+
/// expression and adds the function to the internal dispatch.
158+
/// If the function is called right away, it does nothing.
159+
void assignInternalFunctionIDIfNotCalledDirectly(
160+
Expression const& _expression,
161+
FunctionDefinition const& _referencedFunction
162+
);
163+
156164
/// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable
157165
/// converted to type @a _to.
158166
IRVariable convert(IRVariable const& _variable, Type const& _to);

test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ contract C {
3232
// compileViaYul: also
3333
// ----
3434
// f() -> 42, 23, 34, 42, 42
35-
// gas irOptimized: 111210
35+
// gas irOptimized: 111180
3636
// gas legacy: 112021
3737
// gas legacyOptimized: 110548

0 commit comments

Comments
 (0)