Skip to content

Commit

Permalink
Merge pull request #15628 from ipsilon/eof-fix-immutables
Browse files Browse the repository at this point in the history
eof: Fix immutables
  • Loading branch information
cameel authored Dec 12, 2024
2 parents 397d971 + b3bf85e commit 9ad6660
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 2 deletions.
10 changes: 9 additions & 1 deletion libsolidity/codegen/ir/IRGenerationContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void IRGenerationContext::resetLocalVariables()

void IRGenerationContext::registerImmutableVariable(VariableDeclaration const& _variable)
{
solAssert(m_executionContext != ExecutionContext::Deployed);
solAssert(_variable.immutable(), "Attempted to register a non-immutable variable as immutable.");
solUnimplementedAssert(
_variable.annotation().type->isValueType(),
Expand Down Expand Up @@ -122,6 +123,7 @@ size_t IRGenerationContext::reservedMemorySize() const

void IRGenerationContext::registerLibraryAddressImmutable()
{
solAssert(m_executionContext != ExecutionContext::Deployed);
solAssert(m_reservedMemory.has_value(), "Reserved memory has already been reset.");
solAssert(!m_libraryAddressImmutableOffset.has_value());
m_libraryAddressImmutableOffset = CompilerUtils::generalPurposeMemoryStart + *m_reservedMemory;
Expand Down Expand Up @@ -156,7 +158,13 @@ size_t IRGenerationContext::reservedMemory()
immutableVariablesSize += var->type()->sizeOnStack() * 32;
}

solAssert(immutableVariablesSize == reservedMemory);
// In Creation context check that only immutable variables or library address are stored in the reserved memory.
// In Deployed context (for EOF) m_immutableVariables contains offsets in EOF data section.
solAssert(
(m_executionContext == ExecutionContext::Creation &&
reservedMemory == immutableVariablesSize + (m_libraryAddressImmutableOffset.has_value() ? 32 : 0)) ||
(m_executionContext == ExecutionContext::Deployed && reservedMemory == 0)
);

m_reservedMemory = std::nullopt;
return reservedMemory;
Expand Down
15 changes: 14 additions & 1 deletion libsolidity/codegen/ir/IRGenerationContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@ class IRGenerationContext

langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; }
langutil::CharStreamProvider const* soliditySourceProvider() const { return m_soliditySourceProvider; }
std::map<VariableDeclaration const*, size_t> const& immutableVariables() const { return m_immutableVariables; }
void setImmutableVariables(std::map<VariableDeclaration const*, size_t> _immutableVariables)
{
solAssert(m_eofVersion.has_value());
solAssert(m_executionContext == ExecutionContext::Deployed);
m_immutableVariables = std::move(_immutableVariables);
}
void setLibraryAddressImmutableOffset(size_t _libraryAddressImmutableOffset)
{
solAssert(m_eofVersion.has_value());
solAssert(m_executionContext == ExecutionContext::Deployed);
m_libraryAddressImmutableOffset = _libraryAddressImmutableOffset;
}

private:
langutil::EVMVersion m_evmVersion;
Expand All @@ -176,7 +189,7 @@ class IRGenerationContext
ContractDefinition const* m_mostDerivedContract = nullptr;
std::map<VariableDeclaration const*, IRVariable> m_localVariables;
/// Memory offsets reserved for the values of immutable variables during contract creation.
/// This map is empty in the runtime context.
/// This map is empty in the legacy runtime context and may be not empty in EOF runtime context.
std::map<VariableDeclaration const*, size_t> m_immutableVariables;
std::optional<size_t> m_libraryAddressImmutableOffset;
/// Total amount of reserved memory. Reserved memory is used to store
Expand Down
14 changes: 14 additions & 0 deletions libsolidity/codegen/ir/IRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,21 @@ std::string IRGenerator::generate(
t("memoryInitCreation", memoryInit(!creationInvolvesMemoryUnsafeAssembly));
t("useSrcMapCreation", formatUseSrcMap(m_context));

auto const immutableVariables = m_context.immutableVariables();
auto const libraryAddressImmutableOffset = (_contract.isLibrary() && eof) ?
m_context.libraryAddressImmutableOffset() : 0;

resetContext(_contract, ExecutionContext::Deployed);

// When generating to EOF we have to initialize these two members, because they store offsets in EOF data section
// which is used during deployed container generation
if (m_eofVersion.has_value())
{
m_context.setImmutableVariables(std::move(immutableVariables));
if (_contract.isLibrary())
m_context.setLibraryAddressImmutableOffset(libraryAddressImmutableOffset);
}

// NOTE: Function pointers can be passed from creation code via storage variables. We need to
// get all the functions they could point to into the dispatch functions even if they're never
// referenced by name in the deployed code.
Expand Down Expand Up @@ -1153,6 +1166,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon
m_context.debugInfoSelection(),
m_context.soliditySourceProvider()
);

m_context = std::move(newContext);

m_context.setMostDerivedContract(_contract);
Expand Down
2 changes: 2 additions & 0 deletions test/libsolidity/semanticTests/immutable/stub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ contract C {
return (x+x,y);
}
}
// ====
// bytecodeFormat: legacy,>=EOFv1
// ----
// f() -> 84, 23
2 changes: 2 additions & 0 deletions test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ object "a" {
retf()
}
}
// ====
// bytecodeFormat: legacy,>=EOFv1
// ----
// DeclarationError 4619: (32-37): Function "callf" not found.
// DeclarationError 4619: (48-53): Function "jumpf" not found.
Expand Down

0 comments on commit 9ad6660

Please sign in to comment.