-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
eof: Support functions (CALLF
, RETF
, JUMPF
)
#15550
base: develop
Are you sure you want to change the base?
Conversation
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. |
19c3760
to
aa13c9c
Compare
fd78a06
to
8ceb5c4
Compare
8ceb5c4
to
9787050
Compare
436f00e
to
e4ab717
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor things from a quick pass over the PR.
libevmasm/Instruction.cpp
Outdated
{Instruction::RETF, {"RETF", 0, 0, 0, true, Tier::Special}}, | ||
{Instruction::CALLF, {"CALLF", 2, 0, 0, true, Tier::Special}}, | ||
{Instruction::JUMPF, {"JUMPF", 2, 0, 0, true, Tier::Special}}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should get dedicated tiers too, to match execution specs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have it also for DATALOADN. https://github.com/ethereum/execution-specs/blob/eips/prague/eof/src/ethereum/prague/vm/gas.py#L78
uint8_t argsNum; | ||
uint8_t retsNum; | ||
}; | ||
std::optional<FunctionSignature> m_functionSignature; ///< Only valid if m_type == CallF or JumpF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a getter, similarly to instruction()
, with an assert that the item type allows it.
libevmasm/Assembly.h
Outdated
AssemblyItem newFunctionCall(uint16_t _functionID) | ||
{ | ||
solAssert(_functionID < m_codeSections.size(), "Call to undeclared function."); | ||
solAssert(_functionID > 0, "Cannot call call section 0"); | ||
auto const& section = m_codeSections.at(_functionID); | ||
if (section.outputs != 0x80) | ||
return AssemblyItem::functionCall(_functionID, section.inputs, section.outputs); | ||
else | ||
return AssemblyItem::jumpF(_functionID, section.inputs); | ||
} | ||
|
||
AssemblyItem newFunctionReturn() | ||
{ | ||
return AssemblyItem::functionReturn(m_codeSections.at(m_currentCodeSection).outputs); | ||
} | ||
|
||
uint16_t createFunction(uint8_t _args, uint8_t _rets) | ||
{ | ||
size_t functionID = m_codeSections.size(); | ||
solAssert(functionID < 1024, "Too many functions."); | ||
solAssert(m_currentCodeSection == 0, "Functions need to be declared from the main block."); | ||
solAssert(_rets <= 0x80, "Too many function returns."); | ||
m_codeSections.emplace_back(CodeSection{_args, _rets, {}}); | ||
return static_cast<uint16_t>(functionID); | ||
} | ||
|
||
void beginFunction(uint16_t _functionID) | ||
{ | ||
solAssert(m_currentCodeSection == 0, "Atempted to begin a function before ending the last one."); | ||
solAssert(_functionID < m_codeSections.size(), "Attempt to begin an undeclared function."); | ||
auto& section = m_codeSections.at(_functionID); | ||
solAssert(section.items.empty(), "Function already defined."); | ||
m_currentCodeSection = _functionID; | ||
} | ||
void endFunction() | ||
{ | ||
solAssert(m_currentCodeSection != 0, "End function without begin function."); | ||
m_currentCodeSection = 0; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are long enough that I'd rather put them in the .cpp file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Fixed. const
added to two of them.
libevmasm/Assembly.cpp
Outdated
case CallF: | ||
{ | ||
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::CALLF)); | ||
solAssert(item.data() <= std::numeric_limits<uint16_t>::max(), "Invalid callf index value."); | ||
appendBigEndianUint16(ret.bytecode, item.data()); | ||
break; | ||
} | ||
case JumpF: | ||
{ | ||
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPF)); | ||
solAssert(item.data() <= std::numeric_limits<uint16_t>::max(), "Invalid jumpf index value."); | ||
appendBigEndianUint16(ret.bytecode, item.data()); | ||
break; | ||
} | ||
case RetF: | ||
{ | ||
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::RETF)); | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have sanity checks that the numbers of inputs and outputs actually match the function. It's technically possible to create AssemblyItem
without using the static helpers and get it wrong (or we might just forget when implementing asm import later). We should be able to catch this kind of mistake.
4f6d769
to
9a5d5a1
Compare
9a5d5a1
to
0b94103
Compare
Implement support for functions calls and returns for EOF.
Depends on: #15547