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.
This commit is contained in:
Christian Parpart 2019-01-09 14:05:03 +01:00
parent 778b14de26
commit 065c3c87af
No known key found for this signature in database
GPG Key ID: 19BC8DD20312C929
11 changed files with 68 additions and 50 deletions

View File

@ -59,25 +59,25 @@ struct StackAssignment { langutil::SourceLocation location; Identifier variableN
/// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy /// 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 /// a single stack slot and expects a single expression on the right hand returning
/// the same amount of items as the number of variables. /// the same amount of items as the number of variables.
struct Assignment { langutil::SourceLocation location; std::vector<Identifier> variableNames; std::shared_ptr<Expression> value; }; struct Assignment { langutil::SourceLocation location; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
/// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))" /// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))"
struct FunctionalInstruction { langutil::SourceLocation location; dev::solidity::Instruction instruction; std::vector<Expression> arguments; }; struct FunctionalInstruction { langutil::SourceLocation location; dev::solidity::Instruction instruction; std::vector<Expression> arguments; };
struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector<Expression> arguments; }; struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector<Expression> arguments; };
/// Statement that contains only a single expression /// Statement that contains only a single expression
struct ExpressionStatement { langutil::SourceLocation location; Expression expression; }; struct ExpressionStatement { langutil::SourceLocation location; Expression expression; };
/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::shared_ptr<Expression> value; }; struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::unique_ptr<Expression> value; };
/// Block that creates a scope (frees declared stack variables) /// Block that creates a scope (frees declared stack variables)
struct Block { langutil::SourceLocation location; std::vector<Statement> statements; }; struct Block { langutil::SourceLocation location; std::vector<Statement> statements; };
/// Function definition ("function f(a, b) -> (d, e) { ... }") /// Function definition ("function f(a, b) -> (d, e) { ... }")
struct FunctionDefinition { langutil::SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; struct FunctionDefinition { langutil::SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
/// Conditional execution without "else" part. /// Conditional execution without "else" part.
struct If { langutil::SourceLocation location; std::shared_ptr<Expression> condition; Block body; }; struct If { langutil::SourceLocation location; std::unique_ptr<Expression> condition; Block body; };
/// Switch case or default case /// Switch case or default case
struct Case { langutil::SourceLocation location; std::shared_ptr<Literal> value; Block body; }; struct Case { langutil::SourceLocation location; std::unique_ptr<Literal> value; Block body; };
/// Switch statement /// Switch statement
struct Switch { langutil::SourceLocation location; std::shared_ptr<Expression> expression; std::vector<Case> cases; }; struct Switch { langutil::SourceLocation location; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
struct ForLoop { langutil::SourceLocation location; Block pre; std::shared_ptr<Expression> condition; Block post; Block body; }; struct ForLoop { langutil::SourceLocation location; Block pre; std::unique_ptr<Expression> condition; Block post; Block body; };
struct LocationExtractor: boost::static_visitor<langutil::SourceLocation> struct LocationExtractor: boost::static_visitor<langutil::SourceLocation>
{ {

View File

@ -81,15 +81,15 @@ Statement Parser::parseStatement()
{ {
If _if = createWithLocation<If>(); If _if = createWithLocation<If>();
m_scanner->next(); m_scanner->next();
_if.condition = make_shared<Expression>(parseExpression()); _if.condition = make_unique<Expression>(parseExpression());
_if.body = parseBlock(); _if.body = parseBlock();
return _if; return Statement{move(_if)};
} }
case Token::Switch: case Token::Switch:
{ {
Switch _switch = createWithLocation<Switch>(); Switch _switch = createWithLocation<Switch>();
m_scanner->next(); m_scanner->next();
_switch.expression = make_shared<Expression>(parseExpression()); _switch.expression = make_unique<Expression>(parseExpression());
while (m_scanner->currentToken() == Token::Case) while (m_scanner->currentToken() == Token::Case)
_switch.cases.emplace_back(parseCase()); _switch.cases.emplace_back(parseCase());
if (m_scanner->currentToken() == Token::Default) if (m_scanner->currentToken() == Token::Default)
@ -101,7 +101,7 @@ Statement Parser::parseStatement()
if (_switch.cases.empty()) if (_switch.cases.empty())
fatalParserError("Switch statement without any cases."); fatalParserError("Switch statement without any cases.");
_switch.location.end = _switch.cases.back().body.location.end; _switch.location.end = _switch.cases.back().body.location.end;
return _switch; return Statement{move(_switch)};
} }
case Token::For: case Token::For:
return parseForLoop(); return parseForLoop();
@ -120,7 +120,7 @@ Statement Parser::parseStatement()
fatalParserError("Identifier expected, got instruction name."); fatalParserError("Identifier expected, got instruction name.");
assignment.location.end = endPosition(); assignment.location.end = endPosition();
expectToken(Token::Identifier); expectToken(Token::Identifier);
return assignment; return Statement{move(assignment)};
} }
default: default:
break; break;
@ -163,7 +163,7 @@ Statement Parser::parseStatement()
assignment.value.reset(new Expression(parseExpression())); assignment.value.reset(new Expression(parseExpression()));
assignment.location.end = locationOf(*assignment.value).end; assignment.location.end = locationOf(*assignment.value).end;
return assignment; return Statement{std::move(assignment)};
} }
case Token::Colon: case Token::Colon:
{ {
@ -184,7 +184,7 @@ Statement Parser::parseStatement()
assignment.variableNames.emplace_back(identifier); assignment.variableNames.emplace_back(identifier);
assignment.value.reset(new Expression(parseExpression())); assignment.value.reset(new Expression(parseExpression()));
assignment.location.end = locationOf(*assignment.value).end; assignment.location.end = locationOf(*assignment.value).end;
return assignment; return Statement{std::move(assignment)};
} }
else else
{ {
@ -230,7 +230,7 @@ Case Parser::parseCase()
ElementaryOperation literal = parseElementaryOperation(); ElementaryOperation literal = parseElementaryOperation();
if (literal.type() != typeid(Literal)) if (literal.type() != typeid(Literal))
fatalParserError("Literal expected."); fatalParserError("Literal expected.");
_case.value = make_shared<Literal>(boost::get<Literal>(std::move(literal))); _case.value = make_unique<Literal>(boost::get<Literal>(std::move(literal)));
} }
else else
fatalParserError("Case or default case expected."); fatalParserError("Case or default case expected.");
@ -245,7 +245,7 @@ ForLoop Parser::parseForLoop()
ForLoop forLoop = createWithLocation<ForLoop>(); ForLoop forLoop = createWithLocation<ForLoop>();
expectToken(Token::For); expectToken(Token::For);
forLoop.pre = parseBlock(); forLoop.pre = parseBlock();
forLoop.condition = make_shared<Expression>(parseExpression()); forLoop.condition = make_unique<Expression>(parseExpression());
forLoop.post = parseBlock(); forLoop.post = parseBlock();
forLoop.body = parseBlock(); forLoop.body = parseBlock();
forLoop.location.end = forLoop.body.location.end; forLoop.location.end = forLoop.body.location.end;
@ -443,7 +443,7 @@ VariableDeclaration Parser::parseVariableDeclaration()
{ {
expectToken(Token::Colon); expectToken(Token::Colon);
expectToken(Token::Assign); expectToken(Token::Assign);
varDecl.value.reset(new Expression(parseExpression())); varDecl.value = make_unique<Expression>(parseExpression());
varDecl.location.end = locationOf(*varDecl.value).end; varDecl.location.end = locationOf(*varDecl.value).end;
} }
else else

View File

@ -93,10 +93,11 @@ protected:
std::vector<T> translateVector(std::vector<T> const& _values); std::vector<T> translateVector(std::vector<T> const& _values);
template <typename T> template <typename T>
std::shared_ptr<T> translate(std::shared_ptr<T> const& _v) std::unique_ptr<T> translate(std::unique_ptr<T> const& _v)
{ {
return _v ? std::make_shared<T>(translate(*_v)) : nullptr; return _v ? std::make_unique<T>(translate(*_v)) : nullptr;
} }
Block translate(Block const& _block); Block translate(Block const& _block);
Case translate(Case const& _case); Case translate(Case const& _case);
Identifier translate(Identifier const& _identifier); Identifier translate(Identifier const& _identifier);

View File

@ -51,8 +51,10 @@ void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl)
for (auto const& var: _varDecl.variables) for (auto const& var: _varDecl.variables)
names.emplace(var.name); names.emplace(var.name);
m_variableScopes.back().variables += names; m_variableScopes.back().variables += names;
if (_varDecl.value) if (_varDecl.value)
visit(*_varDecl.value); visit(*_varDecl.value);
handleAssignment(names, _varDecl.value.get()); handleAssignment(names, _varDecl.value.get());
} }

