From 065c3c87af0cd4f620d929a01b2902edf6c5892d Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 9 Jan 2019 14:05:03 +0100 Subject: [PATCH] libyul: changing some AST members from shared_ptr<> to unique_ptr<> * Some spaces look a little more verbose now, but that shouln't be a problem as it also should raise readability, too. * This makes some use of return-value-optimizations also. --- libyul/AsmData.h | 12 +++++------ libyul/AsmParser.cpp | 20 ++++++++--------- libyul/optimiser/ASTCopier.h | 5 +++-- libyul/optimiser/DataFlowAnalyzer.cpp | 2 ++ libyul/optimiser/ExpressionSplitter.cpp | 2 +- libyul/optimiser/FullInliner.cpp | 12 +++++------ libyul/optimiser/SSATransform.cpp | 23 ++++++++++++-------- libyul/optimiser/StructuralSimplifier.cpp | 26 ++++++++++++++++------- libyul/optimiser/SyntacticalEquality.cpp | 10 ++++----- libyul/optimiser/SyntacticalEquality.h | 2 +- libyul/optimiser/VarDeclInitializer.cpp | 4 ++-- 11 files changed, 68 insertions(+), 50 deletions(-) diff --git a/libyul/AsmData.h b/libyul/AsmData.h index 86c373a49..fd8eab38b 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -59,25 +59,25 @@ struct StackAssignment { langutil::SourceLocation location; Identifier variableN /// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy /// a single stack slot and expects a single expression on the right hand returning /// the same amount of items as the number of variables. -struct Assignment { langutil::SourceLocation location; std::vector variableNames; std::shared_ptr value; }; +struct Assignment { langutil::SourceLocation location; std::vector variableNames; std::unique_ptr value; }; /// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))" struct FunctionalInstruction { langutil::SourceLocation location; dev::solidity::Instruction instruction; std::vector arguments; }; struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector arguments; }; /// Statement that contains only a single expression struct ExpressionStatement { langutil::SourceLocation location; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted -struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::shared_ptr value; }; +struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::unique_ptr value; }; /// Block that creates a scope (frees declared stack variables) struct Block { langutil::SourceLocation location; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") struct FunctionDefinition { langutil::SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. -struct If { langutil::SourceLocation location; std::shared_ptr condition; Block body; }; +struct If { langutil::SourceLocation location; std::unique_ptr condition; Block body; }; /// Switch case or default case -struct Case { langutil::SourceLocation location; std::shared_ptr value; Block body; }; +struct Case { langutil::SourceLocation location; std::unique_ptr value; Block body; }; /// Switch statement -struct Switch { langutil::SourceLocation location; std::shared_ptr expression; std::vector cases; }; -struct ForLoop { langutil::SourceLocation location; Block pre; std::shared_ptr condition; Block post; Block body; }; +struct Switch { langutil::SourceLocation location; std::unique_ptr expression; std::vector cases; }; +struct ForLoop { langutil::SourceLocation location; Block pre; std::unique_ptr condition; Block post; Block body; }; struct LocationExtractor: boost::static_visitor { diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index f3ca6cd08..217c838a7 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -81,15 +81,15 @@ Statement Parser::parseStatement() { If _if = createWithLocation(); m_scanner->next(); - _if.condition = make_shared(parseExpression()); + _if.condition = make_unique(parseExpression()); _if.body = parseBlock(); - return _if; + return Statement{move(_if)}; } case Token::Switch: { Switch _switch = createWithLocation(); m_scanner->next(); - _switch.expression = make_shared(parseExpression()); + _switch.expression = make_unique(parseExpression()); while (m_scanner->currentToken() == Token::Case) _switch.cases.emplace_back(parseCase()); if (m_scanner->currentToken() == Token::Default) @@ -101,7 +101,7 @@ Statement Parser::parseStatement() if (_switch.cases.empty()) fatalParserError("Switch statement without any cases."); _switch.location.end = _switch.cases.back().body.location.end; - return _switch; + return Statement{move(_switch)}; } case Token::For: return parseForLoop(); @@ -120,7 +120,7 @@ Statement Parser::parseStatement() fatalParserError("Identifier expected, got instruction name."); assignment.location.end = endPosition(); expectToken(Token::Identifier); - return assignment; + return Statement{move(assignment)}; } default: break; @@ -163,7 +163,7 @@ Statement Parser::parseStatement() assignment.value.reset(new Expression(parseExpression())); assignment.location.end = locationOf(*assignment.value).end; - return assignment; + return Statement{std::move(assignment)}; } case Token::Colon: { @@ -184,7 +184,7 @@ Statement Parser::parseStatement() assignment.variableNames.emplace_back(identifier); assignment.value.reset(new Expression(parseExpression())); assignment.location.end = locationOf(*assignment.value).end; - return assignment; + return Statement{std::move(assignment)}; } else { @@ -230,7 +230,7 @@ Case Parser::parseCase() ElementaryOperation literal = parseElementaryOperation(); if (literal.type() != typeid(Literal)) fatalParserError("Literal expected."); - _case.value = make_shared(boost::get(std::move(literal))); + _case.value = make_unique(boost::get(std::move(literal))); } else fatalParserError("Case or default case expected."); @@ -245,7 +245,7 @@ ForLoop Parser::parseForLoop() ForLoop forLoop = createWithLocation(); expectToken(Token::For); forLoop.pre = parseBlock(); - forLoop.condition = make_shared(parseExpression()); + forLoop.condition = make_unique(parseExpression()); forLoop.post = parseBlock(); forLoop.body = parseBlock(); forLoop.location.end = forLoop.body.location.end; @@ -443,7 +443,7 @@ VariableDeclaration Parser::parseVariableDeclaration() { expectToken(Token::Colon); expectToken(Token::Assign); - varDecl.value.reset(new Expression(parseExpression())); + varDecl.value = make_unique(parseExpression()); varDecl.location.end = locationOf(*varDecl.value).end; } else diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 4d2f18aea..7e5e9c868 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -93,10 +93,11 @@ protected: std::vector translateVector(std::vector const& _values); template - std::shared_ptr translate(std::shared_ptr const& _v) + std::unique_ptr translate(std::unique_ptr const& _v) { - return _v ? std::make_shared(translate(*_v)) : nullptr; + return _v ? std::make_unique(translate(*_v)) : nullptr; } + Block translate(Block const& _block); Case translate(Case const& _case); Identifier translate(Identifier const& _identifier); diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index e97bcdc4c..b4f2d1f96 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -51,8 +51,10 @@ void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl) for (auto const& var: _varDecl.variables) names.emplace(var.name); m_variableScopes.back().variables += names; + if (_varDecl.value) visit(*_varDecl.value); + handleAssignment(names, _varDecl.value.get()); } diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 334e33f45..2f80fc32c 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -106,7 +106,7 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) m_statementsToPrefix.emplace_back(VariableDeclaration{ location, {{TypedName{location, var, {}}}}, - make_shared(std::move(_expr)) + make_unique(std::move(_expr)) }); _expr = Identifier{location, var}; } diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index dd969fafc..ca6162ec6 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -181,9 +181,9 @@ vector InlineModifier::performInline(Statement& _statement, FunctionC variableReplacements[_existingVariable.name] = newName; VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}}; if (_value) - varDecl.value = make_shared(std::move(*_value)); + varDecl.value = make_unique(std::move(*_value)); else - varDecl.value = make_shared(zero); + varDecl.value = make_unique(zero); newStatements.emplace_back(std::move(varDecl)); }; @@ -202,7 +202,7 @@ vector InlineModifier::performInline(Statement& _statement, FunctionC newStatements.emplace_back(Assignment{ _assignment.location, {_assignment.variableNames[i]}, - make_shared(Identifier{ + make_unique(Identifier{ _assignment.location, variableReplacements.at(function->returnVariables[i].name) }) @@ -214,7 +214,7 @@ vector InlineModifier::performInline(Statement& _statement, FunctionC newStatements.emplace_back(VariableDeclaration{ _varDecl.location, {std::move(_varDecl.variables[i])}, - make_shared(Identifier{ + make_unique(Identifier{ _varDecl.location, variableReplacements.at(function->returnVariables[i].name) }) @@ -232,10 +232,10 @@ Statement BodyCopier::operator()(VariableDeclaration const& _varDecl) return ASTCopier::operator()(_varDecl); } -Statement BodyCopier::operator()(FunctionDefinition const& _funDef) +Statement BodyCopier::operator()(FunctionDefinition const&) { assertThrow(false, OptimizerException, "Function hoisting has to be done before function inlining."); - return _funDef; + return {}; } YulString BodyCopier::translateIdentifier(YulString _name) diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 928c08597..33c875b5d 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -66,12 +66,13 @@ void SSATransform::operator()(Block& _block) // Creates a new variable (and returns its declaration) with value _value // and replaces _value by a reference to that new variable. - auto replaceByNew = [&](SourceLocation _loc, YulString _varName, YulString _type, shared_ptr& _value) -> VariableDeclaration + + auto replaceByNew = [&](SourceLocation _loc, YulString _varName, YulString _type, unique_ptr& _value) -> VariableDeclaration { YulString newName = m_nameDispenser.newName(_varName); m_currentVariableValues[_varName] = newName; variablesToClearAtEnd.emplace(_varName); - shared_ptr v = make_shared(Identifier{_loc, newName}); + unique_ptr v = make_unique(Identifier{_loc, newName}); _value.swap(v); return VariableDeclaration{_loc, {TypedName{_loc, std::move(newName), std::move(_type)}}, std::move(v)}; }; @@ -87,14 +88,16 @@ void SSATransform::operator()(Block& _block) visit(*varDecl.value); if (varDecl.variables.size() != 1 || !m_variablesToReplace.count(varDecl.variables.front().name)) return {}; - // Replace "let a := v" by "let a_1 := v let a := v" - VariableDeclaration newVarDecl = replaceByNew( + vector v; + // Replace "let a := v" by "let a_1 := v let a := a_1" + v.emplace_back(replaceByNew( varDecl.location, varDecl.variables.front().name, varDecl.variables.front().type, varDecl.value - ); - return vector{std::move(newVarDecl), std::move(varDecl)}; + )); + v.emplace_back(move(varDecl)); + return v; } else if (_s.type() == typeid(Assignment)) { @@ -103,14 +106,16 @@ void SSATransform::operator()(Block& _block) if (assignment.variableNames.size() != 1) return {}; assertThrow(m_variablesToReplace.count(assignment.variableNames.front().name), OptimizerException, ""); + vector v; // Replace "a := v" by "let a_1 := v a := v" - VariableDeclaration newVarDecl = replaceByNew( + v.emplace_back(replaceByNew( assignment.location, assignment.variableNames.front().name, {}, // TODO determine type assignment.value - ); - return vector{std::move(newVarDecl), std::move(assignment)}; + )); + v.emplace_back(move(assignment)); + return v; } else visit(_s); diff --git a/libyul/optimiser/StructuralSimplifier.cpp b/libyul/optimiser/StructuralSimplifier.cpp index 8d7dcd57c..727775cb3 100644 --- a/libyul/optimiser/StructuralSimplifier.cpp +++ b/libyul/optimiser/StructuralSimplifier.cpp @@ -51,7 +51,11 @@ void StructuralSimplifier::simplify(std::vector& _statements) GenericFallbackReturnsVisitor const visitor( [&](If& _ifStmt) -> OptionalStatements { if (_ifStmt.body.statements.empty()) - return {{makePopExpressionStatement(_ifStmt.location, std::move(*_ifStmt.condition))}}; + { + OptionalStatements s = vector{}; + s->emplace_back(makePopExpressionStatement(_ifStmt.location, std::move(*_ifStmt.condition))); + return s; + } if (expressionAlwaysTrue(*_ifStmt.condition)) return {std::move(_ifStmt.body.statements)}; else if (expressionAlwaysFalse(*_ifStmt.condition)) @@ -64,18 +68,24 @@ void StructuralSimplifier::simplify(std::vector& _statements) auto& switchCase = _switchStmt.cases.front(); auto loc = locationOf(*_switchStmt.expression); if (switchCase.value) - return {{If{ + { + OptionalStatements s = vector{}; + s->emplace_back(If{ std::move(_switchStmt.location), - make_shared(FunctionalInstruction{ + make_unique(FunctionalInstruction{ std::move(loc), solidity::Instruction::EQ, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} - }), std::move(switchCase.body)}}}; + }), std::move(switchCase.body)}); + return s; + } else - return {{ - makePopExpressionStatement(loc, std::move(*_switchStmt.expression)), - std::move(switchCase.body) - }}; + { + OptionalStatements s = vector{}; + s->emplace_back(makePopExpressionStatement(loc, std::move(*_switchStmt.expression))); + s->emplace_back(std::move(switchCase.body)); + return s; + } } else return {}; diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index ba8cc7934..53f0b029e 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -100,7 +100,7 @@ bool SyntacticallyEqual::statementEqual(Assignment const& _lhs, Assignment const bool SyntacticallyEqual::statementEqual(VariableDeclaration const& _lhs, VariableDeclaration const& _rhs) { // first visit expression, then variable declarations - if (!compareSharedPtr(_lhs.value, _rhs.value)) + if (!compareUniquePtr(_lhs.value, _rhs.value)) return false; return containerEqual(_lhs.variables, _rhs.variables, [this](TypedName const& _lhsVarName, TypedName const& _rhsVarName) -> bool { return this->visitDeclaration(_lhsVarName, _rhsVarName); @@ -123,7 +123,7 @@ bool SyntacticallyEqual::statementEqual(FunctionDefinition const& _lhs, Function bool SyntacticallyEqual::statementEqual(If const& _lhs, If const& _rhs) { return - compareSharedPtr(_lhs.condition, _rhs.condition) && + compareUniquePtr(_lhs.condition, _rhs.condition) && statementEqual(_lhs.body, _rhs.body); } @@ -139,7 +139,7 @@ bool SyntacticallyEqual::statementEqual(Switch const& _lhs, Switch const& _rhs) for (auto const& rhsCase: _rhs.cases) rhsCases.insert(&rhsCase); return - compareSharedPtr(_lhs.expression, _rhs.expression) && + compareUniquePtr(_lhs.expression, _rhs.expression) && containerEqual(lhsCases, rhsCases, [this](Case const* _lhsCase, Case const* _rhsCase) -> bool { return this->switchCaseEqual(*_lhsCase, *_rhsCase); }); @@ -149,7 +149,7 @@ bool SyntacticallyEqual::statementEqual(Switch const& _lhs, Switch const& _rhs) bool SyntacticallyEqual::switchCaseEqual(Case const& _lhs, Case const& _rhs) { return - compareSharedPtr(_lhs.value, _rhs.value) && + compareUniquePtr(_lhs.value, _rhs.value) && statementEqual(_lhs.body, _rhs.body); } @@ -157,7 +157,7 @@ bool SyntacticallyEqual::statementEqual(ForLoop const& _lhs, ForLoop const& _rhs { return statementEqual(_lhs.pre, _rhs.pre) && - compareSharedPtr(_lhs.condition, _rhs.condition) && + compareUniquePtr(_lhs.condition, _rhs.condition) && statementEqual(_lhs.body, _rhs.body) && statementEqual(_lhs.post, _rhs.post); } diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index d4630d957..af240717b 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -76,7 +76,7 @@ private: } template - bool compareSharedPtr(std::shared_ptr const& _lhs, std::shared_ptr const& _rhs) + bool compareUniquePtr(std::unique_ptr const& _lhs, std::unique_ptr const& _rhs) { return (_lhs == _rhs) || (_lhs && _rhs && (this->*CompareMember)(*_lhs, *_rhs)); } diff --git a/libyul/optimiser/VarDeclInitializer.cpp b/libyul/optimiser/VarDeclInitializer.cpp index 4a26757f2..7009cc9b2 100644 --- a/libyul/optimiser/VarDeclInitializer.cpp +++ b/libyul/optimiser/VarDeclInitializer.cpp @@ -39,7 +39,7 @@ void VarDeclInitializer::operator()(Block& _block) return {}; else if (_varDecl.variables.size() == 1) { - _varDecl.value = make_shared(zero); + _varDecl.value = make_unique(zero); return {}; } else @@ -47,7 +47,7 @@ void VarDeclInitializer::operator()(Block& _block) OptionalStatements ret{vector{}}; langutil::SourceLocation loc{std::move(_varDecl.location)}; for (auto& var: _varDecl.variables) - ret->push_back(VariableDeclaration{loc, {std::move(var)}, make_shared(zero)}); + ret->push_back(VariableDeclaration{loc, {std::move(var)}, make_unique(zero)}); return ret; } }