Merge pull request #6503 from ethereum/inlineAsm-yul

Inline asm yul
This commit is contained in:
chriseth 2019-04-18 17:15:09 +02:00 committed by GitHub
commit b02fbc5d02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 104 additions and 2 deletions

View File

@ -23,12 +23,61 @@
#include <libsolidity/codegen/ir/IRGenerationContext.h>
#include <libsolidity/codegen/YulUtilFunctions.h>
#include <libyul/AsmPrinter.h>
#include <libyul/AsmData.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libdevcore/StringUtils.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
namespace
{
struct CopyTranslate: public yul::ASTCopier
{
using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>;
CopyTranslate(IRGenerationContext& _context, ExternalRefsMap const& _references):
m_context(_context), m_references(_references) {}
using ASTCopier::operator();
yul::YulString translateIdentifier(yul::YulString _name) override
{
return yul::YulString{"usr$" + _name.str()};
}
yul::Identifier translate(yul::Identifier const& _identifier) override
{
if (!m_references.count(&_identifier))
return ASTCopier::translate(_identifier);
auto const& reference = m_references.at(&_identifier);
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
solUnimplementedAssert(varDecl, "");
solUnimplementedAssert(
reference.isOffset == false && reference.isSlot == false,
""
);
return yul::Identifier{
_identifier.location,
yul::YulString{m_context.variableName(*varDecl)}
};
}
private:
IRGenerationContext& m_context;
ExternalRefsMap const& m_references;
};
}
bool IRGeneratorForStatements::visit(VariableDeclarationStatement const& _varDeclStatement)
{
for (auto const& decl: _varDeclStatement.declarations())
@ -179,6 +228,18 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
return false;
}
bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
{
CopyTranslate bodyCopier{m_context, _inlineAsm.annotation().externalReferences};
yul::Statement modified = bodyCopier(_inlineAsm.operations());
solAssert(modified.type() == typeid(yul::Block), "");
m_code << yul::AsmPrinter()(boost::get<yul::Block>(std::move(modified))) << "\n";
return false;
}
bool IRGeneratorForStatements::visit(Identifier const& _identifier)
{
Declaration const* declaration = _identifier.annotation().referencedDeclaration;

View File

@ -48,6 +48,7 @@ public:
bool visit(Assignment const& _assignment) override;
void endVisit(BinaryOperation const& _binOp) override;
bool visit(FunctionCall const& _funCall) override;
bool visit(InlineAssembly const& _inlineAsm) override;
bool visit(Identifier const& _identifier) override;
bool visit(Literal const& _literal) override;

View File

@ -91,7 +91,7 @@ Expression ASTCopier::operator()(FunctionalInstruction const& _instruction)
Expression ASTCopier::operator()(Identifier const& _identifier)
{
return Identifier{_identifier.location, translateIdentifier(_identifier.name)};
return translate(_identifier);
}
Expression ASTCopier::operator()(Literal const& _literal)

View File

@ -104,7 +104,7 @@ protected:
Block translate(Block const& _block);
Case translate(Case const& _case);
Identifier translate(Identifier const& _identifier);
virtual Identifier translate(Identifier const& _identifier);
Literal translate(Literal const& _literal);
TypedName translate(TypedName const& _typedName);

View File

@ -0,0 +1,17 @@
contract C {
function f() public pure returns (uint32 x) {
uint32 a;
uint32 b;
uint32 c;
assembly {
a := 1
b := 2
c := 3
}
x = a + b + c;
}
}
// ====
// compileViaYul: true
// ----
// f() -> 6

View File

@ -0,0 +1,23 @@
contract C {
function f() public pure returns (uint32 x) {
uint32 a;
uint32 b;
uint32 c;
assembly {
function myAwesomeFunction(param) -> returnMe {
let localVar := 10
returnMe := add(localVar, param)
}
let abc := sub(10, a)
let xyz := 20
a := abc
b := myAwesomeFunction(30)
c := xyz
}
x = a + b + c;
}
}
// ====
// compileViaYul: true
// ----
// f() -> 70