mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Introduce machine-dependent stack adjustment.
This commit is contained in:
parent
64ddb176bb
commit
fefd3b866d
@ -105,6 +105,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
{
|
||||
returnLabel = m_assembly.newLabelId();
|
||||
m_assembly.appendLabelReference(returnLabel);
|
||||
m_stackAdjustment++;
|
||||
}
|
||||
|
||||
Scope::Function* function = nullptr;
|
||||
@ -125,6 +126,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
|
||||
{
|
||||
m_assembly.appendJumpTo(*function->id, function->returns.size() - function->arguments.size() - 1);
|
||||
m_assembly.appendLabel(returnLabel);
|
||||
m_stackAdjustment--;
|
||||
}
|
||||
checkStackHeight(&_call);
|
||||
}
|
||||
@ -280,7 +282,8 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
Scope::Function& function = boost::get<Scope::Function>(m_scope->identifiers.at(_function.name));
|
||||
assignLabelIdIfUnset(function.id);
|
||||
|
||||
int height = m_evm15 ? 0 : 1;
|
||||
int const localStackAdjustment = m_evm15 ? 0 : 1;
|
||||
int height = localStackAdjustment;
|
||||
solAssert(m_info.scopes.at(&_function.body), "");
|
||||
Scope* varScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get();
|
||||
solAssert(varScope, "");
|
||||
@ -294,12 +297,18 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
m_assembly.setSourceLocation(_function.location);
|
||||
int stackHeightBefore = m_assembly.stackHeight();
|
||||
AbstractAssembly::LabelID afterFunction = m_assembly.newLabelId();
|
||||
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
|
||||
|
||||
if (m_evm15)
|
||||
{
|
||||
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore);
|
||||
m_assembly.appendBeginsub(*function.id, _function.arguments.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
|
||||
m_assembly.appendLabel(*function.id);
|
||||
}
|
||||
m_stackAdjustment += localStackAdjustment;
|
||||
|
||||
for (auto const& v: _function.returns)
|
||||
{
|
||||
@ -309,10 +318,11 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
m_assembly.appendConstant(u256(0));
|
||||
}
|
||||
|
||||
CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, 0).run(_function.body);
|
||||
CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment)
|
||||
.run(_function.body);
|
||||
|
||||
if (_function.arguments.size() > 0)
|
||||
{
|
||||
// Stack of target positions of stack elements
|
||||
vector<int> stackLayout;
|
||||
if (!m_evm15)
|
||||
stackLayout.push_back(_function.returns.size()); // Move return label to the top
|
||||
@ -321,7 +331,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
stackLayout.push_back(i);
|
||||
|
||||
solAssert(stackLayout.size() <= 17, "Stack too deep");
|
||||
while (stackLayout.back() != int(stackLayout.size() - 1))
|
||||
while (!stackLayout.empty() && stackLayout.back() != int(stackLayout.size() - 1))
|
||||
if (stackLayout.back() < 0)
|
||||
{
|
||||
m_assembly.appendInstruction(solidity::Instruction::POP);
|
||||
@ -340,13 +350,14 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
||||
m_assembly.appendReturnsub(_function.returns.size());
|
||||
else
|
||||
m_assembly.appendJump(stackHeightBefore - _function.returns.size());
|
||||
m_stackAdjustment -= localStackAdjustment;
|
||||
m_assembly.appendLabel(afterFunction);
|
||||
checkStackHeight(&_function);
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(Block const& _block)
|
||||
{
|
||||
CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_initialStackHeight).run(_block);
|
||||
CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block);
|
||||
}
|
||||
|
||||
AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier)
|
||||
@ -420,11 +431,11 @@ void CodeTransform::checkStackHeight(void const* _astElement)
|
||||
{
|
||||
solAssert(m_info.stackHeightInfo.count(_astElement), "Stack height for AST element not found.");
|
||||
solAssert(
|
||||
m_info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_initialStackHeight,
|
||||
m_info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_stackAdjustment,
|
||||
"Stack height mismatch between analysis and code generation phase: Analysis: " +
|
||||
to_string(m_info.stackHeightInfo.at(_astElement)) +
|
||||
" code gen: " +
|
||||
to_string(m_assembly.stackHeight() - m_initialStackHeight)
|
||||
to_string(m_assembly.stackHeight() - m_stackAdjustment)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -80,14 +80,14 @@ protected:
|
||||
solidity::assembly::AsmAnalysisInfo& _analysisInfo,
|
||||
bool _evm15,
|
||||
ExternalIdentifierAccess const& _identifierAccess,
|
||||
int _initialStackHeight
|
||||
int _stackAdjustment
|
||||
):
|
||||
m_errorReporter(_errorReporter),
|
||||
m_assembly(_assembly),
|
||||
m_info(_analysisInfo),
|
||||
m_evm15(_evm15),
|
||||
m_identifierAccess(_identifierAccess),
|
||||
m_initialStackHeight(_initialStackHeight)
|
||||
m_stackAdjustment(_stackAdjustment)
|
||||
{}
|
||||
|
||||
public:
|
||||
@ -128,7 +128,11 @@ public:
|
||||
solidity::assembly::Scope* m_scope = nullptr;
|
||||
bool m_evm15 = false;
|
||||
ExternalIdentifierAccess m_identifierAccess;
|
||||
int const m_initialStackHeight;
|
||||
/// Adjustment between the stack height as determined during the analysis phase
|
||||
/// and the stack height in the assembly. This is caused by an initial stack being present
|
||||
/// for inline assembly and different stack heights depending on the EVM backend used
|
||||
/// (EVM 1.0 or 1.5).
|
||||
int m_stackAdjustment = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -203,8 +203,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
|
||||
}
|
||||
|
||||
int const stackHeight = m_stackHeight;
|
||||
// 1 for return label, depends on VM version
|
||||
m_stackHeight = 1 + _funDef.arguments.size() + _funDef.returns.size();
|
||||
m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();
|
||||
|
||||
bool success = (*this)(_funDef.body);
|
||||
|
||||
@ -258,11 +257,10 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
m_stackHeight += 1; // Return label, but depends on backend
|
||||
for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
|
||||
if (!expectExpression(arg))
|
||||
success = false;
|
||||
m_stackHeight += int(returns) - int(arguments) - 1; // Return label, but depends on backend
|
||||
m_stackHeight += int(returns) - int(arguments);
|
||||
m_info.stackHeightInfo[&_funCall] = m_stackHeight;
|
||||
return success;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user