View File

@ -106,7 +106,7 @@ void ExpressionSplitter::outlineExpression(Expression& _expr)
m_statementsToPrefix.emplace_back(VariableDeclaration{ m_statementsToPrefix.emplace_back(VariableDeclaration{
location, location,
{{TypedName{location, var, {}}}}, {{TypedName{location, var, {}}}},
make_shared<Expression>(std::move(_expr)) make_unique<Expression>(std::move(_expr))
}); });
_expr = Identifier{location, var}; _expr = Identifier{location, var};
} }

View File

@ -181,9 +181,9 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
variableReplacements[_existingVariable.name] = newName; variableReplacements[_existingVariable.name] = newName;
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}}; VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
if (_value) if (_value)
varDecl.value = make_shared<Expression>(std::move(*_value)); varDecl.value = make_unique<Expression>(std::move(*_value));
else else
varDecl.value = make_shared<Expression>(zero); varDecl.value = make_unique<Expression>(zero);
newStatements.emplace_back(std::move(varDecl)); newStatements.emplace_back(std::move(varDecl));
}; };
@ -202,7 +202,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
newStatements.emplace_back(Assignment{ newStatements.emplace_back(Assignment{
_assignment.location, _assignment.location,
{_assignment.variableNames[i]}, {_assignment.variableNames[i]},
make_shared<Expression>(Identifier{ make_unique<Expression>(Identifier{
_assignment.location, _assignment.location,
variableReplacements.at(function->returnVariables[i].name) variableReplacements.at(function->returnVariables[i].name)
}) })
@ -214,7 +214,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
newStatements.emplace_back(VariableDeclaration{ newStatements.emplace_back(VariableDeclaration{
_varDecl.location, _varDecl.location,
{std::move(_varDecl.variables[i])}, {std::move(_varDecl.variables[i])},
make_shared<Expression>(Identifier{ make_unique<Expression>(Identifier{
_varDecl.location, _varDecl.location,
variableReplacements.at(function->returnVariables[i].name) variableReplacements.at(function->returnVariables[i].name)
}) })
@ -232,10 +232,10 @@ Statement BodyCopier::operator()(VariableDeclaration const& _varDecl)
return ASTCopier::operator()(_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."); assertThrow(false, OptimizerException, "Function hoisting has to be done before function inlining.");
return _funDef; return {};
} }
YulString BodyCopier::translateIdentifier(YulString _name) YulString BodyCopier::translateIdentifier(YulString _name)

View File

@ -66,12 +66,13 @@ void SSATransform::operator()(Block& _block)
// Creates a new variable (and returns its declaration) with value _value // Creates a new variable (and returns its declaration) with value _value
// and replaces _value by a reference to that new variable. // and replaces _value by a reference to that new variable.
auto replaceByNew = [&](SourceLocation _loc, YulString _varName, YulString _type, shared_ptr<Expression>& _value) -> VariableDeclaration
auto replaceByNew = [&](SourceLocation _loc, YulString _varName, YulString _type, unique_ptr<Expression>& _value) -> VariableDeclaration
{ {
YulString newName = m_nameDispenser.newName(_varName); YulString newName = m_nameDispenser.newName(_varName);
m_currentVariableValues[_varName] = newName; m_currentVariableValues[_varName] = newName;
variablesToClearAtEnd.emplace(_varName); variablesToClearAtEnd.emplace(_varName);
shared_ptr<Expression> v = make_shared<Expression>(Identifier{_loc, newName}); unique_ptr<Expression> v = make_unique<Expression>(Identifier{_loc, newName});
_value.swap(v); _value.swap(v);
return VariableDeclaration{_loc, {TypedName{_loc, std::move(newName), std::move(_type)}}, std::move(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); visit(*varDecl.value);
if (varDecl.variables.size() != 1 || !m_variablesToReplace.count(varDecl.variables.front().name)) if (varDecl.variables.size() != 1 || !m_variablesToReplace.count(varDecl.variables.front().name))
return {}; return {};
// Replace "let a := v" by "let a_1 := v let a := v" vector<Statement> v;
VariableDeclaration newVarDecl = replaceByNew( // Replace "let a := v" by "let a_1 := v let a := a_1"
v.emplace_back(replaceByNew(
varDecl.location, varDecl.location,
varDecl.variables.front().name, varDecl.variables.front().name,
varDecl.variables.front().type, varDecl.variables.front().type,
varDecl.value varDecl.value
); ));
return vector<Statement>{std::move(newVarDecl), std::move(varDecl)}; v.emplace_back(move(varDecl));
return v;
} }
else if (_s.type() == typeid(Assignment)) else if (_s.type() == typeid(Assignment))
{ {
@ -103,14 +106,16 @@ void SSATransform::operator()(Block& _block)
if (assignment.variableNames.size() != 1) if (assignment.variableNames.size() != 1)
return {}; return {};
assertThrow(m_variablesToReplace.count(assignment.variableNames.front().name), OptimizerException, ""); assertThrow(m_variablesToReplace.count(assignment.variableNames.front().name), OptimizerException, "");
vector<Statement> v;
// Replace "a := v" by "let a_1 := v a := v" // Replace "a := v" by "let a_1 := v a := v"
VariableDeclaration newVarDecl = replaceByNew( v.emplace_back(replaceByNew(
assignment.location, assignment.location,
assignment.variableNames.front().name, assignment.variableNames.front().name,
{}, // TODO determine type {}, // TODO determine type
assignment.value assignment.value
); ));
return vector<Statement>{std::move(newVarDecl), std::move(assignment)}; v.emplace_back(move(assignment));
return v;
} }
else else
visit(_s); visit(_s);

View File

@ -51,7 +51,11 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
GenericFallbackReturnsVisitor<OptionalStatements, If, Switch, ForLoop> const visitor( GenericFallbackReturnsVisitor<OptionalStatements, If, Switch, ForLoop> const visitor(
[&](If& _ifStmt) -> OptionalStatements { [&](If& _ifStmt) -> OptionalStatements {
if (_ifStmt.body.statements.empty()) if (_ifStmt.body.statements.empty())
return {{makePopExpressionStatement(_ifStmt.location, std::move(*_ifStmt.condition))}}; {
OptionalStatements s = vector<Statement>{};
s->emplace_back(makePopExpressionStatement(_ifStmt.location, std::move(*_ifStmt.condition)));
return s;
}
if (expressionAlwaysTrue(*_ifStmt.condition)) if (expressionAlwaysTrue(*_ifStmt.condition))
return {std::move(_ifStmt.body.statements)}; return {std::move(_ifStmt.body.statements)};
else if (expressionAlwaysFalse(*_ifStmt.condition)) else if (expressionAlwaysFalse(*_ifStmt.condition))
@ -64,18 +68,24 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
auto& switchCase = _switchStmt.cases.front(); auto& switchCase = _switchStmt.cases.front();
auto loc = locationOf(*_switchStmt.expression); auto loc = locationOf(*_switchStmt.expression);
if (switchCase.value) if (switchCase.value)
return {{If{ {
OptionalStatements s = vector<Statement>{};
s->emplace_back(If{
std::move(_switchStmt.location), std::move(_switchStmt.location),
make_shared<Expression>(FunctionalInstruction{ make_unique<Expression>(FunctionalInstruction{
std::move(loc), std::move(loc),
solidity::Instruction::EQ, solidity::Instruction::EQ,
{std::move(*switchCase.value), std::move(*_switchStmt.expression)} {std::move(*switchCase.value), std::move(*_switchStmt.expression)}
}), std::move(switchCase.body)}}}; }), std::move(switchCase.body)});
return s;
}
else else
return {{ {
makePopExpressionStatement(loc, std::move(*_switchStmt.expression)), OptionalStatements s = vector<Statement>{};
std::move(switchCase.body) s->emplace_back(makePopExpressionStatement(loc, std::move(*_switchStmt.expression)));
}}; s->emplace_back(std::move(switchCase.body));
return s;
}
} }
else else
return {}; return {};

View File

@ -100,7 +100,7 @@ bool SyntacticallyEqual::statementEqual(Assignment const& _lhs, Assignment const
bool SyntacticallyEqual::statementEqual(VariableDeclaration const& _lhs, VariableDeclaration const& _rhs) bool SyntacticallyEqual::statementEqual(VariableDeclaration const& _lhs, VariableDeclaration const& _rhs)
{ {
// first visit expression, then variable declarations // first visit expression, then variable declarations
if (!compareSharedPtr<Expression, &SyntacticallyEqual::operator()>(_lhs.value, _rhs.value)) if (!compareUniquePtr<Expression, &SyntacticallyEqual::operator()>(_lhs.value, _rhs.value))
return false; return false;
return containerEqual(_lhs.variables, _rhs.variables, [this](TypedName const& _lhsVarName, TypedName const& _rhsVarName) -> bool { return containerEqual(_lhs.variables, _rhs.variables, [this](TypedName const& _lhsVarName, TypedName const& _rhsVarName) -> bool {
return this->visitDeclaration(_lhsVarName, _rhsVarName); 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) bool SyntacticallyEqual::statementEqual(If const& _lhs, If const& _rhs)
{ {
return return
compareSharedPtr<Expression, &SyntacticallyEqual::operator()>(_lhs.condition, _rhs.condition) && compareUniquePtr<Expression, &SyntacticallyEqual::operator()>(_lhs.condition, _rhs.condition) &&
statementEqual(_lhs.body, _rhs.body); statementEqual(_lhs.body, _rhs.body);
} }
@ -139,7 +139,7 @@ bool SyntacticallyEqual::statementEqual(Switch const& _lhs, Switch const& _rhs)
for (auto const& rhsCase: _rhs.cases) for (auto const& rhsCase: _rhs.cases)
rhsCases.insert(&rhsCase); rhsCases.insert(&rhsCase);
return return
compareSharedPtr<Expression, &SyntacticallyEqual::operator()>(_lhs.expression, _rhs.expression) && compareUniquePtr<Expression, &SyntacticallyEqual::operator()>(_lhs.expression, _rhs.expression) &&
containerEqual(lhsCases, rhsCases, [this](Case const* _lhsCase, Case const* _rhsCase) -> bool { containerEqual(lhsCases, rhsCases, [this](Case const* _lhsCase, Case const* _rhsCase) -> bool {
return this->switchCaseEqual(*_lhsCase, *_rhsCase); 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) bool SyntacticallyEqual::switchCaseEqual(Case const& _lhs, Case const& _rhs)
{ {
return return
compareSharedPtr<Literal, &SyntacticallyEqual::expressionEqual>(_lhs.value, _rhs.value) && compareUniquePtr<Literal, &SyntacticallyEqual::expressionEqual>(_lhs.value, _rhs.value) &&
statementEqual(_lhs.body, _rhs.body); statementEqual(_lhs.body, _rhs.body);
} }
@ -157,7 +157,7 @@ bool SyntacticallyEqual::statementEqual(ForLoop const& _lhs, ForLoop const& _rhs
{ {
return return
statementEqual(_lhs.pre, _rhs.pre) && statementEqual(_lhs.pre, _rhs.pre) &&
compareSharedPtr<Expression, &SyntacticallyEqual::operator()>(_lhs.condition, _rhs.condition) && compareUniquePtr<Expression, &SyntacticallyEqual::operator()>(_lhs.condition, _rhs.condition) &&
statementEqual(_lhs.body, _rhs.body) && statementEqual(_lhs.body, _rhs.body) &&
statementEqual(_lhs.post, _rhs.post); statementEqual(_lhs.post, _rhs.post);
} }

View File

@ -76,7 +76,7 @@ private:
} }
template<typename T, bool (SyntacticallyEqual::*CompareMember)(T const&, T const&)> template<typename T, bool (SyntacticallyEqual::*CompareMember)(T const&, T const&)>
bool compareSharedPtr(std::shared_ptr<T> const& _lhs, std::shared_ptr<T> const& _rhs) bool compareUniquePtr(std::unique_ptr<T> const& _lhs, std::unique_ptr<T> const& _rhs)
{ {
return (_lhs == _rhs) || (_lhs && _rhs && (this->*CompareMember)(*_lhs, *_rhs)); return (_lhs == _rhs) || (_lhs && _rhs && (this->*CompareMember)(*_lhs, *_rhs));
} }

View File

@ -39,7 +39,7 @@ void VarDeclInitializer::operator()(Block& _block)
return {}; return {};
else if (_varDecl.variables.size() == 1) else if (_varDecl.variables.size() == 1)
{ {
_varDecl.value = make_shared<Expression>(zero); _varDecl.value = make_unique<Expression>(zero);
return {}; return {};
} }
else else
@ -47,7 +47,7 @@ void VarDeclInitializer::operator()(Block& _block)
OptionalStatements ret{vector<Statement>{}}; OptionalStatements ret{vector<Statement>{}};
langutil::SourceLocation loc{std::move(_varDecl.location)}; langutil::SourceLocation loc{std::move(_varDecl.location)};
for (auto& var: _varDecl.variables) for (auto& var: _varDecl.variables)
ret->push_back(VariableDeclaration{loc, {std::move(var)}, make_shared<Expression>(zero)}); ret->push_back(VariableDeclaration{loc, {std::move(var)}, make_unique<Expression>(zero)});
return ret; return ret;
} }
} }