diff options
Diffstat (limited to 'libsolidity/inlineasm/AsmCodeGen.cpp')
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 5fa04087..d571ce0d 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -86,8 +86,12 @@ public: void operator()(Label const& _item) { if (m_state.labels.count(_item.name)) - //@TODO location and secondary location - m_state.addError(Error::Type::DeclarationError, "Label " + _item.name + " declared twice."); + //@TODO secondary location + m_state.addError( + Error::Type::DeclarationError, + "Label " + _item.name + " declared twice.", + _item.location + ); m_state.labels.insert(make_pair(_item.name, m_state.assembly.newTag())); } void operator()(assembly::Block const& _block) @@ -117,34 +121,43 @@ public: m_identifierAccess = [](assembly::Identifier const&, eth::Assembly&, CodeGenerator::IdentifierContext) { return false; }; } - void operator()(dev::solidity::assembly::Instruction const& _instruction) + void operator()(assembly::Instruction const& _instruction) { + m_state.assembly.setSourceLocation(_instruction.location); m_state.assembly.append(_instruction.instruction); } void operator()(assembly::Literal const& _literal) { + m_state.assembly.setSourceLocation(_literal.location); if (_literal.isNumber) m_state.assembly.append(u256(_literal.value)); else if (_literal.value.size() > 32) + { m_state.addError( Error::Type::TypeError, "String literal too long (" + boost::lexical_cast<string>(_literal.value.size()) + " > 32)" ); + m_state.assembly.append(u256(0)); + } else m_state.assembly.append(_literal.value); } void operator()(assembly::Identifier const& _identifier) { + m_state.assembly.setSourceLocation(_identifier.location); // First search local variables, then labels, then externals. if (int const* stackHeight = m_state.findVariable(_identifier.name)) { int heightDiff = m_state.assembly.deposit() - *stackHeight; if (heightDiff <= 0 || heightDiff > 16) - //@TODO location + { m_state.addError( Error::Type::TypeError, - "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")" + "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")", + _identifier.location ); + m_state.assembly.append(u256(0)); + } else m_state.assembly.append(solidity::dupInstruction(heightDiff)); return; @@ -152,10 +165,14 @@ public: else if (eth::AssemblyItem const* label = m_state.findLabel(_identifier.name)) m_state.assembly.append(label->pushTag()); else if (!m_identifierAccess(_identifier, m_state.assembly, CodeGenerator::IdentifierContext::RValue)) + { m_state.addError( Error::Type::DeclarationError, - "Identifier \"" + string(_identifier.name) + "\" not found or not unique" + "Identifier not found or not unique", + _identifier.location ); + m_state.assembly.append(u256(0)); + } } void operator()(FunctionalInstruction const& _instr) { @@ -163,30 +180,33 @@ public: { int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *it); - expectDeposit(1, height); + expectDeposit(1, height, locationOf(*it)); } (*this)(_instr.instruction); } void operator()(Label const& _label) { + m_state.assembly.setSourceLocation(_label.location); m_state.assembly.append(m_state.labels.at(_label.name)); } void operator()(assembly::Assignment const& _assignment) { - generateAssignment(_assignment.variableName); + m_state.assembly.setSourceLocation(_assignment.location); + generateAssignment(_assignment.variableName, _assignment.location); } void operator()(FunctionalAssignment const& _assignment) { int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *_assignment.value); - expectDeposit(1, height); - generateAssignment(_assignment.variableName); + expectDeposit(1, height, locationOf(*_assignment.value)); + m_state.assembly.setSourceLocation(_assignment.location); + generateAssignment(_assignment.variableName, _assignment.location); } void operator()(assembly::VariableDeclaration const& _varDecl) { int height = m_state.assembly.deposit(); boost::apply_visitor(*this, *_varDecl.value); - expectDeposit(1, height); + expectDeposit(1, height, locationOf(*_varDecl.value)); m_state.variables.push_back(make_pair(_varDecl.name, height)); } void operator()(assembly::Block const& _block) @@ -194,7 +214,8 @@ public: size_t numVariables = m_state.variables.size(); std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this)); // pop variables - //@TODO check height before and after + // we deliberately do not check stack height + m_state.assembly.setSourceLocation(_block.location); while (m_state.variables.size() > numVariables) { m_state.assembly.append(solidity::Instruction::POP); @@ -203,22 +224,20 @@ public: } private: - void generateAssignment(assembly::Identifier const& _variableName) + void generateAssignment(assembly::Identifier const& _variableName, SourceLocation const& _location) { if (int const* stackHeight = m_state.findVariable(_variableName.name)) { int heightDiff = m_state.assembly.deposit() - *stackHeight - 1; if (heightDiff <= 0 || heightDiff > 16) - //@TODO location m_state.addError( Error::Type::TypeError, - "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")" + "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")", + _location ); else - { m_state.assembly.append(solidity::swapInstruction(heightDiff)); - m_state.assembly.append(solidity::Instruction::POP); - } + m_state.assembly.append(solidity::Instruction::POP); return; } else if (!m_identifierAccess(_variableName, m_state.assembly, CodeGenerator::IdentifierContext::LValue)) @@ -228,16 +247,16 @@ private: ); } - void expectDeposit(int _deposit, int _oldHeight) + void expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location) { if (m_state.assembly.deposit() != _oldHeight + 1) - //@TODO location m_state.addError(Error::Type::TypeError, "Expected instruction(s) to deposit " + boost::lexical_cast<string>(_deposit) + " item(s) to the stack, but did deposit " + boost::lexical_cast<string>(m_state.assembly.deposit() - _oldHeight) + - " item(s)." + " item(s).", + _location ); } |