diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 252ddffa7..0717d6540 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -584,7 +584,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) case FunctionType::Kind::Internal: { vector args; - for (unsigned i = 0; i < arguments.size(); ++i) + for (size_t i = 0; i < arguments.size(); ++i) if (functionType->takesArbitraryParameters()) args.emplace_back(IRVariable(*arguments[i]).commaSeparatedList()); else @@ -818,15 +818,43 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { break; } - case FunctionType::Kind::GasLeft: + case FunctionType::Kind::AddMod: + case FunctionType::Kind::MulMod: { - define(_functionCall) << "gas()\n"; + static map functions = { + {FunctionType::Kind::AddMod, "addmod"}, + {FunctionType::Kind::MulMod, "mulmod"}, + }; + solAssert(functions.find(functionType->kind()) != functions.end(), ""); + solAssert(arguments.size() == 3 && parameterTypes.size() == 3, ""); + + IRVariable modulus(m_context.newYulVariable(), *(parameterTypes[2])); + define(modulus, *arguments[2]); + Whiskers templ("if iszero() { invalid() }\n"); + m_code << templ("modulus", modulus.name()).render(); + + string args; + for (size_t i = 0; i < 2; ++i) + args += expressionAsType(*arguments[i], *(parameterTypes[i])) + ", "; + args += modulus.name(); + define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n"; break; } + case FunctionType::Kind::GasLeft: case FunctionType::Kind::Selfdestruct: + case FunctionType::Kind::BlockHash: { - solAssert(arguments.size() == 1, ""); - define(_functionCall) << "selfdestruct(" << expressionAsType(*arguments.front(), *parameterTypes.front()) << ")\n"; + static map functions = { + {FunctionType::Kind::GasLeft, "gas"}, + {FunctionType::Kind::Selfdestruct, "selfdestruct"}, + {FunctionType::Kind::BlockHash, "blockhash"}, + }; + solAssert(functions.find(functionType->kind()) != functions.end(), ""); + + string args; + for (size_t i = 0; i < arguments.size(); ++i) + args += (args.empty() ? "" : ", ") + expressionAsType(*arguments[i], *(parameterTypes[i])); + define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n"; break; } case FunctionType::Kind::Log0: diff --git a/test/libsolidity/semanticTests/arithmetics/addmod_mulmod_zero.sol b/test/libsolidity/semanticTests/arithmetics/addmod_mulmod_zero.sol index 7585980e1..c70f195ba 100644 --- a/test/libsolidity/semanticTests/arithmetics/addmod_mulmod_zero.sol +++ b/test/libsolidity/semanticTests/arithmetics/addmod_mulmod_zero.sol @@ -18,6 +18,8 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f(uint256): 0 -> FAILURE // g(uint256): 0 -> FAILURE diff --git a/test/libsolidity/semanticTests/builtinFunctions/blockhash.sol b/test/libsolidity/semanticTests/builtinFunctions/blockhash.sol new file mode 100644 index 000000000..075e6c395 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/blockhash.sol @@ -0,0 +1,17 @@ +contract C { + function f() public returns(bytes32) { + return blockhash(1); + } + function g() public returns(bytes32) { + return blockhash(2); + } + function h() public returns(bytes32) { + return blockhash(3); + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0x3737373737373737373737373737373737373737373737373737373737373738 +// g() -> 0x3737373737373737373737373737373737373737373737373737373737373739 +// h() -> 0x373737373737373737373737373737373737373737373737373737373737373a