diff options
Diffstat (limited to 'libsolidity/inlineasm')
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 26 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 14 |
2 files changed, 35 insertions, 5 deletions
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 53d19b0a..5d920cb7 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -23,6 +23,7 @@ #include <libsolidity/inlineasm/AsmCodeGen.h> #include <memory> #include <functional> +#include <libdevcore/CommonIO.h> #include <libevmasm/Assembly.h> #include <libevmasm/SourceLocation.h> #include <libevmasm/Instruction.h> @@ -213,10 +214,31 @@ public: void operator()(assembly::Block const& _block) { size_t numVariables = m_state.variables.size(); + int deposit = m_state.assembly.deposit(); std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this)); - // pop variables - // we deliberately do not check stack height + deposit = m_state.assembly.deposit() - deposit; + m_state.assembly.setSourceLocation(_block.location); + + // issue warnings for stack height discrepancies + if (deposit < 0) + { + m_state.addError( + Error::Type::Warning, + "Inline assembly block is not balanced. It takes " + toString(-deposit) + " item(s) from the stack.", + _block.location + ); + } + else if (deposit > 0) + { + m_state.addError( + Error::Type::Warning, + "Inline assembly block is not balanced. It leaves " + toString(deposit) + " item(s) on the stack.", + _block.location + ); + } + + // pop variables while (m_state.variables.size() > numVariables) { m_state.assembly.append(solidity::Instruction::POP); diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 5c7163ee..8d2c2ed4 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -95,7 +95,9 @@ assembly::Statement Parser::parseStatement() fatalParserError("Label name / variable name must precede \":\"."); assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement); m_scanner->next(); - if (m_scanner->currentToken() == Token::Assign) + // identifier:=: should be parsed as identifier: =: (i.e. a label), + // while identifier:= (being followed by a non-colon) as identifier := (assignment). + if (m_scanner->currentToken() == Token::Assign && m_scanner->peekNextToken() != Token::Colon) { // functional assignment FunctionalAssignment funAss = createWithLocation<FunctionalAssignment>(identifier.location); @@ -133,6 +135,7 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) // Allowed instructions, lowercase names. static map<string, dev::solidity::Instruction> s_instructions; if (s_instructions.empty()) + { for (auto const& instruction: solidity::c_instructions) { if ( @@ -141,24 +144,29 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) ) continue; string name = instruction.first; - if (instruction.second == solidity::Instruction::SUICIDE) - name = "selfdestruct"; transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); }); s_instructions[name] = instruction.second; } + // add alias for selfdestruct + s_instructions["selfdestruct"] = solidity::Instruction::SUICIDE; + } + Statement ret; switch (m_scanner->currentToken()) { case Token::Identifier: case Token::Return: case Token::Byte: + case Token::Address: { string literal; if (m_scanner->currentToken() == Token::Return) literal = "return"; else if (m_scanner->currentToken() == Token::Byte) literal = "byte"; + else if (m_scanner->currentToken() == Token::Address) + literal = "address"; else literal = m_scanner->currentLiteral(); // first search the set of instructions. |