Remove stack height checks.

This commit is contained in:
chriseth 2020-01-15 23:23:32 +01:00 committed by Mathias Baumann
parent 0dd398e2ac
commit f0afb0aeff
5 changed files with 7 additions and 91 deletions

View File

@ -101,7 +101,6 @@ bool AsmAnalyzer::operator()(Literal const& _literal)
} }
else if (_literal.kind == LiteralKind::Boolean) else if (_literal.kind == LiteralKind::Boolean)
yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, ""); yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "");
m_info.stackHeightInfo[&_literal] = m_stackHeight;
return true; return true;
} }
@ -151,7 +150,6 @@ bool AsmAnalyzer::operator()(Identifier const& _identifier)
} }
m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize; m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize;
} }
m_info.stackHeightInfo[&_identifier] = m_stackHeight;
return success; return success;
} }
@ -170,7 +168,6 @@ bool AsmAnalyzer::operator()(ExpressionStatement const& _statement)
m_errorReporter.error(Error::Type::TypeError, _statement.location, msg); m_errorReporter.error(Error::Type::TypeError, _statement.location, msg);
success = false; success = false;
} }
m_info.stackHeightInfo[&_statement] = m_stackHeight;
return success; return success;
} }
@ -196,7 +193,6 @@ bool AsmAnalyzer::operator()(Assignment const& _assignment)
for (auto const& variableName: _assignment.variableNames) for (auto const& variableName: _assignment.variableNames)
if (!checkAssignment(variableName, 1)) if (!checkAssignment(variableName, 1))
success = false; success = false;
m_info.stackHeightInfo[&_assignment] = m_stackHeight;
return success; return success;
} }
@ -239,7 +235,6 @@ bool AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
expectValidType(variable.type, variable.location); expectValidType(variable.type, variable.location);
m_activeVariables.insert(&std::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name))); m_activeVariables.insert(&std::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)));
} }
m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
return success; return success;
} }
@ -261,7 +256,6 @@ bool AsmAnalyzer::operator()(FunctionDefinition const& _funDef)
bool success = (*this)(_funDef.body); bool success = (*this)(_funDef.body);
m_stackHeight = stackHeight; m_stackHeight = stackHeight;
m_info.stackHeightInfo[&_funDef] = m_stackHeight;
return success; return success;
} }
@ -334,7 +328,6 @@ bool AsmAnalyzer::operator()(FunctionCall const& _funCall)
} }
// Use argument size instead of parameter count to avoid misleading errors. // Use argument size instead of parameter count to avoid misleading errors.
m_stackHeight += int(returns) - int(_funCall.arguments.size()); m_stackHeight += int(returns) - int(_funCall.arguments.size());
m_info.stackHeightInfo[&_funCall] = m_stackHeight;
return success; return success;
} }
@ -351,8 +344,6 @@ bool AsmAnalyzer::operator()(If const& _if)
if (!(*this)(_if.body)) if (!(*this)(_if.body))
success = false; success = false;
m_info.stackHeightInfo[&_if] = m_stackHeight;
return success; return success;
} }
@ -421,7 +412,6 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
} }
m_stackHeight = initialHeight; m_stackHeight = initialHeight;
m_info.stackHeightInfo[&_switch] = m_stackHeight;
return success; return success;
} }
@ -458,31 +448,12 @@ bool AsmAnalyzer::operator()(ForLoop const& _for)
success = false; success = false;
m_stackHeight = initialHeight; m_stackHeight = initialHeight;
m_info.stackHeightInfo[&_for] = m_stackHeight;
m_currentScope = outerScope; m_currentScope = outerScope;
m_currentForLoop = outerForLoop; m_currentForLoop = outerForLoop;
return success; return success;
} }
bool AsmAnalyzer::operator()(Break const& _break)
{
m_info.stackHeightInfo[&_break] = m_stackHeight;
return true;
}
bool AsmAnalyzer::operator()(Continue const& _continue)
{
m_info.stackHeightInfo[&_continue] = m_stackHeight;
return true;
}
bool AsmAnalyzer::operator()(Leave const& _leaveStatement)
{
m_info.stackHeightInfo[&_leaveStatement] = m_stackHeight;
return true;
}
bool AsmAnalyzer::operator()(Block const& _block) bool AsmAnalyzer::operator()(Block const& _block)
{ {
bool success = true; bool success = true;
@ -512,7 +483,6 @@ bool AsmAnalyzer::operator()(Block const& _block)
success = false; success = false;
} }
m_info.stackHeightInfo[&_block] = m_stackHeight;
m_currentScope = previousScope; m_currentScope = previousScope;
return success; return success;
} }

