aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-10-17 23:05:49 +0800
committerGitHub <noreply@github.com>2018-10-17 23:05:49 +0800
commitf2f72ff7eea9a461ae8c71a13428e499c8b91025 (patch)
tree02c46d9f13ff85b5a2ad3d124054bdfc71af4791
parent6b7d182658988f22ba23cc3852510864881515e2 (diff)
parent16c2a775fd532c301eae3abecc8d68c5c421a9a0 (diff)
downloaddexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.tar
dexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.tar.gz
dexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.tar.bz2
dexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.tar.lz
dexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.tar.xz
dexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.tar.zst
dexon-solidity-f2f72ff7eea9a461ae8c71a13428e499c8b91025.zip
Merge pull request #5227 from ethereum/doNotRemoveExternallyUsedFunction
Prevent externally used functions from being removed.
-rw-r--r--libsolidity/codegen/ABIFunctions.cpp15
-rw-r--r--libsolidity/codegen/ABIFunctions.h15
-rw-r--r--libsolidity/codegen/CompilerContext.cpp1
-rw-r--r--libsolidity/codegen/CompilerContext.h2
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp6
-rw-r--r--libyul/optimiser/Disambiguator.cpp3
-rw-r--r--libyul/optimiser/Disambiguator.h12
-rw-r--r--libyul/optimiser/UnusedPruner.cpp8
-rw-r--r--libyul/optimiser/UnusedPruner.h4
-rw-r--r--test/libyul/Common.cpp2
10 files changed, 49 insertions, 19 deletions
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp
index 6c27533c..bd29b382 100644
--- a/libsolidity/codegen/ABIFunctions.cpp
+++ b/libsolidity/codegen/ABIFunctions.cpp
@@ -49,7 +49,7 @@ string ABIFunctions::tupleEncoder(
if (_encodeAsLibraryTypes)
functionName += "_library";
- return createFunction(functionName, [&]() {
+ return createExternallyUsedFunction(functionName, [&]() {
solAssert(!_givenTypes.empty(), "");
// Note that the values are in reverse due to the difference in calling semantics.
@@ -113,7 +113,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
solAssert(!_types.empty(), "");
- return createFunction(functionName, [&]() {
+ return createExternallyUsedFunction(functionName, [&]() {
TypePointers decodingTypes;
for (auto const& t: _types)
decodingTypes.emplace_back(t->decodingType());
@@ -176,13 +176,13 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
});
}
-string ABIFunctions::requestedFunctions()
+pair<string, set<string>> ABIFunctions::requestedFunctions()
{
string result;
for (auto const& f: m_requestedFunctions)
result += f.second;
m_requestedFunctions.clear();
- return result;
+ return make_pair(result, std::move(m_externallyUsedFunctions));
}
string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure)
@@ -1697,6 +1697,13 @@ string ABIFunctions::createFunction(string const& _name, function<string ()> con
return _name;
}
+string ABIFunctions::createExternallyUsedFunction(string const& _name, function<string ()> const& _creator)
+{
+ string name = createFunction(_name, _creator);
+ m_externallyUsedFunctions.insert(name);
+ return name;
+}
+
size_t ABIFunctions::headSize(TypePointers const& _targetTypes)
{
size_t headSize = 0;
diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h
index 3caaa1d9..e9ffe4fb 100644
--- a/libsolidity/codegen/ABIFunctions.h
+++ b/libsolidity/codegen/ABIFunctions.h
@@ -28,6 +28,7 @@
#include <vector>
#include <functional>
+#include <set>
#include <map>
namespace dev {
@@ -80,8 +81,11 @@ public:
/// stack slot, it takes exactly that number of values.
std::string tupleDecoder(TypePointers const& _types, bool _fromMemory = false);
- /// @returns concatenation of all generated functions.
- std::string requestedFunctions();
+ /// @returns concatenation of all generated functions and a set of the
+ /// externally used functions.
+ /// Clears the internal list, i.e. calling it again will result in an
+ /// empty return value.
+ std::pair<std::string, std::set<std::string>> requestedFunctions();
private:
/// @returns the name of the cleanup function for the given type and
@@ -224,12 +228,17 @@ private:
/// cases.
std::string createFunction(std::string const& _name, std::function<std::string()> const& _creator);
+ /// Helper function that uses @a _creator to create a function and add it to
+ /// @a m_requestedFunctions if it has not been created yet and returns @a _name in both
+ /// cases. Also adds it to the list of externally used functions.
+ std::string createExternallyUsedFunction(std::string const& _name, std::function<std::string()> const& _creator);
+
/// @returns the size of the static part of the encoding of the given types.
static size_t headSize(TypePointers const& _targetTypes);
/// Map from function name to code for a multi-use function.
std::map<std::string, std::string> m_requestedFunctions;
-
+ std::set<std::string> m_externallyUsedFunctions;
EVMVersion m_evmVersion;
};
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 089386b5..210b613d 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -313,6 +313,7 @@ void CompilerContext::resetVisitedNodes(ASTNode const* _node)
void CompilerContext::appendInlineAssembly(
string const& _assembly,
vector<string> const& _localVariables,
+ set<string> const&,
bool _system
)
{
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 3f357821..5bdc1d19 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -206,10 +206,12 @@ public:
/// Appends inline assembly (strict mode).
/// @a _replacements are string-matching replacements that are performed prior to parsing the inline assembly.
/// @param _localVariables assigns stack positions to variables with the last one being the stack top
+ /// @param _externallyUsedFunctions a set of function names that are not to be renamed or removed.
/// @param _system if true, this is a "system-level" assembly where all functions use named labels.
void appendInlineAssembly(
std::string const& _assembly,
std::vector<std::string> const& _localVariables = std::vector<std::string>(),
+ std::set<std::string> const& _externallyUsedFunctions = std::set<std::string>(),
bool _system = false
);
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index c845da8f..1fdf3483 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -874,9 +874,9 @@ void ContractCompiler::appendMissingFunctions()
solAssert(m_context.nextFunctionToCompile() != function, "Compiled the wrong function?");
}
m_context.appendMissingLowLevelFunctions();
- string abiFunctions = m_context.abiFunctions().requestedFunctions();
- if (!abiFunctions.empty())
- m_context.appendInlineAssembly("{" + move(abiFunctions) + "}", {}, true);
+ auto abiFunctions = m_context.abiFunctions().requestedFunctions();
+ if (!abiFunctions.first.empty())
+ m_context.appendInlineAssembly("{" + move(abiFunctions.first) + "}", {}, abiFunctions.second, true);
}
void ContractCompiler::appendModifierOrFunctionCode()
diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp
index af3507e1..dcba97c9 100644
--- a/libyul/optimiser/Disambiguator.cpp
+++ b/libyul/optimiser/Disambiguator.cpp
@@ -34,6 +34,9 @@ using Scope = dev::solidity::assembly::Scope;
string Disambiguator::translateIdentifier(string const& _originalName)
{
+ if ((m_externallyUsedIdentifiers.count(_originalName)))
+ return _originalName;
+
assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, "");
Scope::Identifier const* id = m_scopes.back()->lookup(_originalName);
assertThrow(id, OptimizerException, "");
diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h
index 0829fd58..e16ebfbf 100644
--- a/libyul/optimiser/Disambiguator.h
+++ b/libyul/optimiser/Disambiguator.h
@@ -43,9 +43,14 @@ namespace yul
class Disambiguator: public ASTCopier
{
public:
- Disambiguator(solidity::assembly::AsmAnalysisInfo const& _analysisInfo):
- m_info(_analysisInfo)
- {}
+ explicit Disambiguator(
+ solidity::assembly::AsmAnalysisInfo const& _analysisInfo,
+ std::set<std::string> const& _externallyUsedIdentifiers = {}
+ ):
+ m_info(_analysisInfo), m_externallyUsedIdentifiers(_externallyUsedIdentifiers)
+ {
+ m_nameDispenser.m_usedNames = m_externallyUsedIdentifiers;
+ }
protected:
virtual void enterScope(Block const& _block) override;
@@ -58,6 +63,7 @@ protected:
void leaveScopeInternal(solidity::assembly::Scope& _scope);
solidity::assembly::AsmAnalysisInfo const& m_info;
+ std::set<std::string> const& m_externallyUsedIdentifiers;
std::vector<solidity::assembly::Scope*> m_scopes;
std::map<void const*, std::string> m_translations;
diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp
index 74b6bee4..37a74553 100644
--- a/libyul/optimiser/UnusedPruner.cpp
+++ b/libyul/optimiser/UnusedPruner.cpp
@@ -33,12 +33,14 @@ using namespace std;
using namespace dev;
using namespace dev::yul;
-UnusedPruner::UnusedPruner(Block& _ast)
+UnusedPruner::UnusedPruner(Block& _ast, set<string> const& _externallyUsedFunctions)
{
ReferencesCounter counter;
counter(_ast);
m_references = counter.references();
+ for (auto const& f: _externallyUsedFunctions)
+ ++m_references[f];
}
void UnusedPruner::operator()(Block& _block)
@@ -89,11 +91,11 @@ void UnusedPruner::operator()(Block& _block)
ASTModifier::operator()(_block);
}
-void UnusedPruner::runUntilStabilised(Block& _ast)
+void UnusedPruner::runUntilStabilised(Block& _ast, set<string> const& _externallyUsedFunctions)
{
while (true)
{
- UnusedPruner pruner(_ast);
+ UnusedPruner pruner(_ast, _externallyUsedFunctions);
pruner(_ast);
if (!pruner.shouldRunAgain())
return;
diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h
index 327921ea..30617ff3 100644
--- a/libyul/optimiser/UnusedPruner.h
+++ b/libyul/optimiser/UnusedPruner.h
@@ -44,7 +44,7 @@ namespace yul
class UnusedPruner: public ASTModifier
{
public:
- explicit UnusedPruner(Block& _ast);
+ explicit UnusedPruner(Block& _ast, std::set<std::string> const& _externallyUsedFunctions = std::set<std::string>());
using ASTModifier::operator();
virtual void operator()(Block& _block) override;
@@ -53,7 +53,7 @@ public:
bool shouldRunAgain() const { return m_shouldRunAgain; }
// Run the pruner until the code does not change anymore.
- static void runUntilStabilised(Block& _ast);
+ static void runUntilStabilised(Block& _ast, std::set<std::string> const& _externallyUsedFunctions = std::set<std::string>());
private:
bool used(std::string const& _name) const;
diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp
index 4c50180a..d224bdcd 100644
--- a/test/libyul/Common.cpp
+++ b/test/libyul/Common.cpp
@@ -86,7 +86,7 @@ pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::yul::test::p
assembly::Block dev::yul::test::disambiguate(string const& _source, bool _yul)
{
auto result = parse(_source, _yul);
- return boost::get<Block>(Disambiguator(*result.second)(*result.first));
+ return boost::get<Block>(Disambiguator(*result.second, {})(*result.first));
}
string dev::yul::test::format(string const& _source, bool _yul)