Support multiple assignment in inline assembly

This commit is contained in:
Alex Beregszaszi
2017-09-20 11:16:23 +02:00
committed by chriseth
parent c0b3e5b078
commit 3b813ed295
10 changed files with 145 additions and 25 deletions
+24 -18
View File
@@ -60,16 +60,19 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
void CodeTransform::operator()(Assignment const& _assignment)
{
visitExpression(*_assignment.value);
int height = m_assembly.stackHeight();
boost::apply_visitor(*this, *_assignment.value);
expectDeposit(_assignment.variableNames.size(), height);
m_assembly.setSourceLocation(_assignment.location);
generateAssignment(_assignment.variableName);
generateAssignment(_assignment.variableNames);
checkStackHeight(&_assignment);
}
void CodeTransform::operator()(StackAssignment const& _assignment)
{
m_assembly.setSourceLocation(_assignment.location);
generateAssignment(_assignment.variableName);
generateAssignment({_assignment.variableName});
checkStackHeight(&_assignment);
}
@@ -469,24 +472,27 @@ void CodeTransform::finalizeBlock(Block const& _block, int blockStartStackHeight
checkStackHeight(&_block);
}
void CodeTransform::generateAssignment(Identifier const& _variableName)
void CodeTransform::generateAssignment(vector<Identifier> const& _variableNames)
{
solAssert(m_scope, "");
auto var = m_scope->lookup(_variableName.name);
if (var)
for (auto const& variableName: _variableNames | boost::adaptors::reversed)
{
Scope::Variable const& _var = boost::get<Scope::Variable>(*var);
if (int heightDiff = variableHeightDiff(_var, true))
m_assembly.appendInstruction(solidity::swapInstruction(heightDiff - 1));
m_assembly.appendInstruction(solidity::Instruction::POP);
}
else
{
solAssert(
m_identifierAccess.generateCode,
"Identifier not found and no external access available."
);
m_identifierAccess.generateCode(_variableName, IdentifierContext::LValue, m_assembly);
auto var = m_scope->lookup(variableName.name);
if (var)
{
Scope::Variable const& _var = boost::get<Scope::Variable>(*var);
if (int heightDiff = variableHeightDiff(_var, true))
m_assembly.appendInstruction(solidity::swapInstruction(heightDiff - 1));
m_assembly.appendInstruction(solidity::Instruction::POP);
}
else
{
solAssert(
m_identifierAccess.generateCode,
"Identifier not found and no external access available."
);
m_identifierAccess.generateCode(variableName, IdentifierContext::LValue, m_assembly);
}
}
}
+1 -1
View File
@@ -124,7 +124,7 @@ private:
/// to @a _blackStartStackHeight.
void finalizeBlock(solidity::assembly::Block const& _block, int _blockStartStackHeight);
void generateAssignment(solidity::assembly::Identifier const& _variableName);
void generateAssignment(std::vector<solidity::assembly::Identifier> const& _variableNames);
/// Determines the stack height difference to the given variables. Throws
/// if it is not yet in scope or the height difference is too large. Returns