mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7075 from ethereum/sol-yul-getter
[Sol->Yul] Implement keccak & getter functions
This commit is contained in:
commit
f3bdc79187
@ -65,6 +65,11 @@ string IRGenerationContext::functionName(FunctionDefinition const& _function)
|
|||||||
return "fun_" + _function.name() + "_" + to_string(_function.id());
|
return "fun_" + _function.name() + "_" + to_string(_function.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string IRGenerationContext::functionName(VariableDeclaration const& _varDecl)
|
||||||
|
{
|
||||||
|
return "getter_fun_" + _varDecl.name() + "_" + to_string(_varDecl.id());
|
||||||
|
}
|
||||||
|
|
||||||
FunctionDefinition const& IRGenerationContext::virtualFunction(FunctionDefinition const& _function)
|
FunctionDefinition const& IRGenerationContext::virtualFunction(FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
// @TODO previously, we had to distinguish creation context and runtime context,
|
// @TODO previously, we had to distinguish creation context and runtime context,
|
||||||
|
@ -76,6 +76,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string functionName(FunctionDefinition const& _function);
|
std::string functionName(FunctionDefinition const& _function);
|
||||||
|
std::string functionName(VariableDeclaration const& _varDecl);
|
||||||
FunctionDefinition const& virtualFunction(FunctionDefinition const& _functionDeclaration);
|
FunctionDefinition const& virtualFunction(FunctionDefinition const& _functionDeclaration);
|
||||||
std::string virtualFunctionName(FunctionDefinition const& _functionDeclaration);
|
std::string virtualFunctionName(FunctionDefinition const& _functionDeclaration);
|
||||||
|
|
||||||
|
@ -149,6 +149,32 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||||
|
{
|
||||||
|
string functionName = m_context.functionName(_varDecl);
|
||||||
|
|
||||||
|
Type const* type = _varDecl.annotation().type;
|
||||||
|
|
||||||
|
solAssert(!_varDecl.isConstant(), "");
|
||||||
|
solAssert(_varDecl.isStateVariable(), "");
|
||||||
|
|
||||||
|
solUnimplementedAssert(type->isValueType(), "");
|
||||||
|
|
||||||
|
return m_context.functionCollector()->createFunction(functionName, [&]() {
|
||||||
|
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);
|
||||||
|
|
||||||
|
return Whiskers(R"(
|
||||||
|
function <functionName>() -> rval {
|
||||||
|
rval := <readStorage>(<slot>)
|
||||||
|
}
|
||||||
|
)")
|
||||||
|
("functionName", functionName)
|
||||||
|
("readStorage", m_utils.readFromStorage(*type, slot_offset.second, false))
|
||||||
|
("slot", slot_offset.first.str())
|
||||||
|
.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
string IRGenerator::constructorCode(ContractDefinition const& _contract)
|
string IRGenerator::constructorCode(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
// TODO initialize state variables in base to derived order.
|
// TODO initialize state variables in base to derived order.
|
||||||
@ -234,7 +260,14 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
|||||||
templ["abiDecode"] = abiFunctions.tupleDecoder(type->parameterTypes());
|
templ["abiDecode"] = abiFunctions.tupleDecoder(type->parameterTypes());
|
||||||
templ["params"] = suffixedVariableNameList("param_", 0, paramVars);
|
templ["params"] = suffixedVariableNameList("param_", 0, paramVars);
|
||||||
templ["retParams"] = suffixedVariableNameList("ret_", retVars, 0);
|
templ["retParams"] = suffixedVariableNameList("ret_", retVars, 0);
|
||||||
templ["function"] = generateFunction(dynamic_cast<FunctionDefinition const&>(type->declaration()));
|
|
||||||
|
if (FunctionDefinition const* funDef = dynamic_cast<FunctionDefinition const*>(&type->declaration()))
|
||||||
|
templ["function"] = generateFunction(*funDef);
|
||||||
|
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(&type->declaration()))
|
||||||
|
templ["function"] = generateGetter(*varDecl);
|
||||||
|
else
|
||||||
|
solAssert(false, "Unexpected declaration for function!");
|
||||||
|
|
||||||
templ["allocate"] = m_utils.allocationFunction();
|
templ["allocate"] = m_utils.allocationFunction();
|
||||||
templ["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), false);
|
templ["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), false);
|
||||||
templ["comma"] = retVars == 0 ? "" : ", ";
|
templ["comma"] = retVars == 0 ? "" : ", ";
|
||||||
|
@ -56,6 +56,8 @@ private:
|
|||||||
|
|
||||||
/// Generates code for and returns the name of the function.
|
/// Generates code for and returns the name of the function.
|
||||||
std::string generateFunction(FunctionDefinition const& _function);
|
std::string generateFunction(FunctionDefinition const& _function);
|
||||||
|
/// Generates a getter for the given declaration and returns its name
|
||||||
|
std::string generateGetter(VariableDeclaration const& _varDecl);
|
||||||
|
|
||||||
std::string constructorCode(ContractDefinition const& _contract);
|
std::string constructorCode(ContractDefinition const& _contract);
|
||||||
std::string deployCode(ContractDefinition const& _contract);
|
std::string deployCode(ContractDefinition const& _contract);
|
||||||
|
@ -607,6 +607,26 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FunctionType::Kind::KECCAK256:
|
||||||
|
{
|
||||||
|
solAssert(arguments.size() == 1, "");
|
||||||
|
|
||||||
|
ArrayType const* arrayType = TypeProvider::bytesMemory();
|
||||||
|
string const& array = m_context.newYulVariable();
|
||||||
|
m_code << "let " << array << " := " << expressionAsType(*arguments[0], *arrayType) << "\n";
|
||||||
|
|
||||||
|
defineExpression(_functionCall) <<
|
||||||
|
"keccak256(" <<
|
||||||
|
m_utils.arrayDataAreaFunction(*arrayType) << "(" <<
|
||||||
|
array <<
|
||||||
|
"), " <<
|
||||||
|
m_utils.arrayLengthFunction(*arrayType) <<
|
||||||
|
"(" <<
|
||||||
|
array <<
|
||||||
|
"))\n";
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
solUnimplemented("FunctionKind " + toString(static_cast<int>(functionType->kind())) + " not yet implemented");
|
solUnimplemented("FunctionKind " + toString(static_cast<int>(functionType->kind())) + " not yet implemented");
|
||||||
}
|
}
|
||||||
|
@ -1095,12 +1095,14 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
|
|||||||
uint256 super_secret_data;
|
uint256 super_secret_data;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode);
|
ALSO_VIA_YUL(
|
||||||
ABI_CHECK(callContractFunction("data()"), encodeArgs(8));
|
compileAndRun(sourceCode);
|
||||||
ABI_CHECK(callContractFunction("name()"), encodeArgs("Celina"));
|
ABI_CHECK(callContractFunction("data()"), encodeArgs(8));
|
||||||
ABI_CHECK(callContractFunction("a_hash()"), encodeArgs(dev::keccak256(bytes(1, 0x7b))));
|
ABI_CHECK(callContractFunction("name()"), encodeArgs("Celina"));
|
||||||
ABI_CHECK(callContractFunction("an_address()"), encodeArgs(toBigEndian(u160(0x1337))));
|
ABI_CHECK(callContractFunction("a_hash()"), encodeArgs(dev::keccak256(bytes(1, 0x7b))));
|
||||||
ABI_CHECK(callContractFunction("super_secret_data()"), bytes());
|
ABI_CHECK(callContractFunction("an_address()"), encodeArgs(toBigEndian(u160(0x1337))));
|
||||||
|
ABI_CHECK(callContractFunction("super_secret_data()"), bytes());
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(balance)
|
BOOST_AUTO_TEST_CASE(balance)
|
||||||
@ -3470,8 +3472,10 @@ BOOST_AUTO_TEST_CASE(keccak256_empty)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode);
|
ALSO_VIA_YUL(
|
||||||
ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
|
compileAndRun(sourceCode);
|
||||||
|
ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments)
|
BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments)
|
||||||
|
14
test/libsolidity/semanticTests/viaYul/keccak.sol
Normal file
14
test/libsolidity/semanticTests/viaYul/keccak.sol
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
contract C {
|
||||||
|
function keccak1() public pure returns (bytes32) {
|
||||||
|
return keccak256("123");
|
||||||
|
}
|
||||||
|
function keccak2() public pure returns (bytes32) {
|
||||||
|
bytes memory a = "123";
|
||||||
|
return keccak256(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: only
|
||||||
|
// ----
|
||||||
|
// keccak1() -> 0x64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107
|
||||||
|
// keccak2() -> 0x64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107
|
Loading…
Reference in New Issue
Block a user