diff options
author | chriseth <chris@ethereum.org> | 2018-01-12 23:14:59 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-02-06 19:31:43 +0800 |
commit | 22c4d282aae4279b37bd3d031b3baade2a3e508b (patch) | |
tree | fa20f662875653562983e3ec1ee810b6c47bedf5 /libjulia/optimiser/Rematerialiser.cpp | |
parent | 30e6f69bfd1a6fd907b96060901b0962b1e9cf18 (diff) | |
download | dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.tar dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.tar.gz dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.tar.bz2 dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.tar.lz dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.tar.xz dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.tar.zst dexon-solidity-22c4d282aae4279b37bd3d031b3baade2a3e508b.zip |
Only substitute if all referenced variables are in scope.
Diffstat (limited to 'libjulia/optimiser/Rematerialiser.cpp')
-rw-r--r-- | libjulia/optimiser/Rematerialiser.cpp | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/libjulia/optimiser/Rematerialiser.cpp b/libjulia/optimiser/Rematerialiser.cpp index ca5f94b0..09a9bb90 100644 --- a/libjulia/optimiser/Rematerialiser.cpp +++ b/libjulia/optimiser/Rematerialiser.cpp @@ -29,6 +29,8 @@ #include <libdevcore/CommonData.h> +#include <boost/range/adaptor/reversed.hpp> + using namespace std; using namespace dev; using namespace dev::julia; @@ -46,6 +48,7 @@ void Rematerialiser::operator()(VariableDeclaration& _varDecl) set<string> names; for (auto const& var: _varDecl.variables) names.insert(var.name); + m_variableScopes.back().first += names; handleAssignment(names, _varDecl.value.get()); } @@ -74,9 +77,23 @@ void Rematerialiser::operator()(Switch& _switch) handleAssignment(assignedVariables, nullptr); } +void Rematerialiser::operator()(FunctionDefinition& _fun) +{ + m_variableScopes.push_back(make_pair(set<string>(), true)); + for (auto const& parameter: _fun.parameters) + m_variableScopes.back().first.insert(parameter.name); + for (auto const& var: _fun.returnVariables) + m_variableScopes.back().first.insert(var.name); + ASTModifier::operator()(_fun); + m_variableScopes.pop_back(); +} + void Rematerialiser::operator()(ForLoop& _for) { - (*this)(_for.pre); + // Special scope handling of the pre block. + m_variableScopes.push_back(make_pair(set<string>(), false)); + for (auto& statement: _for.pre.statements) + visit(statement); Assignments ass; ass(_for.body); @@ -88,6 +105,17 @@ void Rematerialiser::operator()(ForLoop& _for) (*this)(_for.post); handleAssignment(ass.names(), nullptr); + + m_variableScopes.pop_back(); +} + +void Rematerialiser::operator()(Block& _block) +{ + size_t numScopes = m_variableScopes.size(); + m_variableScopes.push_back(make_pair(set<string>(), false)); + ASTModifier::operator()(_block); + m_variableScopes.pop_back(); + solAssert(numScopes == m_variableScopes.size(), ""); } void Rematerialiser::handleAssignment(set<string> const& _variables, Expression* _value) @@ -128,6 +156,18 @@ void Rematerialiser::handleAssignment(set<string> const& _variables, Expression* } } +bool Rematerialiser::inScope(string const& _variableName) const +{ + for (auto const& scope: m_variableScopes | boost::adaptors::reversed) + { + if (scope.first.count(_variableName)) + return true; + if (scope.second) + return false; + } + return false; +} + void Rematerialiser::visit(Expression& _e) { if (_e.type() == typeid(Identifier)) @@ -136,7 +176,15 @@ void Rematerialiser::visit(Expression& _e) if (m_substitutions.count(identifier.name)) { string name = identifier.name; - _e = (ASTCopier{}).translate(*m_substitutions.at(name)); + bool doSubstitute = true; + for (auto const& ref: m_references[name]) + if (!inScope(ref)) + { + doSubstitute = false; + break; + } + if (doSubstitute) + _e = (ASTCopier{}).translate(*m_substitutions.at(name)); } } ASTModifier::visit(_e); |