View File

@ -87,9 +87,9 @@ public:
bool operator()(If const& _if); bool operator()(If const& _if);
bool operator()(Switch const& _switch); bool operator()(Switch const& _switch);
bool operator()(ForLoop const& _forLoop); bool operator()(ForLoop const& _forLoop);
bool operator()(Break const&); bool operator()(Break const&) { return true; }
bool operator()(Continue const&); bool operator()(Continue const&) { return true; }
bool operator()(Leave const&); bool operator()(Leave const&) { return true; }
bool operator()(Block const& _block); bool operator()(Block const& _block);
private: private:

View File

@ -36,7 +36,6 @@ struct AsmAnalysisInfo
using StackHeightInfo = std::map<void const*, int>; using StackHeightInfo = std::map<void const*, int>;
using Scopes = std::map<Block const*, std::shared_ptr<Scope>>; using Scopes = std::map<Block const*, std::shared_ptr<Scope>>;
Scopes scopes; Scopes scopes;
StackHeightInfo stackHeightInfo;
/// Virtual blocks which will be used for scopes for function arguments and return values. /// Virtual blocks which will be used for scopes for function arguments and return values.
std::map<FunctionDefinition const*, std::shared_ptr<Block const>> virtualBlocks; std::map<FunctionDefinition const*, std::shared_ptr<Block const>> virtualBlocks;
}; };

View File

