IRGeneratorForStatements: Handle internal calls to functions from specific base contracts as static calls rather than calls via pointers

This commit is contained in:
Kamil Śliwak 2020-04-20 23:21:09 +02:00
parent 397ea18b78
commit 56a85d6cb3
3 changed files with 52 additions and 20 deletions

View File

@ -579,32 +579,60 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
else else
args.emplace_back(convert(*arguments[i], *parameterTypes[i]).commaSeparatedList()); args.emplace_back(convert(*arguments[i], *parameterTypes[i]).commaSeparatedList());
if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression())) optional<FunctionDefinition const*> functionDef;
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
{ {
solAssert(!functionType->bound(), ""); solAssert(!functionType->bound(), "");
if (auto functionDef = dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration))
functionDef = dynamic_cast<FunctionDefinition const*>(memberAccess->annotation().referencedDeclaration);
if (functionDef.value() != nullptr)
solAssert(functionType->declaration() == *memberAccess->annotation().referencedDeclaration, "");
else
{ {
define(_functionCall) << solAssert(dynamic_cast<VariableDeclaration const*>(memberAccess->annotation().referencedDeclaration), "");
m_context.enqueueFunctionForCodeGeneration( solAssert(!functionType->hasDeclaration(), "");
functionDef->resolveVirtual(m_context.mostDerivedContract())
) <<
"(" <<
joinHumanReadable(args) <<
")\n";
return;
} }
} }
else if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
{
solAssert(!functionType->bound(), "");
define(_functionCall) << if (auto unresolvedFunctionDef = dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration))
// NOTE: internalDispatch() takes care of adding the function to function generation queue {
m_context.internalDispatch( functionDef = &unresolvedFunctionDef->resolveVirtual(m_context.mostDerivedContract());
TupleType(functionType->parameterTypes()).sizeOnStack(), solAssert(functionType->declaration() == *identifier->annotation().referencedDeclaration, "");
TupleType(functionType->returnParameterTypes()).sizeOnStack() }
) << else
"(" << {
IRVariable(_functionCall.expression()).part("functionIdentifier").name() << functionDef = nullptr;
joinHumanReadablePrefixed(args) << solAssert(dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration), "");
")\n"; solAssert(!functionType->hasDeclaration(), "");
}
}
else
// Not a simple expression like x or A.x
functionDef = nullptr;
solAssert(functionDef.has_value(), "");
solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), "");
if (functionDef.value() != nullptr)
define(_functionCall) <<
m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) <<
"(" <<
joinHumanReadable(args) <<
")\n";
else
define(_functionCall) <<
// NOTE: internalDispatch() takes care of adding the function to function generation queue
m_context.internalDispatch(
TupleType(functionType->parameterTypes()).sizeOnStack(),
TupleType(functionType->returnParameterTypes()).sizeOnStack()
) <<
"(" <<
IRVariable(_functionCall.expression()).part("functionIdentifier").name() <<
joinHumanReadablePrefixed(args) <<
")\n";
break; break;
} }
case FunctionType::Kind::External: case FunctionType::Kind::External:

View File

@ -34,6 +34,8 @@ contract Child is Base {
BaseBase.init(c, d); BaseBase.init(c, d);
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// x() -> 0 // x() -> 0
// y() -> 0 // y() -> 0

View File

@ -18,6 +18,8 @@ contract Child is Base {
Base.init(c, d); Base.init(c, d);
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// x() -> 0 // x() -> 0
// y() -> 0 // y() -> 0