Browse Source

Merge pull request #1205 from LianaHus/sol_SourceLineInOutput

Added source lines to output
cl-refactor
chriseth 10 years ago
parent
commit
11a4ec737a
  1. 52
      libevmcore/Assembly.cpp
  2. 9
      libevmcore/Assembly.h
  3. 7
      libsolidity/Compiler.h
  4. 5
      libsolidity/CompilerContext.h
  5. 4
      libsolidity/CompilerStack.cpp
  6. 7
      libsolidity/CompilerStack.h
  7. 4
      solc/CommandLineInterface.cpp

52
libevmcore/Assembly.cpp

@ -21,6 +21,8 @@
#include "Assembly.h" #include "Assembly.h"
#include <fstream>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
using namespace std; using namespace std;
@ -171,48 +173,74 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i)
return _out; return _out;
} }
ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) 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 const& source = it->second;
if (size_t(_location.start) >= source.size())
return "";
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(cut);
}
ostream& Assembly::streamRLP(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
{ {
_out << _prefix << ".code:" << endl; _out << _prefix << ".code:" << endl;
for (AssemblyItem const& i: m_items) for (AssemblyItem const& i: m_items)
{
string sourceLine = getLocationFromSources(_sourceCodes, i.getLocation());
_out << _prefix;
switch (i.m_type) switch (i.m_type)
{ {
case Operation: case Operation:
_out << _prefix << " " << instructionInfo((Instruction)(byte)i.m_data).name << endl; _out << " " << instructionInfo((Instruction)(byte)i.m_data).name;
break; break;
case Push: case Push:
_out << _prefix << " PUSH " << i.m_data << endl; _out << " PUSH " << i.m_data;
break; break;
case PushString: case PushString:
_out << _prefix << " PUSH \"" << m_strings.at((h256)i.m_data) << "\"" << endl; _out << " PUSH \"" << m_strings.at((h256)i.m_data) << "\"";
break; break;
case PushTag: case PushTag:
_out << _prefix << " PUSH [tag" << i.m_data << "]" << endl; _out << " PUSH [tag" << i.m_data << "]";
break; break;
case PushSub: case PushSub:
_out << _prefix << " PUSH [$" << h256(i.m_data).abridged() << "]" << endl; _out << " PUSH [$" << h256(i.m_data).abridged() << "]";
break; break;
case PushSubSize: case PushSubSize:
_out << _prefix << " PUSH #[$" << h256(i.m_data).abridged() << "]" << endl; _out << " PUSH #[$" << h256(i.m_data).abridged() << "]";
break; break;
case PushProgramSize: case PushProgramSize:
_out << _prefix << " PUSHSIZE" << endl; _out << " PUSHSIZE";
break; break;
case Tag: case Tag:
_out << _prefix << "tag" << i.m_data << ": " << endl << _prefix << " JUMPDEST" << endl; _out << "tag" << i.m_data << ": " << endl << _prefix << " JUMPDEST";
break; break;
case PushData: case PushData:
_out << _prefix << " PUSH [" << hex << (unsigned)i.m_data << "]" << endl; _out << " PUSH [" << hex << (unsigned)i.m_data << "]";
break; break;
case NoOptimizeBegin: case NoOptimizeBegin:
_out << _prefix << "DoNotOptimze{{" << endl; _out << "DoNotOptimze{{";
break; break;
case NoOptimizeEnd: case NoOptimizeEnd:
_out << _prefix << "DoNotOptimze}}" << endl; _out << "DoNotOptimze}}";
break; break;
default: default:
BOOST_THROW_EXCEPTION(InvalidOpcode()); BOOST_THROW_EXCEPTION(InvalidOpcode());
} }
_out << string("\t\t") << sourceLine << endl;
}
if (!m_data.empty() || !m_subs.empty()) if (!m_data.empty() || !m_subs.empty())
{ {

9
libevmcore/Assembly.h

@ -100,9 +100,7 @@ public:
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } 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 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; } AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; }
template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; } template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
AssemblyItems const& getItems() const { return m_items; } AssemblyItems const& getItems() const { return m_items; }
AssemblyItem const& back() const { return m_items.back(); } 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(); } 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,18 +114,17 @@ public:
void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); } void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); }
void injectStart(AssemblyItem const& _i); void injectStart(AssemblyItem const& _i);
std::string out() const { std::stringstream ret; streamRLP(ret); return ret.str(); } std::string out() const { std::stringstream ret; streamRLP(ret); return ret.str(); }
int deposit() const { return m_deposit; } int deposit() const { return m_deposit; }
void adjustDeposit(int _adjustment) { m_deposit += _adjustment; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } 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()); } void setDeposit(int _deposit) { m_deposit = _deposit; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
bytes assemble() const; bytes assemble() const;
Assembly& optimise(bool _enable); 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 = "", const StringMap &_sourceCodes = StringMap()) const;
private: protected:
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()); } void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
unsigned bytesRequired() const; unsigned bytesRequired() const;

