aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-10-16 23:01:13 +0800
committerchriseth <chris@ethereum.org>2018-10-17 23:21:55 +0800
commit732d09cef1548e2111c47b6f5b04a54db10a9d41 (patch)
tree757af93eb855da8de07c99d5429be27a95f78ab1
parentf2f72ff7eea9a461ae8c71a13428e499c8b91025 (diff)
downloaddexon-solidity-732d09cef1548e2111c47b6f5b04a54db10a9d41.tar.gz
dexon-solidity-732d09cef1548e2111c47b6f5b04a54db10a9d41.tar.zst
dexon-solidity-732d09cef1548e2111c47b6f5b04a54db10a9d41.zip
Limit size of generated names and add convenience constructors.
-rw-r--r--libyul/optimiser/Disambiguator.h3
-rw-r--r--libyul/optimiser/FullInliner.cpp14
-rw-r--r--libyul/optimiser/FullInliner.h2
-rw-r--r--libyul/optimiser/NameDispenser.cpp31
-rw-r--r--libyul/optimiser/NameDispenser.h26
-rw-r--r--test/libyul/YulOptimizerTest.cpp9
-rw-r--r--test/libyul/yulOptimizerTests/disambiguator/long_names.yul12
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/long_names.yul25
8 files changed, 97 insertions, 25 deletions
diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h
index e16ebfbf..74a491ab 100644
--- a/libyul/optimiser/Disambiguator.h
+++ b/libyul/optimiser/Disambiguator.h
@@ -47,9 +47,8 @@ public:
solidity::assembly::AsmAnalysisInfo const& _analysisInfo,
std::set<std::string> const& _externallyUsedIdentifiers = {}
):
- m_info(_analysisInfo), m_externallyUsedIdentifiers(_externallyUsedIdentifiers)
+ m_info(_analysisInfo), m_externallyUsedIdentifiers(_externallyUsedIdentifiers), m_nameDispenser(m_externallyUsedIdentifiers)
{
- m_nameDispenser.m_usedNames = m_externallyUsedIdentifiers;
}
protected:
diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp
index cd0ed52a..c20c2b08 100644
--- a/libyul/optimiser/FullInliner.cpp
+++ b/libyul/optimiser/FullInliner.cpp
@@ -39,11 +39,10 @@ using namespace dev::yul;
using namespace dev::solidity;
FullInliner::FullInliner(Block& _ast):
- m_ast(_ast)
+ m_ast(_ast), m_nameDispenser(_ast)
{
assertThrow(m_ast.statements.size() >= 1, OptimizerException, "");
assertThrow(m_ast.statements.front().type() == typeid(Block), OptimizerException, "");
- m_nameDispenser.m_usedNames = NameCollector(m_ast).names();
for (size_t i = 1; i < m_ast.statements.size(); ++i)
{
@@ -112,7 +111,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
// helper function to create a new variable that is supposed to model
// an existing variable.
auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) {
- string newName = m_nameDispenser.newName(function.name + "_" + _existingVariable.name);
+ string newName = m_nameDispenser.newName(_existingVariable.name, function.name);
variableReplacements[_existingVariable.name] = newName;
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
if (_value)
@@ -125,7 +124,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
for (auto const& var: function.returnVariables)
newVariable(var, nullptr);
- Statement newBody = BodyCopier(m_nameDispenser, function.name + "_", variableReplacements)(function.body);
+ Statement newBody = BodyCopier(m_nameDispenser, function.name, variableReplacements)(function.body);
newStatements += std::move(boost::get<Block>(newBody).statements);
boost::apply_visitor(GenericFallbackVisitor<Assignment, VariableDeclaration>{
@@ -158,15 +157,10 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
return newStatements;
}
-string InlineModifier::newName(string const& _prefix)
-{
- return m_nameDispenser.newName(_prefix);
-}
-
Statement BodyCopier::operator()(VariableDeclaration const& _varDecl)
{
for (auto const& var: _varDecl.variables)
- m_variableReplacements[var.name] = m_nameDispenser.newName(m_varNamePrefix + var.name);
+ m_variableReplacements[var.name] = m_nameDispenser.newName(var.name, m_varNamePrefix);
return ASTCopier::operator()(_varDecl);
}
diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h
index 495286c0..5037b56e 100644
--- a/libyul/optimiser/FullInliner.h
+++ b/libyul/optimiser/FullInliner.h
@@ -106,8 +106,6 @@ private:
boost::optional<std::vector<Statement>> tryInlineStatement(Statement& _statement);
std::vector<Statement> performInline(Statement& _statement, FunctionCall& _funCall);
- std::string newName(std::string const& _prefix);
-
std::string m_currentFunction;
FullInliner& m_driver;
NameDispenser& m_nameDispenser;
diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp
index f7385471..d3f10bc2 100644
--- a/libyul/optimiser/NameDispenser.cpp
+++ b/libyul/optimiser/NameDispenser.cpp
@@ -20,18 +20,43 @@
#include <libyul/optimiser/NameDispenser.h>
+#include <libyul/optimiser/NameCollector.h>
+
+#include <libsolidity/inlineasm/AsmData.h>
+
using namespace std;
using namespace dev;
using namespace dev::yul;
-string NameDispenser::newName(string const& _prefix)
+NameDispenser::NameDispenser(Block const& _ast):
+ NameDispenser(NameCollector(_ast).names())
+{
+}
+
+NameDispenser::NameDispenser(set<string> _usedNames):
+ m_usedNames(std::move(_usedNames))
+{
+}
+
+string NameDispenser::newName(string const& _nameHint, string const& _context)
+{
+ // Shortening rules: Use a suffix of _prefix and a prefix of _context.
+ string prefix = _nameHint;
+
+ if (!_context.empty())
+ prefix = _context.substr(0, 10) + "_" + prefix;
+
+ return newNameInternal(prefix);
+}
+
+string NameDispenser::newNameInternal(string const& _nameHint)
{
- string name = _prefix;
size_t suffix = 0;
+ string name = _nameHint;
while (name.empty() || m_usedNames.count(name))
{
suffix++;
- name = _prefix + "_" + to_string(suffix);
+ name = _nameHint + "_" + to_string(suffix);
}
m_usedNames.insert(name);
return name;
diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h
index 64ec318f..5fbf5f8e 100644
--- a/libyul/optimiser/NameDispenser.h
+++ b/libyul/optimiser/NameDispenser.h
@@ -19,6 +19,8 @@
*/
#pragma once
+#include <libyul/ASTDataForward.h>
+
#include <set>
#include <string>
@@ -27,9 +29,29 @@ namespace dev
namespace yul
{
-struct NameDispenser
+/**
+ * Optimizer component that can be used to generate new names that
+ * do not conflict with existing names.
+ *
+ * Tries to keep names short and appends decimals to disambiguate.
+ */
+class NameDispenser
{
- std::string newName(std::string const& _prefix);
+public:
+ /// Initialize the name dispenser with all the names used in the given AST.
+ explicit NameDispenser(Block const& _ast);
+ /// Initialize the name dispenser with the given used names.
+ explicit NameDispenser(std::set<std::string> _usedNames);
+
+ /// @returns a currently unused name that should be similar to _nameHint
+ /// and prefixed by _context if present.
+ /// If the resulting name would be too long, trims the context at the end
+ /// and the name hint at the start.
+ std::string newName(std::string const& _nameHint, std::string const& _context = {});
+
+private:
+ std::string newNameInternal(std::string const& _nameHint);
+
std::set<std::string> m_usedNames;
};
diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp
index 8e4771c8..a89711a1 100644
--- a/test/libyul/YulOptimizerTest.cpp
+++ b/test/libyul/YulOptimizerTest.cpp
@@ -106,8 +106,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
}
else if (m_optimizerStep == "expressionSplitter")
{
- NameDispenser nameDispenser;
- nameDispenser.m_usedNames = NameCollector(*m_ast).names();
+ NameDispenser nameDispenser(*m_ast);
ExpressionSplitter{nameDispenser}(*m_ast);
}
else if (m_optimizerStep == "functionGrouper")
@@ -130,8 +129,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
disambiguate();
(FunctionHoister{})(*m_ast);
(FunctionGrouper{})(*m_ast);
- NameDispenser nameDispenser;
- nameDispenser.m_usedNames = NameCollector(*m_ast).names();
+ NameDispenser nameDispenser(*m_ast);
ExpressionSplitter{nameDispenser}(*m_ast);
FullInliner(*m_ast).run();
ExpressionJoiner::run(*m_ast);
@@ -155,8 +153,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
else if (m_optimizerStep == "fullSimplify")
{
disambiguate();
- NameDispenser nameDispenser;
- nameDispenser.m_usedNames = NameCollector(*m_ast).names();
+ NameDispenser nameDispenser(*m_ast);
ExpressionSplitter{nameDispenser}(*m_ast);
CommonSubexpressionEliminator{}(*m_ast);
ExpressionSimplifier::run(*m_ast);
diff --git a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul
new file mode 100644
index 00000000..933e1e8f
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul
@@ -0,0 +1,12 @@
+// yul
+{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } }
+// ----
+// disambiguator
+// {
+// {
+// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256
+// }
+// {
+// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh_1:u256
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul
new file mode 100644
index 00000000..644e9126
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul
@@ -0,0 +1,25 @@
+{
+ function verylongfunctionname(verylongvariablename) -> verylongvariablename2 {
+ verylongvariablename2 := add(verylongvariablename, verylongvariablename)
+ }
+ // same long name
+ let verylongvariablename2 := 3
+ mstore(0, verylongfunctionname(verylongvariablename2))
+ mstore(1, verylongvariablename2)
+}
+// ----
+// fullInliner
+// {
+// {
+// let verylongvariablename2_1 := 3
+// let verylongfu_verylongvariablename := verylongvariablename2_1
+// let verylongfu_verylongvariablename2
+// verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename)
+// mstore(0, verylongfu_verylongvariablename2)
+// mstore(1, verylongvariablename2_1)
+// }
+// function verylongfunctionname(verylongvariablename) -> verylongvariablename2
+// {
+// verylongvariablename2 := add(verylongvariablename, verylongvariablename)
+// }
+// }