diff options
Diffstat (limited to 'libevmasm')
-rw-r--r-- | libevmasm/Assembly.cpp | 11 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 8 | ||||
-rw-r--r-- | libevmasm/AssemblyItem.cpp | 2 | ||||
-rw-r--r-- | libevmasm/AssemblyItem.h | 14 | ||||
-rw-r--r-- | libevmasm/CMakeLists.txt | 22 | ||||
-rw-r--r-- | libevmasm/CommonSubexpressionEliminator.cpp | 1 | ||||
-rw-r--r-- | libevmasm/CommonSubexpressionEliminator.h | 9 | ||||
-rw-r--r-- | libevmasm/ConstantOptimiser.cpp | 2 | ||||
-rw-r--r-- | libevmasm/ConstantOptimiser.h | 14 | ||||
-rw-r--r-- | libevmasm/ControlFlowGraph.cpp | 2 | ||||
-rw-r--r-- | libevmasm/ExpressionClasses.cpp | 2 | ||||
-rw-r--r-- | libevmasm/ExpressionClasses.h | 7 | ||||
-rw-r--r-- | libevmasm/GasMeter.h | 2 | ||||
-rw-r--r-- | libevmasm/KnownState.cpp | 1 | ||||
-rw-r--r-- | libevmasm/KnownState.h | 21 | ||||
-rw-r--r-- | libevmasm/PathGasMeter.h | 2 | ||||
-rw-r--r-- | libevmasm/SimplificationRules.cpp | 2 | ||||
-rw-r--r-- | libevmasm/SimplificationRules.h | 9 | ||||
-rw-r--r-- | libevmasm/SourceLocation.h | 105 |
19 files changed, 86 insertions, 150 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index e63194a0..29d9846d 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -35,6 +35,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; void Assembly::append(Assembly const& _a) { @@ -113,10 +114,10 @@ namespace string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) { - if (_location.isEmpty() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0) + if (_location.isEmpty() || !_location.source.get() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0) return ""; - auto it = _sourceCodes.find(*_location.sourceName); + auto it = _sourceCodes.find(_location.source->name()); if (it == _sourceCodes.end()) return ""; @@ -185,11 +186,11 @@ public: void printLocation() { - if (!m_location.sourceName && m_location.isEmpty()) + if (!m_location.source && m_location.isEmpty()) return; m_out << m_prefix << " /*"; - if (m_location.sourceName) - m_out << " \"" + *m_location.sourceName + "\""; + if (m_location.source) + m_out << " \"" + m_location.source->name() + "\""; if (!m_location.isEmpty()) m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end); m_out << " " << locationFromSources(m_sourceCodes, m_location); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 8ef36923..d846b475 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -18,12 +18,12 @@ #pragma once #include <libevmasm/Instruction.h> -#include <libevmasm/SourceLocation.h> +#include <liblangutil/SourceLocation.h> #include <libevmasm/AssemblyItem.h> #include <libevmasm/LinkerObject.h> #include <libevmasm/Exceptions.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <libdevcore/Common.h> #include <libdevcore/Assertions.h> @@ -93,7 +93,7 @@ public: void setDeposit(int _deposit) { m_deposit = _deposit; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } /// Changes the source location used for each appended item. - void setSourceLocation(SourceLocation const& _location) { m_currentSourceLocation = _location; } + void setSourceLocation(langutil::SourceLocation const& _location) { m_currentSourceLocation = _location; } /// Assembles the assembly into bytecode. The assembly should not be modified after this call, since the assembled version is cached. LinkerObject const& assemble() const; @@ -178,7 +178,7 @@ protected: int m_deposit = 0; - SourceLocation m_currentSourceLocation; + langutil::SourceLocation m_currentSourceLocation; }; inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index a3a4d6b6..52f246d1 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -117,6 +117,8 @@ int AssemblyItem::returnValues() const bool AssemblyItem::canBeFunctional() const { + if (m_jumpType != JumpType::Ordinary) + return false; switch (m_type) { case Operation: diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 6187e18f..a7875171 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -26,7 +26,7 @@ #include <libdevcore/Common.h> #include <libdevcore/Assertions.h> #include <libevmasm/Instruction.h> -#include <libevmasm/SourceLocation.h> +#include <liblangutil/SourceLocation.h> #include "Exceptions.h" using namespace dev::solidity; @@ -57,14 +57,14 @@ class AssemblyItem public: enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; - AssemblyItem(u256 _push, SourceLocation const& _location = SourceLocation()): + AssemblyItem(u256 _push, langutil::SourceLocation const& _location = langutil::SourceLocation()): AssemblyItem(Push, _push, _location) { } - AssemblyItem(solidity::Instruction _i, SourceLocation const& _location = SourceLocation()): + AssemblyItem(solidity::Instruction _i, langutil::SourceLocation const& _location = langutil::SourceLocation()): m_type(Operation), m_instruction(_i), m_location(_location) {} - AssemblyItem(AssemblyItemType _type, u256 _data = 0, SourceLocation const& _location = SourceLocation()): + AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::SourceLocation const& _location = langutil::SourceLocation()): m_type(_type), m_location(_location) { @@ -124,8 +124,8 @@ public: /// @returns true if the assembly item can be used in a functional context. bool canBeFunctional() const; - void setLocation(SourceLocation const& _location) { m_location = _location; } - SourceLocation const& location() const { return m_location; } + void setLocation(langutil::SourceLocation const& _location) { m_location = _location; } + langutil::SourceLocation const& location() const { return m_location; } void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; } JumpType getJumpType() const { return m_jumpType; } @@ -140,7 +140,7 @@ private: AssemblyItemType m_type; Instruction m_instruction; ///< Only valid if m_type == Operation std::shared_ptr<u256> m_data; ///< Only valid if m_type != Operation - SourceLocation m_location; + langutil::SourceLocation m_location; JumpType m_jumpType = JumpType::Ordinary; /// Pushed value for operations with data to be determined during assembly stage, /// e.g. PushSubSize, PushTag, PushSub, etc. diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 86192c1b..e0e3389a 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -1,5 +1,21 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + Assembly.cpp + AssemblyItem.cpp + BlockDeduplicator.cpp + CommonSubexpressionEliminator.cpp + ConstantOptimiser.cpp + ControlFlowGraph.cpp + ExpressionClasses.cpp + GasMeter.cpp + Instruction.cpp + JumpdestRemover.cpp + KnownState.cpp + LinkerObject.cpp + PathGasMeter.cpp + PeepholeOptimiser.cpp + SemanticInformation.cpp + SimplificationRules.cpp +) -add_library(evmasm ${sources} ${headers}) +add_library(evmasm ${sources}) target_link_libraries(evmasm PUBLIC devcore) diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 04926986..949d2c75 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -30,6 +30,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems() { diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index b20de246..eba25db0 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -34,6 +34,11 @@ #include <libevmasm/SemanticInformation.h> #include <libevmasm/KnownState.h> +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -137,10 +142,10 @@ private: bool removeStackTopIfPossible(); /// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position. - void appendDup(int _fromPosition, SourceLocation const& _location); + void appendDup(int _fromPosition, langutil::SourceLocation const& _location); /// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position. /// @note this might also remove the last item if it exactly the same swap instruction. - void appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location); + void appendOrRemoveSwap(int _fromPosition, langutil::SourceLocation const& _location); /// Appends the given assembly item. void appendItem(AssemblyItem const& _item); diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 9844ba3a..ae1a5643 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -193,7 +193,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) bigint bestGas = gasNeeded(routine); for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits) { - unsigned gapDetector = unsigned(_value >> (bits - 8)) & 0x1ff; + unsigned gapDetector = unsigned((_value >> (bits - 8)) & 0x1ff); if (gapDetector != 0xff && gapDetector != 0x100) continue; diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 2c753fa8..04c43c5d 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -23,7 +23,7 @@ #include <libevmasm/Exceptions.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <libdevcore/Assertions.h> #include <libdevcore/CommonData.h> @@ -109,8 +109,8 @@ class LiteralMethod: public ConstantOptimisationMethod public: explicit LiteralMethod(Params const& _params, u256 const& _value): ConstantOptimisationMethod(_params, _value) {} - virtual bigint gasNeeded() const override; - virtual AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; } + bigint gasNeeded() const override; + AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; } }; /** @@ -120,8 +120,8 @@ class CodeCopyMethod: public ConstantOptimisationMethod { public: explicit CodeCopyMethod(Params const& _params, u256 const& _value); - virtual bigint gasNeeded() const override; - virtual AssemblyItems execute(Assembly& _assembly) const override; + bigint gasNeeded() const override; + AssemblyItems execute(Assembly& _assembly) const override; protected: static AssemblyItems const& copyRoutine(); @@ -144,8 +144,8 @@ public: ); } - virtual bigint gasNeeded() const override { return gasNeeded(m_routine); } - virtual AssemblyItems execute(Assembly&) const override + bigint gasNeeded() const override { return gasNeeded(m_routine); } + AssemblyItems execute(Assembly&) const override { return m_routine; } diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 86f16d48..d62f5436 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -275,7 +275,7 @@ void ControlFlowGraph::gatherKnowledge() //@todo in the case of JUMPI, add knowledge about the condition to the state // (for both values of the condition) set<u256> tags = state->tagsInExpression( - state->stackElement(state->stackHeight(), SourceLocation()) + state->stackElement(state->stackHeight(), langutil::SourceLocation{}) ); state->feedItem(m_items.at(pc++)); diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index 42a1819a..abbbbc2c 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -34,7 +34,7 @@ using namespace std; using namespace dev; using namespace dev::eth; - +using namespace langutil; bool ExpressionClasses::Expression::operator<(ExpressionClasses::Expression const& _other) const { diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index df8082f9..a34844c5 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -31,6 +31,11 @@ #include <memory> #include <set> +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -82,7 +87,7 @@ public: void forceEqual(Id _id, AssemblyItem const& _item, Ids const& _arguments, bool _copyItem = true); /// @returns the id of a new class which is different to all other classes. - Id newClass(SourceLocation const& _location); + Id newClass(langutil::SourceLocation const& _location); /// @returns true if the values of the given classes are known to be different (on every input). /// @note that this function might still return false for some different inputs. diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index da90b028..e3909e86 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -24,7 +24,7 @@ #include <libevmasm/ExpressionClasses.h> #include <libevmasm/AssemblyItem.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <ostream> #include <tuple> diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index b6c1bcc9..a5546e61 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -29,6 +29,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; ostream& KnownState::stream(ostream& _out) const { diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index cd50550e..3ab1c4b1 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -46,6 +46,11 @@ #include <libevmasm/ExpressionClasses.h> #include <libevmasm/SemanticInformation.h> +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -121,9 +126,9 @@ public: /// Retrieves the current equivalence class fo the given stack element (or generates a new /// one if it does not exist yet). - Id stackElement(int _stackHeight, SourceLocation const& _location); + Id stackElement(int _stackHeight, langutil::SourceLocation const& _location); /// @returns the stackElement relative to the current stack height. - Id relativeStackElement(int _stackOffset, SourceLocation const& _location = SourceLocation()); + Id relativeStackElement(int _stackOffset, langutil::SourceLocation const& _location = {}); /// @returns its set of tags if the given expression class is a known tag union; returns a set /// containing the tag if it is a PushTag expression and the empty set otherwise. @@ -142,22 +147,22 @@ private: /// Assigns a new equivalence class to the next sequence number of the given stack element. void setStackElement(int _stackHeight, Id _class); /// Swaps the given stack elements in their next sequence number. - void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location); + void swapStackElements(int _stackHeightA, int _stackHeightB, langutil::SourceLocation const& _location); /// Increments the sequence number, deletes all storage information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if storage was not modified - StoreOperation storeInStorage(Id _slot, Id _value, SourceLocation const& _location); + StoreOperation storeInStorage(Id _slot, Id _value, langutil::SourceLocation const& _location); /// Retrieves the current value at the given slot in storage or creates a new special sload class. - Id loadFromStorage(Id _slot, SourceLocation const& _location); + Id loadFromStorage(Id _slot, langutil::SourceLocation const& _location); /// Increments the sequence number, deletes all memory information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if memory was not modified - StoreOperation storeInMemory(Id _slot, Id _value, SourceLocation const& _location); + StoreOperation storeInMemory(Id _slot, Id _value, langutil::SourceLocation const& _location); /// Retrieves the current value at the given slot in memory or creates a new special mload class. - Id loadFromMemory(Id _slot, SourceLocation const& _location); + Id loadFromMemory(Id _slot, langutil::SourceLocation const& _location); /// Finds or creates a new expression that applies the Keccak-256 hash function to the contents in memory. - Id applyKeccak256(Id _start, Id _length, SourceLocation const& _location); + Id applyKeccak256(Id _start, Id _length, langutil::SourceLocation const& _location); /// @returns a new or already used Id representing the given set of tags. Id tagUnion(std::set<u256> _tags); diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h index fb821684..772df484 100644 --- a/libevmasm/PathGasMeter.h +++ b/libevmasm/PathGasMeter.h @@ -23,7 +23,7 @@ #include <libevmasm/GasMeter.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <set> #include <vector> diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index 120d1787..1dce5f1e 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -38,7 +38,7 @@ using namespace std; using namespace dev; using namespace dev::eth; - +using namespace langutil; SimplificationRule<Pattern> const* Rules::findFirstMatch( Expression const& _expr, diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index fbe5a2b0..fc45a46c 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -31,6 +31,11 @@ #include <functional> #include <vector> +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -97,7 +102,7 @@ public: unsigned matchGroup() const { return m_matchGroup; } bool matches(Expression const& _expr, ExpressionClasses const& _classes) const; - AssemblyItem toAssemblyItem(SourceLocation const& _location) const; + AssemblyItem toAssemblyItem(langutil::SourceLocation const& _location) const; std::vector<Pattern> arguments() const { return m_arguments; } /// @returns the id of the matched expression if this pattern is part of a match group. @@ -135,7 +140,7 @@ struct ExpressionTemplate { using Expression = ExpressionClasses::Expression; using Id = ExpressionClasses::Id; - explicit ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location); + explicit ExpressionTemplate(Pattern const& _pattern, langutil::SourceLocation const& _location); std::string toString() const; bool hasId = false; /// Id of the matched expression, if available. diff --git a/libevmasm/SourceLocation.h b/libevmasm/SourceLocation.h deleted file mode 100644 index b42c3aa9..00000000 --- a/libevmasm/SourceLocation.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see <http://www.gnu.org/licenses/>. -*/ -/** - * @author Lefteris Karapetsas <lefteris@ethdev.com> - * @date 2015 - * Represents a location in a source file - */ - -#pragma once - -#include <memory> -#include <string> -#include <ostream> -#include <tuple> -#include <libdevcore/Common.h> // defines noexcept macro for MSVC - -namespace dev -{ - -/** - * Representation of an interval of source positions. - * The interval includes start and excludes end. - */ -struct SourceLocation -{ - SourceLocation(): start(-1), end(-1) { } - SourceLocation(int _start, int _end, std::shared_ptr<std::string const> _sourceName): - start(_start), end(_end), sourceName(_sourceName) { } - SourceLocation(SourceLocation&& _other) noexcept: - start(_other.start), - end(_other.end), - sourceName(std::move(_other.sourceName)) - {} - SourceLocation(SourceLocation const&) = default; - SourceLocation& operator=(SourceLocation const&) = default; - SourceLocation& operator=(SourceLocation&& _other) noexcept - { - start = _other.start; - end = _other.end; - sourceName = std::move(_other.sourceName); - return *this; - } - - bool operator==(SourceLocation const& _other) const - { - return start == _other.start && end == _other.end && - ((!sourceName && !_other.sourceName) || (sourceName && _other.sourceName && *sourceName == *_other.sourceName)); - } - bool operator!=(SourceLocation const& _other) const { return !operator==(_other); } - inline bool operator<(SourceLocation const& _other) const; - inline bool contains(SourceLocation const& _other) const; - inline bool intersects(SourceLocation const& _other) const; - - bool isEmpty() const { return start == -1 && end == -1; } - - int start; - int end; - std::shared_ptr<std::string const> sourceName; -}; - -/// Stream output for Location (used e.g. in boost exceptions). -inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location) -{ - if (_location.isEmpty()) - return _out << "NO_LOCATION_SPECIFIED"; - return _out << *_location.sourceName << "[" << _location.start << "," << _location.end << ")"; -} - -bool SourceLocation::operator<(SourceLocation const& _other) const -{ - if (!sourceName || !_other.sourceName) - return std::make_tuple(int(!!sourceName), start, end) < std::make_tuple(int(!!_other.sourceName), _other.start, _other.end); - else - return std::make_tuple(*sourceName, start, end) < std::make_tuple(*_other.sourceName, _other.start, _other.end); -} - -bool SourceLocation::contains(SourceLocation const& _other) const -{ - if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) - return false; - return start <= _other.start && _other.end <= end; -} - -bool SourceLocation::intersects(SourceLocation const& _other) const -{ - if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) - return false; - return _other.start < end && start < _other.end; -} - -} |