mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9652 from ethereum/iceInlineAssemblyOffset
[Sol->Yul] Enabling storage pointers to local vars in inline assembly.
This commit is contained in:
commit
dbe0518cd2
@ -98,8 +98,9 @@ public:
|
|||||||
|
|
||||||
void addStateVariable(VariableDeclaration const& _varDecl, u256 _storageOffset, unsigned _byteOffset);
|
void addStateVariable(VariableDeclaration const& _varDecl, u256 _storageOffset, unsigned _byteOffset);
|
||||||
bool isStateVariable(VariableDeclaration const& _varDecl) const { return m_stateVariables.count(&_varDecl); }
|
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);
|
return m_stateVariables.at(&_varDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
|
|
||||||
string code;
|
string code;
|
||||||
|
|
||||||
auto const& location = m_context.storageLocationOfVariable(_varDecl);
|
auto const& location = m_context.storageLocationOfStateVariable(_varDecl);
|
||||||
code += Whiskers(R"(
|
code += Whiskers(R"(
|
||||||
let slot := <slot>
|
let slot := <slot>
|
||||||
let offset := <offset>
|
let offset := <offset>
|
||||||
|
@ -75,18 +75,30 @@ struct CopyTranslate: public yul::ASTCopier
|
|||||||
{
|
{
|
||||||
solAssert(reference.isOffset != reference.isSlot, "");
|
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 ?
|
if (isdigit(value.front()))
|
||||||
slot_offset.first.str() :
|
return yul::Literal{_identifier.location, yul::LiteralKind::Number, yul::YulString{value}, {}};
|
||||||
to_string(slot_offset.second);
|
else
|
||||||
|
return yul::Identifier{_identifier.location, yul::YulString{value}};
|
||||||
return yul::Literal{
|
|
||||||
_identifier.location,
|
|
||||||
yul::LiteralKind::Number,
|
|
||||||
yul::YulString{value},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ASTCopier::operator()(_identifier);
|
return ASTCopier::operator()(_identifier);
|
||||||
@ -152,8 +164,8 @@ void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _va
|
|||||||
_varDecl.immutable() ?
|
_varDecl.immutable() ?
|
||||||
IRLValue{*_varDecl.annotation().type, IRLValue::Immutable{&_varDecl}} :
|
IRLValue{*_varDecl.annotation().type, IRLValue::Immutable{&_varDecl}} :
|
||||||
IRLValue{*_varDecl.annotation().type, IRLValue::Storage{
|
IRLValue{*_varDecl.annotation().type, IRLValue::Storage{
|
||||||
util::toCompactHexWithPrefix(m_context.storageLocationOfVariable(_varDecl).first),
|
util::toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_varDecl).first),
|
||||||
m_context.storageLocationOfVariable(_varDecl).second
|
m_context.storageLocationOfStateVariable(_varDecl).second
|
||||||
}},
|
}},
|
||||||
*_varDecl.value()
|
*_varDecl.value()
|
||||||
);
|
);
|
||||||
@ -2026,8 +2038,8 @@ void IRGeneratorForStatements::handleVariableReference(
|
|||||||
setLValue(_referencingExpression, IRLValue{
|
setLValue(_referencingExpression, IRLValue{
|
||||||
*_variable.annotation().type,
|
*_variable.annotation().type,
|
||||||
IRLValue::Storage{
|
IRLValue::Storage{
|
||||||
toCompactHexWithPrefix(m_context.storageLocationOfVariable(_variable).first),
|
toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_variable).first),
|
||||||
m_context.storageLocationOfVariable(_variable).second
|
m_context.storageLocationOfStateVariable(_variable).second
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
|
@ -53,6 +53,17 @@ IRVariable IRVariable::part(string const& _name) const
|
|||||||
solAssert(false, "Invalid stack item name: " + _name);
|
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> IRVariable::stackSlots() const
|
||||||
{
|
{
|
||||||
vector<string> result;
|
vector<string> result;
|
||||||
|
@ -71,6 +71,10 @@ public:
|
|||||||
/// in ``m_type.stackItems()`` and may again occupy multiple stack slots.
|
/// in ``m_type.stackItems()`` and may again occupy multiple stack slots.
|
||||||
IRVariable part(std::string const& _slot) const;
|
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.
|
/// @returns a vector containing the names of the stack slots of the variable.
|
||||||
std::vector<std::string> stackSlots() const;
|
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