Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of EOF in Solidity #15294

Draft
wants to merge 15 commits into
base: develop
Choose a base branch
from
Draft

Conversation

rodiazet
Copy link
Contributor

@rodiazet rodiazet commented Jul 23, 2024

EOF Mega Spec

TODO:

  • There is a couple TODOs added in the commits. They need to be implemented in separated PR.
  • Immutables bug reported by Paradigm needs to be fixed. FIXED
  • Semantic tests may stop passing because part of them depend on exact contract code which may change with compiler development. Additional support for contract addresses needs to be implemented in soltest.
  • CI integration may be required.

Copy link

Thank you for your contribution to the Solidity compiler! A team member will follow up shortly.

If you haven't read our contributing guidelines and our review checklist before, please do it now, this makes the reviewing process and accepting your contribution smoother.

If you have any questions or need our help, feel free to post them in the PR or talk to us directly on the #solidity-dev channel on Matrix.

@rodiazet rodiazet force-pushed the eof-cleaned branch 10 times, most recently from c49b88b to 88cf606 Compare July 29, 2024 16:56
m_items.back().setLocation(m_currentSourceLocation);
m_items.back().m_modifierDepth = m_currentModifierDepth;
return m_items.back();
auto& currentItems = m_codeSections.at(m_currentCodeSection).items;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_codeSection.at(...) can throw - either a util::contains check should go here, or even better, an assertion if you're sure that the current code section is present.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I'm adding an assertion as m_currentCodeSection is changed on in void beginFunction(uint16_t _functionID) and similar assertion is there too.

}

unsigned Assembly::codeSize(unsigned subTagSize) const
{
for (unsigned tagSize = subTagSize; true; ++tagSize)
{
size_t ret = 1;
for (auto const& i: m_data)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is m_data no longer taken into account?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That part of the calculation moved to ::assemble - it's part of bytesRequiredForDataUpperBound there (both for EOF and legacy)...

But we should probably rethink this as well at the latest as part of #15294 (comment) - For example: since in EOF there won't be any PushTags, the weird outer loop here becomes superfluous as well, since code size no longer depends on the tag size (the "tag size" in general becomes irrelevant).

For now, maybe a comment in the header is enough, clarifying that even for legacy this now only counts "pure" code size without data?

libevmasm/Assembly.cpp Show resolved Hide resolved

std::vector<size_t> successors;

if (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that ConditionalRelativeJump is not here because both 'branches' need to have their stack heights calculated? I.e. both the next assembly item as well as the tagged one that we're (possibly) jumping to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. For ConditionalRelativeJump we need to calculated both branches and one of them starts with the next instruction but second is the jump target. It's being added to successors by next if

{
uint16_t maxStackHeight = _args;
std::stack<size_t> worklist;
std::vector<int32_t> stack_heights(_items.size(), -1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::vector<int32_t> stack_heights(_items.size(), -1);
std::vector<size_t> stack_heights(_items.size(), std::numeric_limits<size_t>::max);

stackHeight should also be unsigned - I would assume our stack height is never going to be negative?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

libevmasm/Assembly.cpp Outdated Show resolved Hide resolved
libevmasm/Assembly.cpp Show resolved Hide resolved
libevmasm/Assembly.cpp Show resolved Hide resolved
libevmasm/BlockDeduplicator.cpp Show resolved Hide resolved
@@ -396,7 +399,8 @@ void Assembly::assemblyStream(
{
Functionalizer f(_out, _prefix, _sourceCodes, *this);

for (auto const& i: m_items)
// TODO: support EOF
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In cases like this (and e.g. similarly for Assembly::assemblyJSON and possibly a few of other similar TODOs like this), it'd be better to add an explicit

solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented.");

Better to error out and then implement it properly later in a subsequent PR than to give a partial output of only the first code section with the rest missing.

Copy link
Contributor Author

@rodiazet rodiazet Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Additionally I switched off the assembly optimization for EOF as event first step requires verification.

@ekpyron ekpyron mentioned this pull request Jul 31, 2024
37 tasks
@rodiazet rodiazet force-pushed the eof-cleaned branch 2 times, most recently from 5ab6923 to 64e4050 Compare August 8, 2024 07:57
rodiazet and others added 13 commits August 8, 2024 15:14
…typo in input parsing

Co-authored-by: Daniel Kirchner <[email protected]>
Add `DATALOAD` instruction
Preparation to implement new contract creation
Co-authored-by: Daniel Kirchner <[email protected]>
@@ -76,6 +87,16 @@ void cleanUnreachable(CFG& _cfg)
cxx20::erase_if(node->entries, [&](CFG::BasicBlock* entry) -> bool {
return !reachabilityCheck.visited.count(entry);
});

// Remove functions which are never referenced.
Copy link
Member

@ekpyron ekpyron Aug 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change in cleanUnreachable could be split out into a separate PR and merged directly into develop up front, right?
EDIT: we can revisit once we get to the commits containing it, whether splitting really makes things easier, fine for now.

auto eofVersion = settings["evmVersion"].get<uint8_t>();
auto eofVersion = settings["eofVersion"].get<uint8_t>();
Copy link
Member

@ekpyron ekpyron Aug 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the related evm-version check change can and should separately go into develop :-).
EDIT: as per chat, let's just merge the first three commits for now :-).

@@ -1412,7 +1420,7 @@ void CompilerStack::compileContract(

Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());

std::shared_ptr<Compiler> compiler = std::make_shared<Compiler>(m_evmVersion, m_revertStrings, m_optimiserSettings);
std::shared_ptr<Compiler> compiler = std::make_shared<Compiler>(m_evmVersion, m_eofVersion, m_revertStrings, m_optimiserSettings);
Copy link
Member

@ekpyron ekpyron Aug 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing m_eofVersion around here, we can just assert

solUnimplementedAssert(!m_eofVersion, "EOF is not supported for legacy code generation");

(this is only-legacy, see the solAssert(!m_viaIR, ""); below)
And thereby leave libsolidity/codegen/Compiler.h and libsolidity/codegen/CompilerContext.h largely untouched (resp. where they need an eof version just use std::nullopt directly).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text = "eofcreate(" + std::to_string(static_cast<size_t>(data())) + ")";
break;
case ReturnContract:
text = "returcontract(" + std::to_string(static_cast<size_t>(data())) + ")";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in assembly text of RETURNCONTRACT

Suggested change
text = "returcontract(" + std::to_string(static_cast<size_t>(data())) + ")";
text = "returncontract(" + std::to_string(static_cast<size_t>(data())) + ")";

@cameel cameel added the EOF label Aug 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants