mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Implement subroutines for yul functions.
This commit is contained in:
committed by
Alex Beregszaszi
parent
dca85a286d
commit
cc04085b9e
@@ -573,7 +573,10 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
|
||||
yulAssert(
|
||||
_instr != evmasm::Instruction::JUMP &&
|
||||
_instr != evmasm::Instruction::JUMPI &&
|
||||
_instr != evmasm::Instruction::JUMPDEST,
|
||||
_instr != evmasm::Instruction::JUMPDEST &&
|
||||
_instr != evmasm::Instruction::JUMPSUB &&
|
||||
_instr != evmasm::Instruction::RETURNSUB &&
|
||||
_instr != evmasm::Instruction::BEGINSUB
|
||||
"");
|
||||
|
||||
auto errorForVM = [&](ErrorId _errorId, string const& vmKindMessage) {
|
||||
|
||||
@@ -70,6 +70,9 @@ std::map<string, evmasm::Instruction> const& Parser::instructions()
|
||||
{
|
||||
if (
|
||||
instruction.second == evmasm::Instruction::JUMPDEST ||
|
||||
instruction.second == evmasm::Instruction::BEGINSUB ||
|
||||
instruction.second == evmasm::Instruction::JUMPSUB ||
|
||||
instruction.second == evmasm::Instruction::RETURNSUB ||
|
||||
evmasm::isPushInstruction(instruction.second)
|
||||
)
|
||||
continue;
|
||||
|
||||
@@ -116,22 +116,22 @@ void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType)
|
||||
appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType);
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::appendBeginsub(LabelID, int)
|
||||
void EthAssemblyAdapter::appendBeginsub(LabelID _labelId, int)
|
||||
{
|
||||
// TODO we could emulate that, though
|
||||
yulAssert(false, "BEGINSUB not implemented for EVM 1.0");
|
||||
m_assembly.append(evmasm::AssemblyItem(evmasm::Subtag, _labelId));
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::appendJumpsub(LabelID, int, int)
|
||||
void EthAssemblyAdapter::appendJumpsub(LabelID _labelId, int _args, int _returns)
|
||||
{
|
||||
// TODO we could emulate that, though
|
||||
yulAssert(false, "JUMPSUB not implemented for EVM 1.0");
|
||||
appendLabelReference(_labelId);
|
||||
appendInstruction(evmasm::Instruction::JUMPSUB);
|
||||
m_assembly.adjustDeposit(-_args + _returns);
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::appendReturnsub(int, int)
|
||||
void EthAssemblyAdapter::appendReturnsub(int _returns, int _stackDiffAfter)
|
||||
{
|
||||
// TODO we could emulate that, though
|
||||
yulAssert(false, "RETURNSUB not implemented for EVM 1.0");
|
||||
appendInstruction(evmasm::Instruction::RETURNSUB);
|
||||
m_assembly.adjustDeposit(_stackDiffAfter - _returns);
|
||||
}
|
||||
|
||||
void EthAssemblyAdapter::appendAssemblySize()
|
||||
|
||||
@@ -53,8 +53,8 @@ public:
|
||||
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;
|
||||
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
|
||||
void appendBeginsub(LabelID, int) override;
|
||||
void appendJumpsub(LabelID, int, int) override;
|
||||
void appendReturnsub(int, int) override;
|
||||
void appendJumpsub(LabelID, int _args, int _returns) override;
|
||||
void appendReturnsub(int _returns, int _stackDiffAfter) override;
|
||||
void appendAssemblySize() override;
|
||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly() override;
|
||||
void appendDataOffset(SubID _sub) override;
|
||||
|
||||
@@ -267,7 +267,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
{
|
||||
m_assembly.setSourceLocation(_call.location);
|
||||
EVMAssembly::LabelID returnLabel(numeric_limits<EVMAssembly::LabelID>::max()); // only used for evm 1.0
|
||||
if (!m_evm15)
|
||||
if (!m_evm15 && !m_dialect.evmVersion().supportsSubroutines())
|
||||
{
|
||||
returnLabel = m_assembly.newLabelId();
|
||||
m_assembly.appendLabelReference(returnLabel);
|
||||
@@ -283,7 +283,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
for (auto const& arg: _call.arguments | boost::adaptors::reversed)
|
||||
visitExpression(arg);
|
||||
m_assembly.setSourceLocation(_call.location);
|
||||
if (m_evm15)
|
||||
if (m_evm15 || m_dialect.evmVersion().supportsSubroutines())
|
||||
m_assembly.appendJumpsub(
|
||||
functionEntryID(_call.functionName.name, *function),
|
||||
static_cast<int>(function->arguments.size()),
|
||||
@@ -417,7 +417,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
m_assembly.setSourceLocation(_function.location);
|
||||
int const stackHeightBefore = m_assembly.stackHeight();
|
||||
|
||||
if (m_evm15)
|
||||
if (m_evm15 || m_dialect.evmVersion().supportsSubroutines())
|
||||
m_assembly.appendBeginsub(functionEntryID(_function.name, function), static_cast<int>(_function.parameters.size()));
|
||||
else
|
||||
m_assembly.appendLabel(functionEntryID(_function.name, function));
|
||||
@@ -475,7 +475,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
// This vector holds the desired target positions of all stack slots and is
|
||||
// modified parallel to the actual stack.
|
||||
vector<int> stackLayout;
|
||||
if (!m_evm15)
|
||||
if (!m_evm15 && !m_dialect.evmVersion().supportsSubroutines())
|
||||
stackLayout.push_back(static_cast<int>(_function.returnVariables.size())); // Move return label to the top
|
||||
stackLayout += vector<int>(_function.parameters.size(), -1); // discard all arguments
|
||||
|
||||
@@ -511,7 +511,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
yulAssert(i == static_cast<size_t>(stackLayout[i]), "Error reshuffling stack.");
|
||||
}
|
||||
}
|
||||
if (m_evm15)
|
||||
if (m_evm15 || m_dialect.evmVersion().supportsSubroutines())
|
||||
m_assembly.appendReturnsub(static_cast<int>(_function.returnVariables.size()), stackHeightBefore);
|
||||
else
|
||||
m_assembly.appendJump(
|
||||
@@ -519,6 +519,8 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
AbstractAssembly::JumpType::OutOfFunction
|
||||
);
|
||||
m_assembly.setStackHeight(stackHeightBefore);
|
||||
// TODO add BEGINSUB?
|
||||
// We need to make sure that we did function hoister and move the "main code" to the beginning.
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(ForLoop const& _forLoop)
|
||||
|
||||
@@ -101,21 +101,17 @@ void NoOutputAssembly::appendJumpToIf(LabelID _labelId, JumpType)
|
||||
|
||||
void NoOutputAssembly::appendBeginsub(LabelID, int _arguments)
|
||||
{
|
||||
yulAssert(m_evm15, "BEGINSUB used for EVM 1.0");
|
||||
yulAssert(_arguments >= 0, "");
|
||||
m_stackHeight += _arguments;
|
||||
}
|
||||
|
||||
void NoOutputAssembly::appendJumpsub(LabelID, int _arguments, int _returns)
|
||||
{
|
||||
yulAssert(m_evm15, "JUMPSUB used for EVM 1.0");
|
||||
yulAssert(_arguments >= 0 && _returns >= 0, "");
|
||||
m_stackHeight += _returns - _arguments;
|
||||
}
|
||||
|
||||
void NoOutputAssembly::appendReturnsub(int _returns, int _stackDiffAfter)
|
||||
{
|
||||
yulAssert(m_evm15, "RETURNSUB used for EVM 1.0");
|
||||
yulAssert(_returns >= 0, "");
|
||||
m_stackHeight += _stackDiffAfter - _returns;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user