Merge pull request #6818 from ethereum/alwaysUseBuiltins

Provide builtin functions even in loose assembly mode.
This commit is contained in:
chriseth
2019-05-23 12:29:12 +02:00
committed by GitHub
18 changed files with 115 additions and 63 deletions
+1 -2
View File
@@ -27,7 +27,6 @@
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <liblangutil/ErrorReporter.h>
@@ -707,7 +706,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
*_inlineAssembly.annotation().analysisInfo,
m_errorReporter,
Error::Type::SyntaxError,
yul::EVMDialect::looseAssemblyForEVM(m_evmVersion),
_inlineAssembly.dialect(),
identifierAccess
);
if (!analyzer.analyze(_inlineAssembly.operations()))
+15 -2
View File
@@ -18,6 +18,7 @@
#include <libsolidity/analysis/ViewPureChecker.h>
#include <libsolidity/ast/ExperimentalFeatures.h>
#include <libyul/AsmData.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <liblangutil/ErrorReporter.h>
#include <libevmasm/SemanticInformation.h>
#include <functional>
@@ -33,7 +34,11 @@ namespace
class AssemblyViewPureChecker: public boost::static_visitor<void>
{
public:
explicit AssemblyViewPureChecker(std::function<void(StateMutability, SourceLocation const&)> _reportMutability):
explicit AssemblyViewPureChecker(
yul::Dialect const& _dialect,
std::function<void(StateMutability, SourceLocation const&)> _reportMutability
):
m_dialect(_dialect),
m_reportMutability(_reportMutability) {}
void operator()(yul::Label const&) { }
@@ -69,6 +74,11 @@ public:
}
void operator()(yul::FunctionCall const& _funCall)
{
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
if (fun->instruction)
checkInstruction(_funCall.location, *fun->instruction);
for (auto const& arg: _funCall.arguments)
boost::apply_visitor(*this, arg);
}
@@ -107,7 +117,6 @@ public:
}
private:
std::function<void(StateMutability, SourceLocation const&)> m_reportMutability;
void checkInstruction(SourceLocation _location, dev::eth::Instruction _instruction)
{
if (eth::SemanticInformation::invalidInViewFunctions(_instruction))
@@ -115,6 +124,9 @@ private:
else if (eth::SemanticInformation::invalidInPureFunctions(_instruction))
m_reportMutability(StateMutability::View, _location);
}
yul::Dialect const& m_dialect;
std::function<void(StateMutability, SourceLocation const&)> m_reportMutability;
};
}
@@ -221,6 +233,7 @@ void ViewPureChecker::endVisit(Identifier const& _identifier)
void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly)
{
AssemblyViewPureChecker{
_inlineAssembly.dialect(),
[=](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); }
}(_inlineAssembly.operations());
}
+5 -1
View File
@@ -43,6 +43,7 @@ namespace yul
{
// Forward-declaration to <yul/AsmData.h>
struct Block;
struct Dialect;
}
namespace dev
@@ -1049,17 +1050,20 @@ public:
InlineAssembly(
SourceLocation const& _location,
ASTPointer<ASTString> const& _docString,
yul::Dialect const& _dialect,
std::shared_ptr<yul::Block> const& _operations
):
Statement(_location, _docString), m_operations(_operations) {}
Statement(_location, _docString), m_dialect(_dialect), m_operations(_operations) {}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;
yul::Dialect const& dialect() const { return m_dialect; }
yul::Block const& operations() const { return *m_operations; }
InlineAssemblyAnnotation& annotation() const override;
private:
yul::Dialect const& m_dialect;
std::shared_ptr<yul::Block> m_operations;
};
+3 -2
View File
@@ -35,8 +35,9 @@
namespace yul
{
struct AsmAnalysisInfo;
struct Identifier;
struct AsmAnalysisInfo;
struct Identifier;
struct Dialect;
}
namespace dev
@@ -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,14 +51,21 @@ 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
{
return yul::YulString{"usr$" + _name.str()};
// 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()};
}
yul::Identifier translate(yul::Identifier const& _identifier) override
@@ -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());
+1 -1
View File
@@ -217,7 +217,7 @@ bool CompilerStack::parse()
string const& path = sourcesToParse[i];
Source& source = m_sources[path];
source.scanner->reset();
source.ast = Parser(m_errorReporter).parse(source.scanner);
source.ast = Parser(m_errorReporter, m_evmVersion).parse(source.scanner);
if (!source.ast)
solAssert(!Error::containsOnlyWarnings(m_errorReporter.errors()), "Parser returned null but did not report error.");
else
+5 -3
View File
@@ -29,6 +29,7 @@
#include <liblangutil/Scanner.h>
#include <liblangutil/SemVerHandler.h>
#include <liblangutil/SourceLocation.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <cctype>
#include <vector>
@@ -1039,21 +1040,22 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
SourceLocation location{position(), -1, source()};
expectToken(Token::Assembly);
yul::Dialect const& dialect = yul::EVMDialect::looseAssemblyForEVM(m_evmVersion);
if (m_scanner->currentToken() == Token::StringLiteral)
{
if (m_scanner->currentLiteral() != "evmasm")
fatalParserError("Only \"evmasm\" supported.");
// This can be used in the future to set the dialect.
m_scanner->next();
}
// Using latest EVM Version for now, it will be run again later.
yul::Parser asmParser(m_errorReporter, yul::EVMDialect::looseAssemblyForEVM(EVMVersion{}));
yul::Parser asmParser(m_errorReporter, dialect);
shared_ptr<yul::Block> block = asmParser.parse(m_scanner, true);
if (block == nullptr)
BOOST_THROW_EXCEPTION(FatalError());
location.end = block->location.end;
return make_shared<InlineAssembly>(location, _docString, block);
return make_shared<InlineAssembly>(location, _docString, dialect, block);
}
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
+9 -1
View File
@@ -24,6 +24,7 @@
#include <libsolidity/ast/AST.h>
#include <liblangutil/ParserBase.h>
#include <liblangutil/EVMVersion.h>
namespace langutil
{
@@ -38,7 +39,13 @@ namespace solidity
class Parser: public langutil::ParserBase
{
public:
explicit Parser(langutil::ErrorReporter& _errorReporter): ParserBase(_errorReporter) {}
explicit Parser(
langutil::ErrorReporter& _errorReporter,
langutil::EVMVersion _evmVersion
):
ParserBase(_errorReporter),
m_evmVersion(_evmVersion)
{}
ASTPointer<SourceUnit> parse(std::shared_ptr<langutil::Scanner> const& _scanner);
@@ -181,6 +188,7 @@ private:
/// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier.
bool m_insideModifier = false;
langutil::EVMVersion m_evmVersion;
};
}