Properly compute source mappings for immutables.

This commit is contained in:
Christian Parpart
2021-10-12 17:56:17 +02:00
committed by Mathias Baumann
parent 49d7b78466
commit b1dd0d0d02
12 changed files with 164 additions and 20 deletions
+43 -4
View File
@@ -65,7 +65,7 @@ void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag)
setData(data);
}
size_t AssemblyItem::bytesRequired(size_t _addressLength) const
size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) const
{
switch (m_type)
{
@@ -87,10 +87,25 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength) const
case PushImmutable:
return 1 + 32;
case AssignImmutable:
if (m_immutableOccurrences)
return 1 + (3 + 32) * *m_immutableOccurrences;
{
unsigned long immutableOccurrences = 0;
// Skip exact immutables count if no precise count was requested
if (_precision == Precision::Approximate)
immutableOccurrences = 1; // Assume one immut. ref.
else
return 1 + (3 + 32) * 1024; // 1024 occurrences are beyond the maximum code size anyways.
{
solAssert(m_immutableOccurrences, "No immutable references. `bytesRequired()` called before assembly()?");
immutableOccurrences = m_immutableOccurrences.value();
}
if (immutableOccurrences != 0)
// (DUP DUP PUSH <n> ADD MSTORE)* (PUSH <n> ADD MSTORE)
return (immutableOccurrences - 1) * (5 + 32) + (3 + 32);
else
// POP POP
return 2;
}
case VerbatimBytecode:
return std::get<2>(*m_verbatimBytecode).size();
default:
@@ -322,6 +337,26 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
return _out;
}
size_t AssemblyItem::opcodeCount() const noexcept
{
switch (m_type)
{
case AssemblyItemType::AssignImmutable:
// Append empty items if this AssignImmutable was referenced more than once.
// For n immutable occurrences the first (n - 1) occurrences will
// generate 5 opcodes and the last will generate 3 opcodes,
// because it is reusing the 2 top-most elements on the stack.
solAssert(m_immutableOccurrences, "");
if (m_immutableOccurrences.value() != 0)
return (*m_immutableOccurrences - 1) * 5 + 3;
else
return 2; // two POP's
default:
return 1;
}
}
std::string AssemblyItem::computeSourceMapping(
AssemblyItems const& _items,
map<string, unsigned> const& _sourceIndicesMap
@@ -334,6 +369,7 @@ std::string AssemblyItem::computeSourceMapping(
int prevSourceIndex = -1;
int prevModifierDepth = -1;
char prevJump = 0;
for (auto const& item: _items)
{
if (!ret.empty())
@@ -402,6 +438,9 @@ std::string AssemblyItem::computeSourceMapping(
}
}
if (item.opcodeCount() > 1)
ret += string(item.opcodeCount() - 1, ';');
prevStart = location.start;
prevLength = length;
prevSourceIndex = sourceIndex;