Assembly printer.

This commit is contained in:
chriseth 2017-02-09 14:04:23 +01:00
parent 4189ff5b68
commit 80f7243786
4 changed files with 204 additions and 4 deletions

View File

@ -0,0 +1,125 @@
/*
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 Christian <c@ethdev.com>
* @date 2017
* Converts a parsed assembly into its textual form.
*/
#include <libsolidity/inlineasm/AsmPrinter.h>
#include <libsolidity/inlineasm/AsmData.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <memory>
#include <functional>
using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::assembly;
//@TODO source locations
string AsmPrinter::operator()(assembly::Instruction const& _instruction)
{
return boost::to_lower_copy(instructionInfo(_instruction.instruction).name);
}
string AsmPrinter::operator()(assembly::Literal const& _literal)
{
if (_literal.isNumber)
return _literal.value;
string out;
for (char c: _literal.value)
if (c == '\\')
out += "\\\\";
else if (c == '"')
out += "\\";
else if (c == '\'')
out += "\\'";
else if (c == '\b')
out += "\\b";
else if (c == '\f')
out += "\\f";
else if (c == '\n')
out += "\\n";
else if (c == '\r')
out += "\\r";
else if (c == '\t')
out += "\\t";
else if (c == '\v')
out += "\\v";
else if (!isprint(c, locale::classic()))
{
ostringstream o;
o << std::hex << setfill('0') << setw(2) << unsigned(c);
out += "0x" + o.str();
}
else
out += c;
return out;
}
string AsmPrinter::operator()(assembly::Identifier const& _identifier)
{
return _identifier.name;
}
string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functionalInstruction)
{
return
(*this)(_functionalInstruction.instruction); +
"(" +
boost::algorithm::join(
_functionalInstruction.arguments | boost::adaptors::transformed(boost::apply_visitor(*this)),
", " ) +
")";
}
string AsmPrinter::operator()(assembly::Label const& _label)
{
return _label.name + ":";
}
string AsmPrinter::operator()(assembly::Assignment const& _assignment)
{
return "=: " + (*this)(_assignment.variableName);
}
string AsmPrinter::operator()(assembly::FunctionalAssignment const& _functionalAssignment)
{
return (*this)(_functionalAssignment.variableName) + " := " + boost::apply_visitor(*this, *_functionalAssignment.value);
}
string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDeclaration)
{
return "let " + _variableDeclaration.name + " := " + boost::apply_visitor(*this, *_variableDeclaration.value);
}
string AsmPrinter::operator()(Block const& _block)
{
string body = boost::algorithm::join(
_block.statements | boost::adaptors::transformed(boost::apply_visitor(*this)),
"\n"
);
boost::replace_all(body, "\n", "\n ");
return "{\n " + body + "\n}";
}

View File

@ -0,0 +1,61 @@
/*
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 Christian <c@ethdev.com>
* @date 2017
* Converts a parsed assembly into its textual form.
*/
#pragma once
#include <boost/variant.hpp>
namespace dev
{
namespace solidity
{
namespace assembly
{
struct Instruction;
struct Literal;
struct Identifier;
struct FunctionalInstruction;
struct Label;
struct Assignment;
struct FunctionalAssignment;
struct VariableDeclaration;
struct FunctionDefinition;
struct FunctionCall;
struct Block;
class AsmPrinter: public boost::static_visitor<std::string>
{
public:
std::string operator()(assembly::Instruction const& _instruction);
std::string operator()(assembly::Literal const& _literal);
std::string operator()(assembly::Identifier const& _identifier);
std::string operator()(assembly::FunctionalInstruction const& _functionalInstruction);
std::string operator()(assembly::Label const& _label);
std::string operator()(assembly::Assignment const& _assignment);
std::string operator()(assembly::FunctionalAssignment const& _functionalAssignment);
std::string operator()(assembly::VariableDeclaration const& _variableDeclaration);
std::string operator()(assembly::Block const& _block);
};
}
}
}

View File

@ -21,12 +21,17 @@
*/
#include <libsolidity/inlineasm/AsmStack.h>
#include <memory>
#include <libevmasm/Assembly.h>
#include <libevmasm/SourceLocation.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/inlineasm/AsmCodeGen.h>
#include <libsolidity/inlineasm/AsmPrinter.h>
#include <libsolidity/parsing/Scanner.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/SourceLocation.h>
#include <memory>
using namespace std;
using namespace dev;
@ -44,6 +49,11 @@ bool InlineAssemblyStack::parse(shared_ptr<Scanner> const& _scanner)
return true;
}
string InlineAssemblyStack::print()
{
return AsmPrinter()(*m_parserResult);
}
eth::Assembly InlineAssemblyStack::assemble()
{
CodeGenerator codeGen(*m_parserResult, m_errors);

View File

@ -46,6 +46,10 @@ public:
/// Parse the given inline assembly chunk starting with `{` and ending with the corresponding `}`.
/// @return false or error.
bool parse(std::shared_ptr<Scanner> const& _scanner);
/// Converts the parser result back into a string form (not necessarily the same form
/// as the source form, but it should parse into the same parsed form again).
std::string print();
eth::Assembly assemble();
/// Parse and assemble a string in one run - for use in Solidity code generation itself.