From 3d061c83d733df77c52a243a6ac990cc2e362e04 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Thu, 11 Apr 2019 12:58:27 +0200 Subject: [PATCH] IR: Generate inline asm blocks --- .../codegen/ir/IRGeneratorForStatements.cpp | 61 +++++++++++++++++++ .../codegen/ir/IRGeneratorForStatements.h | 1 + libyul/optimiser/ASTCopier.cpp | 2 +- libyul/optimiser/ASTCopier.h | 2 +- .../viaYul/simple_inline_asm.sol | 17 ++++++ .../viaYul/various_inline_asm.sol | 23 +++++++ 6 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/semanticTests/viaYul/simple_inline_asm.sol create mode 100644 test/libsolidity/semanticTests/viaYul/various_inline_asm.sol diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 62842f47e..1c2563771 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -23,12 +23,61 @@ #include #include +#include +#include +#include + #include using namespace std; using namespace dev; using namespace dev::solidity; +namespace +{ + +struct CopyTranslate: public yul::ASTCopier +{ + using ExternalRefsMap = std::map; + + 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(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(std::move(modified))) << "\n"; + return false; +} + bool IRGeneratorForStatements::visit(Identifier const& _identifier) { Declaration const* declaration = _identifier.annotation().referencedDeclaration; diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 6c33b7b05..c90f2f0bf 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -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; diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index f98cb5653..efe3ff854 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -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) diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index a408b43fb..b2e0a383a 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -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); diff --git a/test/libsolidity/semanticTests/viaYul/simple_inline_asm.sol b/test/libsolidity/semanticTests/viaYul/simple_inline_asm.sol new file mode 100644 index 000000000..f0779639f --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/simple_inline_asm.sol @@ -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 diff --git a/test/libsolidity/semanticTests/viaYul/various_inline_asm.sol b/test/libsolidity/semanticTests/viaYul/various_inline_asm.sol new file mode 100644 index 000000000..ebdbb7522 --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/various_inline_asm.sol @@ -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