[Sol->Yul] Implement getter functions

This commit is contained in:
Mathias Baumann 2019-07-08 22:15:59 +02:00
parent 37f04976a2
commit d264e3e0ba
5 changed files with 50 additions and 7 deletions

View File

@ -65,6 +65,11 @@ string IRGenerationContext::functionName(FunctionDefinition const& _function)
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)
{
// @TODO previously, we had to distinguish creation context and runtime context,

View File

@ -76,6 +76,7 @@ public:
}
std::string functionName(FunctionDefinition const& _function);
std::string functionName(VariableDeclaration const& _varDecl);
FunctionDefinition const& virtualFunction(FunctionDefinition const& _functionDeclaration);
std::string virtualFunctionName(FunctionDefinition const& _functionDeclaration);

View File

@ -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)
{
// 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["params"] = suffixedVariableNameList("param_", 0, paramVars);
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["abiEncode"] = abiFunctions.tupleEncoder(type->returnParameterTypes(), type->returnParameterTypes(), false);
templ["comma"] = retVars == 0 ? "" : ", ";

View File

@ -56,6 +56,8 @@ private:
/// Generates code for and returns the name of the 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 deployCode(ContractDefinition const& _contract);

View File

@ -1095,12 +1095,14 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
uint256 super_secret_data;
}
)";
ALSO_VIA_YUL(
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("data()"), encodeArgs(8));
ABI_CHECK(callContractFunction("name()"), encodeArgs("Celina"));
ABI_CHECK(callContractFunction("a_hash()"), encodeArgs(dev::keccak256(bytes(1, 0x7b))));
ABI_CHECK(callContractFunction("an_address()"), encodeArgs(toBigEndian(u160(0x1337))));
ABI_CHECK(callContractFunction("super_secret_data()"), bytes());
);
}
BOOST_AUTO_TEST_CASE(balance)