Mapping getters for Yul IR.

This commit is contained in:
Daniel Kirchner 2020-02-04 14:59:33 +01:00
parent d3cbfb0c5c
commit af9fc8b634
3 changed files with 129 additions and 14 deletions

View File

@ -159,21 +159,70 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
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>)
if (auto const* mappingType = dynamic_cast<MappingType const*>(type))
return m_context.functionCollector()->createFunction(functionName, [&]() {
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);
solAssert(slot_offset.second == 0, "");
FunctionType funType(_varDecl);
solUnimplementedAssert(funType.returnParameterTypes().size() == 1, "");
TypePointer returnType = funType.returnParameterTypes().front();
unsigned num_keys = 0;
stringstream indexAccesses;
string slot = m_context.newYulVariable();
do
{
solUnimplementedAssert(
mappingType->keyType()->sizeOnStack() == 1,
"Multi-slot mapping key unimplemented - might not be a problem"
);
indexAccesses <<
slot <<
" := " <<
m_utils.mappingIndexAccessFunction(*mappingType, *mappingType->keyType()) <<
"(" <<
slot;
if (mappingType->keyType()->sizeOnStack() > 0)
indexAccesses <<
", " <<
suffixedVariableNameList("key", num_keys, num_keys + mappingType->keyType()->sizeOnStack());
indexAccesses << ")\n";
num_keys += mappingType->keyType()->sizeOnStack();
}
)")
("functionName", functionName)
("readStorage", m_utils.readFromStorage(*type, slot_offset.second, false))
("slot", slot_offset.first.str())
.render();
});
while ((mappingType = dynamic_cast<MappingType const*>(mappingType->valueType())));
return Whiskers(R"(
function <functionName>(<keys>) -> rval {
let <slot> := <base>
<indexAccesses>
rval := <readStorage>(<slot>)
}
)")
("functionName", functionName)
("keys", suffixedVariableNameList("key", 0, num_keys))
("readStorage", m_utils.readFromStorage(*returnType, 0, false))
("indexAccesses", indexAccesses.str())
("slot", slot)
("base", slot_offset.first.str())
.render();
});
else
{
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)

View File

@ -0,0 +1,26 @@
pragma experimental ABIEncoderV2;
contract test {
enum E { A, B, C }
mapping(E => uint8) public table;
function set(E k, uint8 v) public {
table[k] = v;
}
}
// ====
// compileViaYul: also
// ----
// table(uint8): 0 -> 0
// table(uint8): 0x01 -> 0
// table(uint8): 0xa7 -> FAILURE
// set(uint8,uint8): 0x01, 0xa1 ->
// table(uint8): 0 -> 0
// table(uint8): 0x01 -> 0xa1
// table(uint8): 0xa7 -> FAILURE
// set(uint8,uint8): 0x00, 0xef ->
// table(uint8): 0 -> 0xef
// table(uint8): 0x01 -> 0xa1
// table(uint8): 0xa7 -> FAILURE
// set(uint8,uint8): 0x01, 0x05 ->
// table(uint8): 0 -> 0xef
// table(uint8): 0x01 -> 0x05
// table(uint8): 0xa7 -> FAILURE

View File

@ -0,0 +1,40 @@
contract test {
mapping(uint256 => uint256) public m1;
mapping(uint256 => mapping(uint256 => uint256)) public m2;
function set(uint256 k, uint256 v) public {
m1[k] = v;
}
function set(uint256 k1, uint256 k2, uint256 v) public {
m2[k1][k2] = v;
}
}
// ====
// compileViaYul: also
// ----
// m1(uint256): 0 -> 0
// m1(uint256): 0x01 -> 0
// m1(uint256): 0xa7 -> 0
// set(uint256,uint256): 0x01, 0xa1 ->
// m1(uint256): 0 -> 0
// m1(uint256): 0x01 -> 0xa1
// m1(uint256): 0xa7 -> 0
// set(uint256,uint256): 0x00, 0xef ->
// m1(uint256): 0 -> 0xef
// m1(uint256): 0x01 -> 0xa1
// m1(uint256): 0xa7 -> 0
// set(uint256,uint256): 0x01, 0x05 ->
// m1(uint256): 0 -> 0xef
// m1(uint256): 0x01 -> 0x05
// m1(uint256): 0xa7 -> 0
// m2(uint256,uint256): 0, 0 -> 0
// m2(uint256,uint256): 0, 0x01 -> 0
// m2(uint256,uint256): 0xa7, 0 -> 0
// m2(uint256,uint256): 0xa7, 0x01 -> 0
// set(uint256,uint256,uint256): 0xa7, 0x01, 0x23
// m2(uint256,uint256): 0, 0x01 -> 0
// m2(uint256,uint256): 0xa7, 0 -> 0
// m2(uint256,uint256): 0xa7, 0x01 -> 0x23
// set(uint256,uint256,uint256): 0, 0x01, 0xef
// m2(uint256,uint256): 0, 0x01 -> 0xef
// m2(uint256,uint256): 0xa7, 0 -> 0
// m2(uint256,uint256): 0xa7, 0x01 -> 0x23