Use different way to fall back to FunctionalInstruction for loose assembly.

This commit is contained in:
chriseth 2019-05-22 16:46:04 +02:00
parent 9a00729ce7
commit 97fa21841d
2 changed files with 25 additions and 16 deletions

View File

@ -32,6 +32,7 @@
#include <libyul/AsmPrinter.h> #include <libyul/AsmPrinter.h>
#include <libyul/AsmData.h> #include <libyul/AsmData.h>
#include <libyul/Dialect.h>
#include <libyul/optimiser/ASTCopier.h> #include <libyul/optimiser/ASTCopier.h>
#include <libdevcore/Whiskers.h> #include <libdevcore/Whiskers.h>
@ -50,13 +51,20 @@ struct CopyTranslate: public yul::ASTCopier
{ {
using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>; using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>;
CopyTranslate(IRGenerationContext& _context, ExternalRefsMap const& _references): CopyTranslate(yul::Dialect const& _dialect, IRGenerationContext& _context, ExternalRefsMap const& _references):
m_context(_context), m_references(_references) {} m_dialect(_dialect), m_context(_context), m_references(_references) {}
using ASTCopier::operator(); using ASTCopier::operator();
yul::YulString translateIdentifier(yul::YulString _name) override yul::YulString translateIdentifier(yul::YulString _name) override
{ {
// Strictly, the dialect used by inline assembly (m_dialect) could be different
// from the Yul dialect we are compiling to. So we are assuming here that the builtin
// functions are identical. This should not be a problem for now since everything
// is EVM anyway.
if (m_dialect.builtin(_name))
return _name;
else
return yul::YulString{"usr$" + _name.str()}; return yul::YulString{"usr$" + _name.str()};
} }
@ -80,6 +88,7 @@ struct CopyTranslate: public yul::ASTCopier
} }
private: private:
yul::Dialect const& m_dialect;
IRGenerationContext& m_context; IRGenerationContext& m_context;
ExternalRefsMap const& m_references; ExternalRefsMap const& m_references;
}; };
@ -723,7 +732,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
{ {
CopyTranslate bodyCopier{m_context, _inlineAsm.annotation().externalReferences}; CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences};
yul::Statement modified = bodyCopier(_inlineAsm.operations()); yul::Statement modified = bodyCopier(_inlineAsm.operations());

View File

@ -248,13 +248,6 @@ Statement Parser::parseStatement()
if (elementary.type() == typeid(Identifier)) if (elementary.type() == typeid(Identifier))
{ {
Identifier& identifier = boost::get<Identifier>(elementary); Identifier& identifier = boost::get<Identifier>(elementary);
// Fallback from builtin function to Instruction for loose assembly.
if (
m_dialect.flavour == AsmFlavour::Loose &&
instructions().count(identifier.name.str())
)
return Instruction{identifier.location, instructions().at(identifier.name.str())};
else
return ExpressionStatement{identifier.location, { move(identifier) }}; return ExpressionStatement{identifier.location, { move(identifier) }};
} }
else if (elementary.type() == typeid(Literal)) else if (elementary.type() == typeid(Literal))
@ -405,11 +398,18 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
// first search the set of builtins, then the instructions. // first search the set of builtins, then the instructions.
if (m_dialect.builtin(literal)) if (m_dialect.builtin(literal))
{ {
// For builtins we already check here that they are followed by `(`. Identifier identifier{location(), literal};
ret = FunctionCall{location(), Identifier{location(), literal}, {}};
advance(); advance();
expectToken(Token::LParen, false); // If the builtin is not followed by `(` and we are in loose mode,
return ret; // fall back to instruction.
if (
m_dialect.flavour == AsmFlavour::Loose &&
instructions().count(identifier.name.str()) &&
m_scanner->currentToken() != Token::LParen
)
return Instruction{identifier.location, instructions().at(identifier.name.str())};
else
return FunctionCall{identifier.location, identifier, {}};
} }
else if (m_dialect.flavour == AsmFlavour::Loose && instructions().count(literal.str())) else if (m_dialect.flavour == AsmFlavour::Loose && instructions().count(literal.str()))
{ {