From dda883b585c2f00ac60c3729feaa9a8fda782b22 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 20 Apr 2020 23:26:00 +0200 Subject: [PATCH] IR generation for sha256. --- .../codegen/ir/IRGeneratorForStatements.cpp | 53 +++++++++++++++---- .../builtinFunctions/sha256_empty.sol | 3 +- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index d8cb8f49c..2edad9329 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -760,6 +760,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) "))\n"; break; } + case FunctionType::Kind::ECRecover: + case FunctionType::Kind::SHA256: + case FunctionType::Kind::RIPEMD160: + { + solAssert(!_functionCall.annotation().tryCall, ""); + appendExternalFunctionCall(_functionCall, arguments); + break; + } case FunctionType::Kind::ArrayPop: { auto const& memberAccessExpression = dynamic_cast(_functionCall.expression()).expression(); @@ -1460,7 +1468,8 @@ void IRGeneratorForStatements::appendExternalFunctionCall( for (auto const& arg: _arguments) { argumentTypes.emplace_back(&type(*arg)); - argumentStrings.emplace_back(IRVariable(*arg).commaSeparatedList()); + if (IRVariable(*arg).type().sizeOnStack() > 0) + argumentStrings.emplace_back(IRVariable(*arg).commaSeparatedList()); } string argumentString = argumentStrings.empty() ? ""s : (", " + joinHumanReadable(argumentStrings)); @@ -1478,7 +1487,6 @@ void IRGeneratorForStatements::appendExternalFunctionCall( ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); - solUnimplementedAssert(!funType.isBareCall(), ""); Whiskers templ(R"( if iszero(extcodesize(
)) { revert(0, 0) } @@ -1486,8 +1494,18 @@ void IRGeneratorForStatements::appendExternalFunctionCall( // storage for arguments and returned data let := - mstore(, ()) - let := (add(, 4) ) + + + mstore(, ()) + + let := ( + + + + add(, 4) + + + ) let := (,
, , , sub(, ), , ) @@ -1509,14 +1527,25 @@ void IRGeneratorForStatements::appendExternalFunctionCall( )"); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); + templ("bareCall", funType.isBareCall()); if (_functionCall.annotation().tryCall) templ("success", m_context.trySuccessConditionVariable(_functionCall)); else templ("success", m_context.newYulVariable()); templ("freeMemory", freeMemory()); templ("shl28", m_utils.shiftLeftFunction(8 * (32 - 4))); - templ("funId", IRVariable(_functionCall.expression()).part("functionIdentifier").name()); - templ("address", IRVariable(_functionCall.expression()).part("address").name()); + + if (!funType.isBareCall()) + templ("funId", IRVariable(_functionCall.expression()).part("functionIdentifier").name()); + + if (funKind == FunctionType::Kind::ECRecover) + templ("address", "1"); + else if (funKind == FunctionType::Kind::SHA256) + templ("address", "2"); + else if (funKind == FunctionType::Kind::RIPEMD160) + templ("address", "3"); + else + templ("address", IRVariable(_functionCall.expression()).part("address").name()); // Always use the actual return length, and not our calculated expected length, if returndatacopy is supported. // This ensures it can catch badly formatted input from external calls. @@ -1548,9 +1577,15 @@ void IRGeneratorForStatements::appendExternalFunctionCall( // but all parameters of ecrecover are value types anyway. encodeInPlace = false; bool encodeForLibraryCall = funKind == FunctionType::Kind::DelegateCall; - solUnimplementedAssert(!encodeInPlace, ""); - solUnimplementedAssert(funType.padArguments(), ""); - templ("encodeArgs", abi.tupleEncoder(argumentTypes, funType.parameterTypes(), encodeForLibraryCall)); + + solUnimplementedAssert(encodeInPlace == !funType.padArguments(), ""); + if (encodeInPlace) + { + solUnimplementedAssert(!encodeForLibraryCall, ""); + templ("encodeArgs", abi.tupleEncoderPacked(argumentTypes, funType.parameterTypes())); + } + else + templ("encodeArgs", abi.tupleEncoder(argumentTypes, funType.parameterTypes(), encodeForLibraryCall)); templ("argumentString", argumentString); // Output data will replace input data, unless we have ECRecover (then, output diff --git a/test/libsolidity/semanticTests/builtinFunctions/sha256_empty.sol b/test/libsolidity/semanticTests/builtinFunctions/sha256_empty.sol index 69b9e15f5..ededa2fab 100644 --- a/test/libsolidity/semanticTests/builtinFunctions/sha256_empty.sol +++ b/test/libsolidity/semanticTests/builtinFunctions/sha256_empty.sol @@ -3,6 +3,7 @@ contract C { return sha256(""); } } - +// ==== +// compileViaYul: also // ---- // f() -> 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855