From 369abf4294b7a556a9520c07d0702a3d40030bfe Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Tue, 3 Mar 2015 18:11:10 +0100 Subject: [PATCH 1/4] to include source lines in output stream AssemblyItem's appropriate function is now receiving the map of fileNames to sourceCodes as argument. --- libevmcore/Assembly.cpp | 3 ++- libevmcore/Assembly.h | 6 +----- libsolidity/Compiler.h | 7 +++++-- libsolidity/CompilerContext.h | 5 ++++- libsolidity/CompilerStack.cpp | 4 ++-- libsolidity/CompilerStack.h | 7 +++---- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index 80ac8c68f..0a568cbfb 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -171,8 +171,9 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) return _out; } -ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) const +ostream& Assembly::streamRLP(ostream& _out, string const& _prefix, StringMap _sourceCodes) const { + (void)_sourceCodes; _out << _prefix << ".code:" << endl; for (AssemblyItem const& i: m_items) switch (i.m_type) diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index 73d2b663c..8bab175a8 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -100,9 +100,7 @@ public: AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; } - template Assembly& operator<<(T const& _d) { append(_d); return *this; } - AssemblyItems const& getItems() const { return m_items; } AssemblyItem const& back() const { return m_items.back(); } std::string backString() const { return m_items.size() && m_items.back().m_type == PushString ? m_strings.at((h256)m_items.back().m_data) : std::string(); } @@ -116,16 +114,14 @@ public: void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); } void injectStart(AssemblyItem const& _i); - std::string out() const { std::stringstream ret; streamRLP(ret); return ret.str(); } - int deposit() const { return m_deposit; } void adjustDeposit(int _adjustment) { m_deposit += _adjustment; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } void setDeposit(int _deposit) { m_deposit = _deposit; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } bytes assemble() const; Assembly& optimise(bool _enable); - std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "") const; + std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "", StringMap _sourceCodes = StringMap()) const; private: void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index 2804e8eca..76f16f3ab 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -41,8 +41,11 @@ public: std::map const& _contracts); bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); } bytes getRuntimeBytecode() { return m_runtimeContext.getAssembledBytecode(m_optimize);} - void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } - + /// @arg _sourceCodes is the map of input files to source code strings + void streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap()) const + { + m_context.streamAssembly(_stream, _sourceCodes); + } /// @returns Assembly items of the normal compiler context eth::AssemblyItems const& getAssemblyItems() const { return m_context.getAssembly().getItems(); } /// @returns Assembly items of the runtime compiler context diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 301ef1468..e42e7c76c 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace dev { namespace solidity { @@ -118,7 +119,9 @@ public: CompilerContext& operator<<(bytes const& _data); eth::Assembly const& getAssembly() const { return m_asm; } - void streamAssembly(std::ostream& _stream) const { _stream << m_asm; } + /// @arg _sourceCodes is the map of input files to source code strings + void streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap()) const { m_asm.streamRLP(_stream, "", _sourceCodes); } + bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); } /** diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 10504a245..a878bb61a 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -180,9 +180,9 @@ dev::h256 CompilerStack::getContractCodeHash(string const& _contractName) const return dev::sha3(getRuntimeBytecode(_contractName)); } -void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName) const +void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName, StringMap _sourceCodes) const { - getContract(_contractName).compiler->streamAssembly(_outStream); + getContract(_contractName).compiler->streamAssembly(_outStream, _sourceCodes); } string const& CompilerStack::getInterface(string const& _contractName) const diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 2f34ab722..1cf576ab4 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -59,8 +59,6 @@ enum class DocumentationType: uint8_t ABISolidityInterface }; -extern const std::map StandardSources; - /** * Easy to use and self-contained Solidity compiler with as few header dependencies as possible. * It holds state and can be used to either step through the compilation stages (and abort e.g. @@ -74,7 +72,7 @@ public: /// Adds a source object (e.g. file) to the parser. After this, parse has to be called again. /// @returns true if a source object by the name already existed and was replaced. - void addSources(std::map const& _nameContents, bool _isLibrary = false) { for (auto const& i: _nameContents) addSource(i.first, i.second, _isLibrary); } + void addSources(StringMap const& _nameContents, bool _isLibrary = false) { for (auto const& i: _nameContents) addSource(i.first, i.second, _isLibrary); } bool addSource(std::string const& _name, std::string const& _content, bool _isLibrary = false); void setSource(std::string const& _sourceCode); /// Parses all source units that were added @@ -103,8 +101,9 @@ public: dev::h256 getContractCodeHash(std::string const& _contractName = "") const; /// Streams a verbose version of the assembly to @a _outStream. + /// @arg _sourceCodes is the map of input files to source code strings /// Prerequisite: Successful compilation. - void streamAssembly(std::ostream& _outStream, std::string const& _contractName = "") const; + void streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const; /// Returns a string representing the contract interface in JSON. /// Prerequisite: Successful call to parse or compile. From 18176ea3e4c5957c61adbfa10be5ea8301bf46c1 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Wed, 4 Mar 2015 18:01:23 +0100 Subject: [PATCH 2/4] added source code printing for each output line. some changes after pr review --- libevmcore/Assembly.cpp | 53 ++++++++++++++++++++++++++--------- libevmcore/Assembly.h | 5 ++-- solc/CommandLineInterface.cpp | 4 +-- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index 0a568cbfb..7f6a16116 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -21,6 +21,8 @@ #include "Assembly.h" +#include + #include using namespace std; @@ -171,49 +173,74 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) return _out; } -ostream& Assembly::streamRLP(ostream& _out, string const& _prefix, StringMap _sourceCodes) const +string Assembly::getLocationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const +{ + if (_location.isEmpty() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0) + return ""; + + auto it = _sourceCodes.find(*_location.sourceName); + if (it == _sourceCodes.end()) + return ""; + + string toReturn = it->second; + if (_location.start >= (int)toReturn.size()) + return ""; + + toReturn = toReturn.substr(_location.start, _location.end - _location.start); + auto newLinePos = toReturn.find_first_of("\n"); + if (newLinePos != string::npos && newLinePos != toReturn.size() - 1) + toReturn = toReturn.substr(0, newLinePos) + "..."; + + return move(toReturn); +} + +ostream& Assembly::streamRLP(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const { - (void)_sourceCodes; _out << _prefix << ".code:" << endl; for (AssemblyItem const& i: m_items) + { + string sourceLine = getLocationFromSources(_sourceCodes, i.getLocation()); + _out << _prefix; switch (i.m_type) { case Operation: - _out << _prefix << " " << instructionInfo((Instruction)(byte)i.m_data).name << endl; + _out << " " << instructionInfo((Instruction)(byte)i.m_data).name; break; case Push: - _out << _prefix << " PUSH " << i.m_data << endl; + _out << " PUSH " << i.m_data; break; case PushString: - _out << _prefix << " PUSH \"" << m_strings.at((h256)i.m_data) << "\"" << endl; + _out << " PUSH \"" << m_strings.at((h256)i.m_data) << "\""; break; case PushTag: - _out << _prefix << " PUSH [tag" << i.m_data << "]" << endl; + _out << " PUSH [tag" << i.m_data << "]"; break; case PushSub: - _out << _prefix << " PUSH [$" << h256(i.m_data).abridged() << "]" << endl; + _out << " PUSH [$" << h256(i.m_data).abridged() << "]"; break; case PushSubSize: - _out << _prefix << " PUSH #[$" << h256(i.m_data).abridged() << "]" << endl; + _out << " PUSH #[$" << h256(i.m_data).abridged() << "]"; break; case PushProgramSize: - _out << _prefix << " PUSHSIZE" << endl; + _out << " PUSHSIZE"; break; case Tag: - _out << _prefix << "tag" << i.m_data << ": " << endl << _prefix << " JUMPDEST" << endl; + _out << "tag" << i.m_data << ": " << endl << _prefix << " JUMPDEST"; break; case PushData: - _out << _prefix << " PUSH [" << hex << (unsigned)i.m_data << "]" << endl; + _out << " PUSH [" << hex << (unsigned)i.m_data << "]"; break; case NoOptimizeBegin: - _out << _prefix << "DoNotOptimze{{" << endl; + _out << "DoNotOptimze{{"; break; case NoOptimizeEnd: - _out << _prefix << "DoNotOptimze}}" << endl; + _out << "DoNotOptimze}}"; break; default: BOOST_THROW_EXCEPTION(InvalidOpcode()); } + _out << string(20, ' ') << sourceLine << endl; + } if (!m_data.empty() || !m_subs.empty()) { diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index 8bab175a8..bd2c87f4c 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -121,9 +121,10 @@ public: bytes assemble() const; Assembly& optimise(bool _enable); - std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "", StringMap _sourceCodes = StringMap()) const; + std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "", const StringMap &_sourceCodes = StringMap()) const; -private: +protected: + std::string getLocationFromSources(const StringMap &_sourceCodes, const SourceLocation &_location) const; void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } unsigned bytesRequired() const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index db12231a7..08acb5ebd 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -424,13 +424,13 @@ void CommandLineInterface::actOnInput() if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; - m_compiler->streamAssembly(cout, contract); + m_compiler->streamAssembly(cout, contract, m_sourceCodes); } if (outputToFile(choice)) { ofstream outFile(contract + ".evm"); - m_compiler->streamAssembly(outFile, contract); + m_compiler->streamAssembly(outFile, contract, m_sourceCodes); outFile.close(); } } From c17c9a4c3175c1e9ccb98164b2e6b3a4e68d1cbe Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Thu, 5 Mar 2015 17:20:38 +0100 Subject: [PATCH 3/4] style fixes --- libevmcore/Assembly.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index 7f6a16116..5e9d2fcd3 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -182,16 +182,16 @@ string Assembly::getLocationFromSources(StringMap const& _sourceCodes, SourceLoc if (it == _sourceCodes.end()) return ""; - string toReturn = it->second; - if (_location.start >= (int)toReturn.size()) + string const& source = it->second; + if (size_t(_location.start) >= source.size()) return ""; - toReturn = toReturn.substr(_location.start, _location.end - _location.start); - auto newLinePos = toReturn.find_first_of("\n"); - if (newLinePos != string::npos && newLinePos != toReturn.size() - 1) - toReturn = toReturn.substr(0, newLinePos) + "..."; + string cut = source.substr(_location.start, _location.end - _location.start); + auto newLinePos = cut.find_first_of("\n"); + if (newLinePos != string::npos) + cut = cut.substr(0, newLinePos) + "..."; - return move(toReturn); + return move(cut); } ostream& Assembly::streamRLP(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const @@ -239,7 +239,7 @@ ostream& Assembly::streamRLP(ostream& _out, string const& _prefix, StringMap con default: BOOST_THROW_EXCEPTION(InvalidOpcode()); } - _out << string(20, ' ') << sourceLine << endl; + _out << string("\t\t") << sourceLine << endl; } if (!m_data.empty() || !m_subs.empty()) From 1b2efc5bf234239120753f35453c90646aadadab Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Thu, 5 Mar 2015 17:23:20 +0100 Subject: [PATCH 4/4] one more style fix --- libevmcore/Assembly.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index bd2c87f4c..4b818e624 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -124,7 +124,7 @@ public: std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "", const StringMap &_sourceCodes = StringMap()) const; protected: - std::string getLocationFromSources(const StringMap &_sourceCodes, const SourceLocation &_location) const; + std::string getLocationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const; void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } unsigned bytesRequired() const;