mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[Sol->Yul] Enabling storage pointers to local vars in inline assembly.
This commit is contained in:
parent
bff0f9bda7
commit
d99b81ef02
@ -98,8 +98,9 @@ public:
|
||||
|
||||
void addStateVariable(VariableDeclaration const& _varDecl, u256 _storageOffset, unsigned _byteOffset);
|
||||
bool isStateVariable(VariableDeclaration const& _varDecl) const { return m_stateVariables.count(&_varDecl); }
|
||||
std::pair<u256, unsigned> storageLocationOfVariable(VariableDeclaration const& _varDecl) const
|
||||
std::pair<u256, unsigned> storageLocationOfStateVariable(VariableDeclaration const& _varDecl) const
|
||||
{
|
||||
solAssert(isStateVariable(_varDecl), "");
|
||||
return m_stateVariables.at(&_varDecl);
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
|
||||
string code;
|
||||
|
||||
auto const& location = m_context.storageLocationOfVariable(_varDecl);
|
||||
auto const& location = m_context.storageLocationOfStateVariable(_varDecl);
|
||||
code += Whiskers(R"(
|
||||
let slot := <slot>
|
||||
let offset := <offset>
|
||||
|
@ -75,18 +75,30 @@ struct CopyTranslate: public yul::ASTCopier
|
||||
{
|
||||
solAssert(reference.isOffset != reference.isSlot, "");
|
||||
|
||||
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(*varDecl);
|
||||
string value;
|
||||
if (varDecl->isStateVariable())
|
||||
value =
|
||||
reference.isSlot ?
|
||||
m_context.storageLocationOfStateVariable(*varDecl).first.str() :
|
||||
to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
else
|
||||
{
|
||||
solAssert(varDecl->isLocalVariable(), "");
|
||||
if (reference.isSlot)
|
||||
value = IRVariable{*varDecl}.part("slot").name();
|
||||
else if (varDecl->type()->isValueType())
|
||||
value = IRVariable{*varDecl}.part("offset").name();
|
||||
else
|
||||
{
|
||||
solAssert(!IRVariable{*varDecl}.hasPart("offset"), "");
|
||||
value = "0";
|
||||
}
|
||||
}
|
||||
|
||||
string const value = reference.isSlot ?
|
||||
slot_offset.first.str() :
|
||||
to_string(slot_offset.second);
|
||||
|
||||
return yul::Literal{
|
||||
_identifier.location,
|
||||
yul::LiteralKind::Number,
|
||||
yul::YulString{value},
|
||||
{}
|
||||
};
|
||||
if (isdigit(value.front()))
|
||||
return yul::Literal{_identifier.location, yul::LiteralKind::Number, yul::YulString{value}, {}};
|
||||
else
|
||||
return yul::Identifier{_identifier.location, yul::YulString{value}};
|
||||
}
|
||||
}
|
||||
return ASTCopier::operator()(_identifier);
|
||||
@ -152,8 +164,8 @@ void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _va
|
||||
_varDecl.immutable() ?
|
||||
IRLValue{*_varDecl.annotation().type, IRLValue::Immutable{&_varDecl}} :
|
||||
IRLValue{*_varDecl.annotation().type, IRLValue::Storage{
|
||||
util::toCompactHexWithPrefix(m_context.storageLocationOfVariable(_varDecl).first),
|
||||
m_context.storageLocationOfVariable(_varDecl).second
|
||||
util::toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_varDecl).first),
|
||||
m_context.storageLocationOfStateVariable(_varDecl).second
|
||||
}},
|
||||
*_varDecl.value()
|
||||
);
|
||||
@ -2026,8 +2038,8 @@ void IRGeneratorForStatements::handleVariableReference(
|
||||
setLValue(_referencingExpression, IRLValue{
|
||||
*_variable.annotation().type,
|
||||
IRLValue::Storage{
|
||||
toCompactHexWithPrefix(m_context.storageLocationOfVariable(_variable).first),
|
||||
m_context.storageLocationOfVariable(_variable).second
|
||||
toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_variable).first),
|
||||
m_context.storageLocationOfStateVariable(_variable).second
|
||||
}
|
||||
});
|
||||
else
|
||||
|
@ -53,6 +53,17 @@ IRVariable IRVariable::part(string const& _name) const
|
||||
solAssert(false, "Invalid stack item name: " + _name);
|
||||
}
|
||||
|
||||
bool IRVariable::hasPart(std::string const& _name) const
|
||||
{
|
||||
for (auto const& [itemName, itemType]: m_type.stackItems())
|
||||
if (itemName == _name)
|
||||
{
|
||||
solAssert(itemName.empty() || itemType, "");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<string> IRVariable::stackSlots() const
|
||||
{
|
||||
vector<string> result;
|
||||
|
@ -71,6 +71,10 @@ public:
|
||||
/// in ``m_type.stackItems()`` and may again occupy multiple stack slots.
|
||||
IRVariable part(std::string const& _slot) const;
|
||||
|
||||
/// @returns true if variable contains @a _name component
|
||||
/// @a _name name of the component that is being checked
|
||||
bool hasPart(std::string const& _name) const;
|
||||
|
||||
/// @returns a vector containing the names of the stack slots of the variable.
|
||||
std::vector<std::string> stackSlots() const;
|
||||
|
||||
|
@ -0,0 +1,18 @@
|
||||
contract C {
|
||||
uint256[] public a;
|
||||
|
||||
function f() public returns (uint256) {
|
||||
uint256[] storage x = a;
|
||||
uint256 off;
|
||||
assembly {
|
||||
sstore(x.slot, 7)
|
||||
off := x.offset
|
||||
}
|
||||
assert(off == 0);
|
||||
return a.length;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 7
|
Loading…
Reference in New Issue
Block a user