mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Mapping getters for Yul IR.
This commit is contained in:
parent
d3cbfb0c5c
commit
af9fc8b634
@ -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)
|
||||
|
@ -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
|
40
test/libsolidity/semanticTests/viaYul/mapping_getters.sol
Normal file
40
test/libsolidity/semanticTests/viaYul/mapping_getters.sol
Normal 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
|
Loading…
Reference in New Issue
Block a user