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();
|
returnLabel = m_assembly.newLabelId();
|
||||||
m_assembly.appendLabelReference(returnLabel);
|
m_assembly.appendLabelReference(returnLabel);
|
||||||
|
m_stackAdjustment++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Function* function = nullptr;
|
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.appendJumpTo(*function->id, function->returns.size() - function->arguments.size() - 1);
|
||||||
m_assembly.appendLabel(returnLabel);
|
m_assembly.appendLabel(returnLabel);
|
||||||
|
m_stackAdjustment--;
|
||||||
}
|
}
|
||||||
checkStackHeight(&_call);
|
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));
|
Scope::Function& function = boost::get<Scope::Function>(m_scope->identifiers.at(_function.name));
|
||||||
assignLabelIdIfUnset(function.id);
|
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), "");
|
solAssert(m_info.scopes.at(&_function.body), "");
|
||||||
Scope* varScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get();
|
Scope* varScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get();
|
||||||
solAssert(varScope, "");
|
solAssert(varScope, "");
|
||||||
@ -294,12 +297,18 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
|||||||
m_assembly.setSourceLocation(_function.location);
|
m_assembly.setSourceLocation(_function.location);
|
||||||
int stackHeightBefore = m_assembly.stackHeight();
|
int stackHeightBefore = m_assembly.stackHeight();
|
||||||
AbstractAssembly::LabelID afterFunction = m_assembly.newLabelId();
|
AbstractAssembly::LabelID afterFunction = m_assembly.newLabelId();
|
||||||
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
|
|
||||||
|
|
||||||
if (m_evm15)
|
if (m_evm15)
|
||||||
|
{
|
||||||
|
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore);
|
||||||
m_assembly.appendBeginsub(*function.id, _function.arguments.size());
|
m_assembly.appendBeginsub(*function.id, _function.arguments.size());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
|
||||||
m_assembly.appendLabel(*function.id);
|
m_assembly.appendLabel(*function.id);
|
||||||
|
}
|
||||||
|
m_stackAdjustment += localStackAdjustment;
|
||||||
|
|
||||||
for (auto const& v: _function.returns)
|
for (auto const& v: _function.returns)
|
||||||
{
|
{
|
||||||
@ -309,10 +318,11 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
|||||||
m_assembly.appendConstant(u256(0));
|
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;
|
vector<int> stackLayout;
|
||||||
if (!m_evm15)
|
if (!m_evm15)
|
||||||
stackLayout.push_back(_function.returns.size()); // Move return label to the top
|
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);
|
stackLayout.push_back(i);
|
||||||
|
|
||||||
solAssert(stackLayout.size() <= 17, "Stack too deep");
|
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)
|
if (stackLayout.back() < 0)
|
||||||
{
|
{
|
||||||
m_assembly.appendInstruction(solidity::Instruction::POP);
|
m_assembly.appendInstruction(solidity::Instruction::POP);
|
||||||
@ -340,13 +350,14 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
|
|||||||
m_assembly.appendReturnsub(_function.returns.size());
|
m_assembly.appendReturnsub(_function.returns.size());
|
||||||
else
|
else
|
||||||
m_assembly.appendJump(stackHeightBefore - _function.returns.size());
|
m_assembly.appendJump(stackHeightBefore - _function.returns.size());
|
||||||
|
m_stackAdjustment -= localStackAdjustment;
|
||||||
m_assembly.appendLabel(afterFunction);
|
m_assembly.appendLabel(afterFunction);
|
||||||
checkStackHeight(&_function);
|
checkStackHeight(&_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeTransform::operator()(Block const& _block)
|
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)
|
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.count(_astElement), "Stack height for AST element not found.");
|
||||||
solAssert(
|
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: " +
|
"Stack height mismatch between analysis and code generation phase: Analysis: " +
|
||||||
to_string(m_info.stackHeightInfo.at(_astElement)) +
|
to_string(m_info.stackHeightInfo.at(_astElement)) +
|
||||||
" code gen: " +
|
" 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,
|
solidity::assembly::AsmAnalysisInfo& _analysisInfo,
|
||||||
bool _evm15,
|
bool _evm15,
|
||||||
ExternalIdentifierAccess const& _identifierAccess,
|
ExternalIdentifierAccess const& _identifierAccess,
|
||||||
int _initialStackHeight
|
int _stackAdjustment
|
||||||
):
|
):
|
||||||
m_errorReporter(_errorReporter),
|
m_errorReporter(_errorReporter),
|
||||||
m_assembly(_assembly),
|
m_assembly(_assembly),
|
||||||
m_info(_analysisInfo),
|
m_info(_analysisInfo),
|
||||||
m_evm15(_evm15),
|
m_evm15(_evm15),
|
||||||
m_identifierAccess(_identifierAccess),
|
m_identifierAccess(_identifierAccess),
|
||||||
m_initialStackHeight(_initialStackHeight)
|
m_stackAdjustment(_stackAdjustment)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -128,7 +128,11 @@ public:
|
|||||||
solidity::assembly::Scope* m_scope = nullptr;
|
solidity::assembly::Scope* m_scope = nullptr;
|
||||||
bool m_evm15 = false;
|
bool m_evm15 = false;
|
||||||
ExternalIdentifierAccess m_identifierAccess;
|
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;
|
int const stackHeight = m_stackHeight;
|
||||||
// 1 for return label, depends on VM version
|
m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();
|
||||||
m_stackHeight = 1 + _funDef.arguments.size() + _funDef.returns.size();
|
|
||||||
|
|
||||||
bool success = (*this)(_funDef.body);
|
bool success = (*this)(_funDef.body);
|
||||||
|
|
||||||
@ -258,11 +257,10 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_stackHeight += 1; // Return label, but depends on backend
|
|
||||||
for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
|
for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
|
||||||
if (!expectExpression(arg))
|
if (!expectExpression(arg))
|
||||||
success = false;
|
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;
|
m_info.stackHeightInfo[&_funCall] = m_stackHeight;
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user