From 3b813ed29569dde02b965c97c9fdd60469876f66 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 19 May 2017 17:06:26 +0100 Subject: Support multiple assignment in inline assembly --- libjulia/backends/evm/EVMCodeTransform.cpp | 42 +++++++++++++++++------------- libjulia/backends/evm/EVMCodeTransform.h | 2 +- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'libjulia/backends') diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index e0b11cf3..e80903d5 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -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 const& _variableNames) { solAssert(m_scope, ""); - auto var = m_scope->lookup(_variableName.name); - if (var) - { - Scope::Variable const& _var = boost::get(*var); - if (int heightDiff = variableHeightDiff(_var, true)) - m_assembly.appendInstruction(solidity::swapInstruction(heightDiff - 1)); - m_assembly.appendInstruction(solidity::Instruction::POP); - } - else + for (auto const& variableName: _variableNames | boost::adaptors::reversed) { - 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(*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); + } } } diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index 2c0fd10c..bb2be786 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -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 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 -- cgit