@ -102,7 +102,6 @@ CodeTransform::CodeTransform(
bool _evm15, bool _evm15,
ExternalIdentifierAccess const& _identifierAccess, ExternalIdentifierAccess const& _identifierAccess,
bool _useNamedLabelsForFunctions, bool _useNamedLabelsForFunctions,
int _stackAdjustment,
shared_ptr<Context> _context shared_ptr<Context> _context
): ):
m_assembly(_assembly), m_assembly(_assembly),
@ -113,7 +112,6 @@ CodeTransform::CodeTransform(
m_evm15(_evm15), m_evm15(_evm15),
m_useNamedLabelsForFunctions(_useNamedLabelsForFunctions), m_useNamedLabelsForFunctions(_useNamedLabelsForFunctions),
m_identifierAccess(_identifierAccess), m_identifierAccess(_identifierAccess),
m_stackAdjustment(_stackAdjustment),
m_context(_context) m_context(_context)
{ {
if (!m_context) if (!m_context)
@ -159,7 +157,6 @@ void CodeTransform::freeUnusedVariables()
{ {
yulAssert(m_unusedStackSlots.erase(m_assembly.stackHeight() - 1), ""); yulAssert(m_unusedStackSlots.erase(m_assembly.stackHeight() - 1), "");
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::Instruction::POP);
--m_stackAdjustment;
} }
} }
@ -178,11 +175,11 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
yulAssert(m_scope, ""); yulAssert(m_scope, "");
int const numVariables = _varDecl.variables.size(); int const numVariables = _varDecl.variables.size();
int height = m_assembly.stackHeight(); int heightAtStart = m_assembly.stackHeight();
if (_varDecl.value) if (_varDecl.value)
{ {
std::visit(*this, *_varDecl.value); std::visit(*this, *_varDecl.value);
expectDeposit(numVariables, height); expectDeposit(numVariables, heightAtStart);
} }
else else
{ {
@ -196,7 +193,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
{ {
YulString varName = _varDecl.variables[varIndex].name; YulString varName = _varDecl.variables[varIndex].name;
auto& var = std::get<Scope::Variable>(m_scope->identifiers.at(varName)); auto& var = std::get<Scope::Variable>(m_scope->identifiers.at(varName));
m_context->variableStackHeights[&var] = height + varIndex; m_context->variableStackHeights[&var] = heightAtStart + varIndex;
if (!m_allowStackOpt) if (!m_allowStackOpt)
continue; continue;
@ -207,7 +204,6 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
m_context->variableStackHeights.erase(&var); m_context->variableStackHeights.erase(&var);
m_assembly.setSourceLocation(_varDecl.location); m_assembly.setSourceLocation(_varDecl.location);
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::Instruction::POP);
--m_stackAdjustment;
} }
else else
m_variablesScheduledForDeletion.insert(&var); m_variablesScheduledForDeletion.insert(&var);
@ -223,10 +219,8 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
if (int heightDiff = variableHeightDiff(var, varName, true)) if (int heightDiff = variableHeightDiff(var, varName, true))
m_assembly.appendInstruction(evmasm::swapInstruction(heightDiff - 1)); m_assembly.appendInstruction(evmasm::swapInstruction(heightDiff - 1));
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::Instruction::POP);
--m_stackAdjustment;
} }
} }
checkStackHeight(&_varDecl);
} }
void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight) void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight)
@ -249,14 +243,12 @@ void CodeTransform::operator()(Assignment const& _assignment)
m_assembly.setSourceLocation(_assignment.location); m_assembly.setSourceLocation(_assignment.location);
generateMultiAssignment(_assignment.variableNames); generateMultiAssignment(_assignment.variableNames);
checkStackHeight(&_assignment);
} }
void CodeTransform::operator()(ExpressionStatement const& _statement) void CodeTransform::operator()(ExpressionStatement const& _statement)
{ {
m_assembly.setSourceLocation(_statement.location); m_assembly.setSourceLocation(_statement.location);
std::visit(*this, _statement.expression); std::visit(*this, _statement.expression);
checkStackHeight(&_statement);
} }
void CodeTransform::operator()(FunctionCall const& _call) void CodeTransform::operator()(FunctionCall const& _call)
@ -279,7 +271,6 @@ 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;
@ -298,9 +289,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
{ {
m_assembly.appendJumpTo(functionEntryID(_call.functionName.name, *function), function->returns.size() - function->arguments.size() - 1); m_assembly.appendJumpTo(functionEntryID(_call.functionName.name, *function), function->returns.size() - function->arguments.size() - 1);
m_assembly.appendLabel(returnLabel); m_assembly.appendLabel(returnLabel);
m_stackAdjustment--;
} }
checkStackHeight(&_call);
} }
} }
@ -334,15 +323,12 @@ void CodeTransform::operator()(Identifier const& _identifier)
"Identifier not found and no external access available." "Identifier not found and no external access available."
); );
m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_assembly); m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_assembly);
checkStackHeight(&_identifier);
} }
void CodeTransform::operator()(Literal const& _literal) void CodeTransform::operator()(Literal const& _literal)
{ {
m_assembly.setSourceLocation(_literal.location); m_assembly.setSourceLocation(_literal.location);
m_assembly.appendConstant(valueOfLiteral(_literal)); m_assembly.appendConstant(valueOfLiteral(_literal));
checkStackHeight(&_literal);
} }
void CodeTransform::operator()(If const& _if) void CodeTransform::operator()(If const& _if)
@ -355,7 +341,6 @@ void CodeTransform::operator()(If const& _if)
(*this)(_if.body); (*this)(_if.body);
m_assembly.setSourceLocation(_if.location); m_assembly.setSourceLocation(_if.location);
m_assembly.appendLabel(end); m_assembly.appendLabel(end);
checkStackHeight(&_if);
} }
void CodeTransform::operator()(Switch const& _switch) void CodeTransform::operator()(Switch const& _switch)
@ -403,7 +388,6 @@ void CodeTransform::operator()(Switch const& _switch)
m_assembly.setSourceLocation(_switch.location); m_assembly.setSourceLocation(_switch.location);
m_assembly.appendLabel(end); m_assembly.appendLabel(end);
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::Instruction::POP);
checkStackHeight(&_switch);
} }
void CodeTransform::operator()(FunctionDefinition const& _function) void CodeTransform::operator()(FunctionDefinition const& _function)
@ -412,8 +396,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
yulAssert(m_scope->identifiers.count(_function.name), ""); yulAssert(m_scope->identifiers.count(_function.name), "");
Scope::Function& function = std::get<Scope::Function>(m_scope->identifiers.at(_function.name)); Scope::Function& function = std::get<Scope::Function>(m_scope->identifiers.at(_function.name));
int const localStackAdjustment = m_evm15 ? 0 : 1; int height = m_evm15 ? 0 : 1;
int height = localStackAdjustment;
yulAssert(m_info.scopes.at(&_function.body), ""); yulAssert(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();
yulAssert(varScope, ""); yulAssert(varScope, "");
@ -433,8 +416,6 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_assembly.setStackHeight(height); m_assembly.setStackHeight(height);
m_stackAdjustment += localStackAdjustment;
for (auto const& v: _function.returnVariables) for (auto const& v: _function.returnVariables)
{ {
auto& var = std::get<Scope::Variable>(varScope->identifiers.at(v.name)); auto& var = std::get<Scope::Variable>(varScope->identifiers.at(v.name));
@ -458,7 +439,6 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_evm15, m_evm15,
m_identifierAccess, m_identifierAccess,
m_useNamedLabelsForFunctions, m_useNamedLabelsForFunctions,
localStackAdjustment,
m_context m_context
)(_function.body); )(_function.body);
} }
@ -527,8 +507,6 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_assembly.appendReturnsub(_function.returnVariables.size(), stackHeightBefore); m_assembly.appendReturnsub(_function.returnVariables.size(), stackHeightBefore);
else else
m_assembly.appendJump(stackHeightBefore - _function.returnVariables.size()); m_assembly.appendJump(stackHeightBefore - _function.returnVariables.size());
m_stackAdjustment -= localStackAdjustment;
checkStackHeight(&_function);
m_assembly.setStackHeight(stackHeightBefore); m_assembly.setStackHeight(stackHeightBefore);
} }
@ -569,7 +547,6 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
finalizeBlock(_forLoop.pre, stackStartHeight); finalizeBlock(_forLoop.pre, stackStartHeight);
m_context->forLoopStack.pop(); m_context->forLoopStack.pop();
m_scope = originalScope; m_scope = originalScope;
checkStackHeight(&_forLoop);
} }
int CodeTransform::appendPopUntil(int _targetDepth) int CodeTransform::appendPopUntil(int _targetDepth)
@ -587,8 +564,6 @@ void CodeTransform::operator()(Break const& _break)
Context::JumpInfo const& jump = m_context->forLoopStack.top().done; Context::JumpInfo const& jump = m_context->forLoopStack.top().done;
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight)); m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
checkStackHeight(&_break);
} }
void CodeTransform::operator()(Continue const& _continue) void CodeTransform::operator()(Continue const& _continue)
@ -598,8 +573,6 @@ void CodeTransform::operator()(Continue const& _continue)
Context::JumpInfo const& jump = m_context->forLoopStack.top().post; Context::JumpInfo const& jump = m_context->forLoopStack.top().post;
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight)); m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
checkStackHeight(&_continue);
} }
void CodeTransform::operator()(Leave const& _leaveStatement) void CodeTransform::operator()(Leave const& _leaveStatement)
@ -609,8 +582,6 @@ void CodeTransform::operator()(Leave const& _leaveStatement)
Context::JumpInfo const& jump = m_context->functionExitPoints.top(); Context::JumpInfo const& jump = m_context->functionExitPoints.top();
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight)); m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
checkStackHeight(&_leaveStatement);
} }
void CodeTransform::operator()(Block const& _block) void CodeTransform::operator()(Block const& _block)
@ -693,7 +664,6 @@ void CodeTransform::finalizeBlock(Block const& _block, int blockStartStackHeight
{ {
yulAssert(!m_context->variableStackHeights.count(&var), ""); yulAssert(!m_context->variableStackHeights.count(&var), "");
yulAssert(!m_context->variableReferences.count(&var), ""); yulAssert(!m_context->variableReferences.count(&var), "");
m_stackAdjustment++;
} }
else else
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::Instruction::POP);
@ -701,7 +671,6 @@ void CodeTransform::finalizeBlock(Block const& _block, int blockStartStackHeight
int deposit = m_assembly.stackHeight() - blockStartStackHeight; int deposit = m_assembly.stackHeight() - blockStartStackHeight;
yulAssert(deposit == 0, "Invalid stack height at end of block: " + to_string(deposit)); yulAssert(deposit == 0, "Invalid stack height at end of block: " + to_string(deposit));
checkStackHeight(&_block);
} }
void CodeTransform::generateMultiAssignment(vector<Identifier> const& _variableNames) void CodeTransform::generateMultiAssignment(vector<Identifier> const& _variableNames)
@ -758,16 +727,3 @@ void CodeTransform::expectDeposit(int _deposit, int _oldHeight) const
yulAssert(m_assembly.stackHeight() == _oldHeight + _deposit, "Invalid stack deposit."); yulAssert(m_assembly.stackHeight() == _oldHeight + _deposit, "Invalid stack deposit.");
} }
void CodeTransform::checkStackHeight(void const* _astElement) const
{
yulAssert(m_info.stackHeightInfo.count(_astElement), "Stack height for AST element not found.");
int stackHeightInAnalysis = m_info.stackHeightInfo.at(_astElement);
int stackHeightInCodegen = m_assembly.stackHeight() - m_stackAdjustment;
yulAssert(
stackHeightInAnalysis == stackHeightInCodegen,
"Stack height mismatch between analysis and code generation phase: Analysis: " +
to_string(stackHeightInAnalysis) +
" code gen: " +
to_string(stackHeightInCodegen)
);
}

