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/AsmData.h>
#include <libyul/Dialect.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libdevcore/Whiskers.h>
@ -50,13 +51,20 @@ 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) {}
CopyTranslate(yul::Dialect const& _dialect, IRGenerationContext& _context, ExternalRefsMap const& _references):
m_dialect(_dialect), m_context(_context), m_references(_references) {}
using ASTCopier::operator();
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()};
}
@ -80,6 +88,7 @@ struct CopyTranslate: public yul::ASTCopier
}
private:
yul::Dialect const& m_dialect;
IRGenerationContext& m_context;
ExternalRefsMap const& m_references;
};
@ -723,7 +732,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
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());

View File

@ -248,13 +248,6 @@ Statement Parser::parseStatement()
if (elementary.type() == typeid(Identifier))
{
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) }};
}
else if (elementary.type() == typeid(Literal))
@ -405,11 +398,18 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
// first search the set of builtins, then the instructions.
if (m_dialect.builtin(literal))
{
// For builtins we already check here that they are followed by `(`.
ret = FunctionCall{location(), Identifier{location(), literal}, {}};
Identifier identifier{location(), literal};
advance();
expectToken(Token::LParen, false);
return ret;
// If the builtin is not followed by `(` and we are in loose mode,
// 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()))
{