mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul] Functions: Remove dependency on AST ID.
This commit is contained in:
parent
e4cf371358
commit
8accf420ea
@ -177,3 +177,17 @@ ABIFunctions IRGenerationContext::abiFunctions()
|
||||
{
|
||||
return ABIFunctions(m_evmVersion, m_revertStrings, m_functions);
|
||||
}
|
||||
|
||||
uint64_t IRGenerationContext::internalFunctionID(FunctionDefinition const& _function, bool _requirePresent)
|
||||
{
|
||||
auto [iterator, inserted] = m_functionIDs.try_emplace(_function.id(), m_functionIDs.size() + 1);
|
||||
if (_requirePresent)
|
||||
solAssert(!inserted, "");
|
||||
return iterator->second;
|
||||
}
|
||||
|
||||
void IRGenerationContext::copyFunctionIDsFrom(IRGenerationContext const& _other)
|
||||
{
|
||||
solAssert(m_functionIDs.empty(), "");
|
||||
m_functionIDs = _other.m_functionIDs;
|
||||
}
|
||||
|
@ -152,6 +152,14 @@ public:
|
||||
bool inlineAssemblySeen() const { return m_inlineAssemblySeen; }
|
||||
void setInlineAssemblySeen() { m_inlineAssemblySeen = true; }
|
||||
|
||||
/// @returns the runtime ID to be used for the function in the dispatch routine
|
||||
/// and for internal function pointers.
|
||||
/// @param _requirePresent if false, generates a new ID if not yet done.
|
||||
uint64_t internalFunctionID(FunctionDefinition const& _function, bool _requirePresent);
|
||||
/// Copies the internal function IDs from the @a _other. For use in transferring
|
||||
/// function IDs from constructor code to deployed code.
|
||||
void copyFunctionIDsFrom(IRGenerationContext const& _other);
|
||||
|
||||
std::map<std::string, unsigned> const& sourceIndices() const { return m_sourceIndices; }
|
||||
|
||||
private:
|
||||
@ -191,6 +199,8 @@ private:
|
||||
/// the code contains a call via a pointer even though a specific function is never assigned to it.
|
||||
/// It will fail at runtime but the code must still compile.
|
||||
InternalDispatchMap m_internalDispatchMap;
|
||||
/// Map used by @a internalFunctionID.
|
||||
std::map<int64_t, uint64_t> m_functionIDs;
|
||||
|
||||
std::set<ContractDefinition const*, ASTNode::CompareByID> m_subObjects;
|
||||
};
|
||||
|
@ -299,7 +299,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
|
||||
|
||||
cases.emplace_back(map<string, string>{
|
||||
{"funID", to_string(function->id())},
|
||||
{"funID", to_string(m_context.internalFunctionID(*function, true))},
|
||||
{"name", IRNames::function(*function)}
|
||||
});
|
||||
}
|
||||
@ -1013,7 +1013,9 @@ void IRGenerator::resetContext(ContractDefinition const& _contract)
|
||||
m_context.internalDispatchClean(),
|
||||
"Reset internal dispatch map without consuming it."
|
||||
);
|
||||
m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices());
|
||||
IRGenerationContext newContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices());
|
||||
newContext.copyFunctionIDsFrom(m_context);
|
||||
m_context = move(newContext);
|
||||
|
||||
m_context.setMostDerivedContract(_contract);
|
||||
for (auto const& var: ContractType(_contract).stateVariables())
|
||||
|
@ -1575,12 +1575,10 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
define(IRVariable(_memberAccess).part("self"), _memberAccess.expression());
|
||||
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
|
||||
if (memberFunctionType->kind() == FunctionType::Kind::Internal)
|
||||
{
|
||||
auto const& functionDefinition = dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration());
|
||||
define(IRVariable(_memberAccess).part("functionIdentifier")) << to_string(functionDefinition.id()) << "\n";
|
||||
if (!_memberAccess.annotation().calledDirectly)
|
||||
m_context.addToInternalDispatch(functionDefinition);
|
||||
}
|
||||
assignInternalFunctionIDIfNotCalledDirectly(
|
||||
_memberAccess,
|
||||
dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration())
|
||||
);
|
||||
else if (
|
||||
memberFunctionType->kind() == FunctionType::Kind::ArrayPush ||
|
||||
memberFunctionType->kind() == FunctionType::Kind::ArrayPop
|
||||
@ -1918,11 +1916,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
*_memberAccess.annotation().referencedDeclaration
|
||||
).resolveVirtual(m_context.mostDerivedContract(), super);
|
||||
|
||||
define(_memberAccess) << to_string(resolvedFunctionDef.id()) << "\n";
|
||||
solAssert(resolvedFunctionDef.functionType(true), "");
|
||||
solAssert(resolvedFunctionDef.functionType(true)->kind() == FunctionType::Kind::Internal, "");
|
||||
if (!_memberAccess.annotation().calledDirectly)
|
||||
m_context.addToInternalDispatch(resolvedFunctionDef);
|
||||
assignInternalFunctionIDIfNotCalledDirectly(_memberAccess, resolvedFunctionDef);
|
||||
}
|
||||
else if (auto const* variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
handleVariableReference(*variable, _memberAccess);
|
||||
@ -1934,11 +1930,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
break;
|
||||
case FunctionType::Kind::Internal:
|
||||
if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
{
|
||||
define(_memberAccess) << to_string(function->id()) << "\n";
|
||||
if (!_memberAccess.annotation().calledDirectly)
|
||||
m_context.addToInternalDispatch(*function);
|
||||
}
|
||||
assignInternalFunctionIDIfNotCalledDirectly(_memberAccess, *function);
|
||||
else
|
||||
solAssert(false, "Function not found in member access");
|
||||
break;
|
||||
@ -2021,10 +2013,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
solAssert(funType->kind() == FunctionType::Kind::Internal, "");
|
||||
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
|
||||
|
||||
define(_memberAccess) << to_string(function->id()) << "\n";
|
||||
|
||||
if (!_memberAccess.annotation().calledDirectly)
|
||||
m_context.addToInternalDispatch(*function);
|
||||
assignInternalFunctionIDIfNotCalledDirectly(_memberAccess, *function);
|
||||
}
|
||||
else if (auto const* contract = dynamic_cast<ContractDefinition const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
{
|
||||
@ -2268,12 +2257,10 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
|
||||
{
|
||||
solAssert(*_identifier.annotation().requiredLookup == VirtualLookup::Virtual, "");
|
||||
FunctionDefinition const& resolvedFunctionDef = functionDef->resolveVirtual(m_context.mostDerivedContract());
|
||||
define(_identifier) << to_string(resolvedFunctionDef.id()) << "\n";
|
||||
|
||||
solAssert(resolvedFunctionDef.functionType(true), "");
|
||||
solAssert(resolvedFunctionDef.functionType(true)->kind() == FunctionType::Kind::Internal, "");
|
||||
if (!_identifier.annotation().calledDirectly)
|
||||
m_context.addToInternalDispatch(resolvedFunctionDef);
|
||||
assignInternalFunctionIDIfNotCalledDirectly(_identifier, resolvedFunctionDef);
|
||||
}
|
||||
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
handleVariableReference(*varDecl, _identifier);
|
||||
@ -2592,6 +2579,25 @@ void IRGeneratorForStatements::appendBareCall(
|
||||
appendCode() << templ.render();
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
|
||||
Expression const& _expression,
|
||||
FunctionDefinition const& _referencedFunction
|
||||
)
|
||||
{
|
||||
solAssert(
|
||||
dynamic_cast<MemberAccess const*>(&_expression) ||
|
||||
dynamic_cast<Identifier const*>(&_expression),
|
||||
""
|
||||
);
|
||||
if (_expression.annotation().calledDirectly)
|
||||
return;
|
||||
|
||||
define(IRVariable(_expression).part("functionIdentifier")) <<
|
||||
to_string(m_context.internalFunctionID(_referencedFunction, false)) <<
|
||||
"\n";
|
||||
m_context.addToInternalDispatch(_referencedFunction);
|
||||
}
|
||||
|
||||
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to)
|
||||
{
|
||||
if (_from.type() == _to)
|
||||
|
@ -153,6 +153,14 @@ private:
|
||||
std::vector<ASTPointer<Expression const>> const& _arguments
|
||||
);
|
||||
|
||||
/// Requests and assigns the internal ID of the referenced function to the referencing
|
||||
/// expression and adds the function to the internal dispatch.
|
||||
/// If the function is called right away, it does nothing.
|
||||
void assignInternalFunctionIDIfNotCalledDirectly(
|
||||
Expression const& _expression,
|
||||
FunctionDefinition const& _referencedFunction
|
||||
);
|
||||
|
||||
/// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable
|
||||
/// converted to type @a _to.
|
||||
IRVariable convert(IRVariable const& _variable, Type const& _to);
|
||||
|
@ -32,6 +32,6 @@ contract C {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 42, 23, 34, 42, 42
|
||||
// gas irOptimized: 111210
|
||||
// gas irOptimized: 111180
|
||||
// gas legacy: 112021
|
||||
// gas legacyOptimized: 110548
|
||||
|
Loading…
Reference in New Issue
Block a user