View File

@ -134,7 +134,6 @@ public:
_evm15, _evm15,
_identifierAccess, _identifierAccess,
_useNamedLabelsForFunctions, _useNamedLabelsForFunctions,
_assembly.stackHeight(),
nullptr nullptr
) )
{ {
@ -155,7 +154,6 @@ protected:
bool _evm15, bool _evm15,
ExternalIdentifierAccess const& _identifierAccess, ExternalIdentifierAccess const& _identifierAccess,
bool _useNamedLabelsForFunctions, bool _useNamedLabelsForFunctions,
int _stackAdjustment,
std::shared_ptr<Context> _context std::shared_ptr<Context> _context
); );
@ -206,8 +204,6 @@ private:
void expectDeposit(int _deposit, int _oldHeight) const; void expectDeposit(int _deposit, int _oldHeight) const;
void checkStackHeight(void const* _astElement) const;
/// Stores the stack error in the list of errors, appends an invalid opcode /// Stores the stack error in the list of errors, appends an invalid opcode
/// and corrects the stack height to the target stack height. /// and corrects the stack height to the target stack height.
void stackError(StackTooDeepError _error, int _targetStackSize); void stackError(StackTooDeepError _error, int _targetStackSize);
@ -225,11 +221,6 @@ private:
bool const m_evm15 = false; bool const m_evm15 = false;
bool const m_useNamedLabelsForFunctions = false; bool const m_useNamedLabelsForFunctions = false;
ExternalIdentifierAccess m_identifierAccess; ExternalIdentifierAccess m_identifierAccess;
/// 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;
std::shared_ptr<Context> m_context; std::shared_ptr<Context> m_context;
/// Set of variables whose reference counter has reached zero, /// Set of variables whose reference counter has reached zero,