diff options
author | chriseth <chris@ethereum.org> | 2017-11-27 22:02:46 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-27 22:02:46 +0800 |
commit | a1f59cbb17d29ca5f92fa1cc20d17f47026ade5a (patch) | |
tree | d17e5ab7a2c9cd5ffacba728851e6c127182fbe0 /libsolidity | |
parent | a7136dbc16ba7e0cf8a7d6097d50cc40c1248914 (diff) | |
parent | 1d91b65b726d4757b866124d75834f28a9bc9eb9 (diff) | |
download | dexon-solidity-a1f59cbb17d29ca5f92fa1cc20d17f47026ade5a.tar.gz dexon-solidity-a1f59cbb17d29ca5f92fa1cc20d17f47026ade5a.tar.zst dexon-solidity-a1f59cbb17d29ca5f92fa1cc20d17f47026ade5a.zip |
Merge pull request #3220 from ethereum/IuliaIf
If statement for Iulia / Inline Assembly
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/ViewPureChecker.cpp | 5 | ||||
-rw-r--r-- | libsolidity/codegen/ABIFunctions.cpp | 6 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 16 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 1 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmData.h | 2 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmDataForward.h | 3 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 12 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmPrinter.cpp | 5 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmPrinter.h | 1 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScopeFiller.cpp | 5 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScopeFiller.h | 1 |
11 files changed, 52 insertions, 5 deletions
diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 7f28c7d2..7e41fc16 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -72,6 +72,11 @@ public: for (auto const& arg: _funCall.arguments) boost::apply_visitor(*this, arg); } + void operator()(assembly::If const& _if) + { + boost::apply_visitor(*this, *_if.condition); + (*this)(_if.body); + } void operator()(assembly::Switch const& _switch) { boost::apply_visitor(*this, *_switch.expression); diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index d2cbac99..bb39cbbb 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -168,7 +168,7 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) { size_t members = dynamic_cast<EnumType const&>(_type).numberOfMembers(); solAssert(members > 0, "empty enum should have caused a parser error."); - Whiskers w("switch lt(value, <members>) case 0 { <failure> } cleaned := value"); + Whiskers w("if iszero(lt(value, <members>)) { <failure> } cleaned := value"); w("members", to_string(members)); if (_revertOnFailure) w("failure", "revert(0, 0)"); @@ -988,8 +988,8 @@ string ABIFunctions::copyToMemoryFunction(bool _fromCalldata) { mstore(add(dst, i), mload(add(src, i))) } - switch eq(i, length) - case 0 { + if gt(i, length) + { // clear end mstore(add(dst, length), 0) } diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index e5bdc90f..2804ddfc 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -286,6 +286,22 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall) return success; } +bool AsmAnalyzer::operator()(If const& _if) +{ + bool success = true; + + if (!expectExpression(*_if.condition)) + success = false; + m_stackHeight--; + + if (!(*this)(_if.body)) + success = false; + + m_info.stackHeightInfo[&_if] = m_stackHeight; + + return success; +} + bool AsmAnalyzer::operator()(Switch const& _switch) { bool success = true; diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 9b2a8f9c..e484b876 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -70,6 +70,7 @@ public: bool operator()(assembly::VariableDeclaration const& _variableDeclaration); bool operator()(assembly::FunctionDefinition const& _functionDefinition); bool operator()(assembly::FunctionCall const& _functionCall); + bool operator()(assembly::If const& _if); bool operator()(assembly::Switch const& _switch); bool operator()(assembly::ForLoop const& _forLoop); bool operator()(assembly::Block const& _block); diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index b0dd85ca..a792a1b8 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -68,6 +68,8 @@ struct VariableDeclaration { SourceLocation location; TypedNameList variables; s struct Block { SourceLocation location; std::vector<Statement> statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") struct FunctionDefinition { SourceLocation location; std::string name; TypedNameList arguments; TypedNameList returns; Block body; }; +/// Conditional execution without "else" part. +struct If { SourceLocation location; std::shared_ptr<Statement> condition; Block body; }; /// Switch case or default case struct Case { SourceLocation location; std::shared_ptr<Literal> value; Block body; }; /// Switch statement diff --git a/libsolidity/inlineasm/AsmDataForward.h b/libsolidity/inlineasm/AsmDataForward.h index 4ead7ff5..d627b41a 100644 --- a/libsolidity/inlineasm/AsmDataForward.h +++ b/libsolidity/inlineasm/AsmDataForward.h @@ -41,11 +41,12 @@ struct VariableDeclaration; struct FunctionalInstruction; struct FunctionDefinition; struct FunctionCall; +struct If; struct Switch; struct ForLoop; struct Block; -using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, ForLoop, Block>; +using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, If, Switch, ForLoop, Block>; } } diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 1f4df75b..8f171005 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -73,13 +73,23 @@ assembly::Statement Parser::parseStatement() return parseFunctionDefinition(); case Token::LBrace: return parseBlock(); + case Token::If: + { + assembly::If _if = createWithLocation<assembly::If>(); + m_scanner->next(); + _if.condition = make_shared<Statement>(parseExpression()); + if (_if.condition->type() == typeid(assembly::Instruction)) + fatalParserError("Instructions are not supported as conditions for if - try to append \"()\"."); + _if.body = parseBlock(); + return _if; + } case Token::Switch: { assembly::Switch _switch = createWithLocation<assembly::Switch>(); m_scanner->next(); _switch.expression = make_shared<Statement>(parseExpression()); if (_switch.expression->type() == typeid(assembly::Instruction)) - fatalParserError("Instructions are not supported as expressions for switch."); + fatalParserError("Instructions are not supported as expressions for switch - try to append \"()\"."); while (m_scanner->currentToken() == Token::Case) _switch.cases.emplace_back(parseCase()); if (m_scanner->currentToken() == Token::Default) diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp index a5272808..0f183244 100644 --- a/libsolidity/inlineasm/AsmPrinter.cpp +++ b/libsolidity/inlineasm/AsmPrinter.cpp @@ -174,6 +174,11 @@ string AsmPrinter::operator()(assembly::FunctionCall const& _functionCall) ")"; } +string AsmPrinter::operator()(If const& _if) +{ + return "if " + boost::apply_visitor(*this, *_if.condition) + "\n" + (*this)(_if.body); +} + string AsmPrinter::operator()(Switch const& _switch) { string out = "switch " + boost::apply_visitor(*this, *_switch.expression); diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libsolidity/inlineasm/AsmPrinter.h index 66520632..eadf81d9 100644 --- a/libsolidity/inlineasm/AsmPrinter.h +++ b/libsolidity/inlineasm/AsmPrinter.h @@ -48,6 +48,7 @@ public: std::string operator()(assembly::VariableDeclaration const& _variableDeclaration); std::string operator()(assembly::FunctionDefinition const& _functionDefinition); std::string operator()(assembly::FunctionCall const& _functionCall); + std::string operator()(assembly::If const& _if); std::string operator()(assembly::Switch const& _switch); std::string operator()(assembly::ForLoop const& _forLoop); std::string operator()(assembly::Block const& _block); diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index b70ae9ac..77ae9102 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -104,6 +104,11 @@ bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef) return success; } +bool ScopeFiller::operator()(If const& _if) +{ + return (*this)(_if.body); +} + bool ScopeFiller::operator()(Switch const& _switch) { bool success = true; diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h index 80c03d2c..ed28abbf 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.h +++ b/libsolidity/inlineasm/AsmScopeFiller.h @@ -59,6 +59,7 @@ public: bool operator()(assembly::VariableDeclaration const& _variableDeclaration); bool operator()(assembly::FunctionDefinition const& _functionDefinition); bool operator()(assembly::FunctionCall const&) { return true; } + bool operator()(assembly::If const& _if); bool operator()(assembly::Switch const& _switch); bool operator()(assembly::ForLoop const& _forLoop); bool operator()(assembly::Block const& _block); |