7
libsolidity/Compiler.h

@ -41,8 +41,11 @@ public:
std::map<ContractDefinition const*, bytes const*> const& _contracts); std::map<ContractDefinition const*, bytes const*> const& _contracts);
bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); } bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); }
bytes getRuntimeBytecode() { return m_runtimeContext.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 /// @returns Assembly items of the normal compiler context
eth::AssemblyItems const& getAssemblyItems() const { return m_context.getAssembly().getItems(); } eth::AssemblyItems const& getAssemblyItems() const { return m_context.getAssembly().getItems(); }
/// @returns Assembly items of the runtime compiler context /// @returns Assembly items of the runtime compiler context

5
libsolidity/CompilerContext.h

@ -28,6 +28,7 @@
#include <libevmcore/Assembly.h> #include <libevmcore/Assembly.h>
#include <libsolidity/ASTForward.h> #include <libsolidity/ASTForward.h>
#include <libsolidity/Types.h> #include <libsolidity/Types.h>
#include <libdevcore/Common.h>
namespace dev { namespace dev {
namespace solidity { namespace solidity {
@ -118,7 +119,9 @@ public:
CompilerContext& operator<<(bytes const& _data); CompilerContext& operator<<(bytes const& _data);
eth::Assembly const& getAssembly() const { return m_asm; } 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(); } bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); }
/** /**

4
libsolidity/CompilerStack.cpp

@ -180,9 +180,9 @@ dev::h256 CompilerStack::getContractCodeHash(string const& _contractName) const
return dev::sha3(getRuntimeBytecode(_contractName)); 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 string const& CompilerStack::getInterface(string const& _contractName) const

7
libsolidity/CompilerStack.h

@ -59,8 +59,6 @@ enum class DocumentationType: uint8_t
ABISolidityInterface ABISolidityInterface
}; };
extern const std::map<std::string, std::string> StandardSources;
/** /**
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible. * 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. * 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. /// 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. /// @returns true if a source object by the name already existed and was replaced.
void addSources(std::map<std::string, std::string> 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); bool addSource(std::string const& _name, std::string const& _content, bool _isLibrary = false);
void setSource(std::string const& _sourceCode); void setSource(std::string const& _sourceCode);
/// Parses all source units that were added /// Parses all source units that were added
@ -103,8 +101,9 @@ public:
dev::h256 getContractCodeHash(std::string const& _contractName = "") const; dev::h256 getContractCodeHash(std::string const& _contractName = "") const;
/// Streams a verbose version of the assembly to @a _outStream. /// 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. /// 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. /// Returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile. /// Prerequisite: Successful call to parse or compile.

4
solc/CommandLineInterface.cpp

@ -424,13 +424,13 @@ void CommandLineInterface::actOnInput()
if (outputToStdout(choice)) if (outputToStdout(choice))
{ {
cout << "EVM assembly:" << endl; cout << "EVM assembly:" << endl;
m_compiler->streamAssembly(cout, contract); m_compiler->streamAssembly(cout, contract, m_sourceCodes);
} }
if (outputToFile(choice)) if (outputToFile(choice))
{ {
ofstream outFile(contract + ".evm"); ofstream outFile(contract + ".evm");
m_compiler->streamAssembly(outFile, contract); m_compiler->streamAssembly(outFile, contract, m_sourceCodes);
outFile.close(); outFile.close();
} }
} }

Loading…
Cancel
Save