Merge pull request #8414 from ethereum/sol2yul-func-type-conversion

[Sol2Yul] Implements function-to-function cast.
This commit is contained in:
Christian Parpart 2020-03-09 11:31:44 +01:00 committed by GitHub
commit 988bd6780b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 1 deletions

View File

@ -1333,6 +1333,35 @@ string YulUtilFunctions::allocateMemoryArrayFunction(ArrayType const& _type)
string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
{
if (_from.category() == Type::Category::Function)
{
solAssert(_to.category() == Type::Category::Function, "");
FunctionType const& fromType = dynamic_cast<FunctionType const&>(_from);
FunctionType const& targetType = dynamic_cast<FunctionType const&>(_to);
solAssert(
fromType.isImplicitlyConvertibleTo(targetType) &&
fromType.sizeOnStack() == targetType.sizeOnStack() &&
(fromType.kind() == FunctionType::Kind::Internal || fromType.kind() == FunctionType::Kind::External) &&
fromType.kind() == targetType.kind(),
"Invalid function type conversion requested."
);
string const functionName =
"convert_" +
_from.identifier() +
"_to_" +
_to.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(addr, functionId) -> outAddr, outFunctionId {
outAddr := addr
outFunctionId := functionId
}
)")
("functionName", functionName)
.render();
});
}
if (_from.sizeOnStack() != 1 || _to.sizeOnStack() != 1)
return conversionFunctionSpecial(_from, _to);

View File

@ -47,6 +47,7 @@ using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
using namespace std::string_literals;
namespace
{
@ -1212,7 +1213,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
argumentTypes.emplace_back(&type(*arg));
argumentStrings.emplace_back(IRVariable(*arg).commaSeparatedList());
}
string argumentString = ", " + joinHumanReadable(argumentStrings);
string argumentString = argumentStrings.empty() ? ""s : (", " + joinHumanReadable(argumentStrings));
solUnimplementedAssert(funKind != FunctionType::Kind::ECRecover, "");

View File

@ -0,0 +1,23 @@
contract C {
function f(uint x) public pure returns (uint) {
return 2 * x;
}
function g() public view returns (function (uint) external returns (uint)) {
return this.f;
}
function h(uint x) public returns (uint) {
return this.g()(x) + 1;
}
function t() external view returns (
function(uint) external returns (uint) a,
function(uint) external view returns (uint) b) {
a = this.f;
b = this.f;
}
}
// ====
// compileViaYul: also
// ----
// f(uint256): 2 -> 4
// h(uint256): 2 -> 5
// t() -> 0xFDD67305928FCAC8D213D1E47BFA6165CD0B87BB3DE648B0000000000000000, 0xFDD67305928FCAC8D213D1E47BFA6165CD0B87BB3DE648B0000000000000000