From 99db4e3ff45c2a8d5d9c645774f099b82b7618ec Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 3 Dec 2018 15:49:23 +0100 Subject: [PATCH] Introduce the concept of builtin functions. --- libsolidity/analysis/ReferencesResolver.cpp | 9 ++- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/codegen/CompilerContext.cpp | 4 +- libsolidity/interface/AssemblyStack.cpp | 14 ++-- libyul/AsmAnalysis.cpp | 14 ++-- libyul/AsmAnalysis.h | 10 +-- libyul/AsmDataForward.h | 7 -- libyul/AsmParser.cpp | 26 +++---- libyul/AsmParser.h | 13 ++-- libyul/Dialect.h | 82 +++++++++++++++++++++ libyul/ObjectParser.cpp | 2 +- libyul/ObjectParser.h | 7 +- test/libyul/Common.cpp | 6 +- test/libyul/Parser.cpp | 4 +- test/libyul/YulOptimizerTest.cpp | 6 +- test/tools/yulopti.cpp | 4 +- 16 files changed, 148 insertions(+), 62 deletions(-) create mode 100644 libyul/Dialect.h diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index c4931d980..ac88a052b 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -316,7 +316,14 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) // We use the latest EVM version because we will re-run it anyway. yul::AsmAnalysisInfo analysisInfo; boost::optional errorTypeForLoose = Error::Type::SyntaxError; - yul::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), errorTypeForLoose, yul::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations()); + yul::AsmAnalyzer( + analysisInfo, + errorsIgnored, + EVMVersion(), + errorTypeForLoose, + yul::Dialect::looseAssemblyForEVM(), + resolver + ).analyze(_inlineAssembly.operations()); return false; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9350df059..5c8e0c6c4 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -658,7 +658,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) m_errorReporter, m_evmVersion, Error::Type::SyntaxError, - yul::AsmFlavour::Loose, + yul::Dialect::looseAssemblyForEVM(), identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 5a3a233ca..039738a63 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -361,7 +361,7 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = make_shared(langutil::CharStream(_assembly, "--CODEGEN--")); - auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); + auto parserResult = yul::Parser(errorReporter, yul::Dialect::strictAssemblyForEVM()).parse(scanner, false); #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter()(*parserResult) << endl; #endif @@ -373,7 +373,7 @@ void CompilerContext::appendInlineAssembly( errorReporter, m_evmVersion, boost::none, - yul::AsmFlavour::Strict, + yul::Dialect::strictAssemblyForEVM(), identifierAccess.resolve ).analyze(*parserResult); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index f5eb7e412..ff345089d 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -43,19 +43,19 @@ using namespace dev::solidity; namespace { -yul::AsmFlavour languageToAsmFlavour(AssemblyStack::Language _language) +yul::Dialect languageToDialect(AssemblyStack::Language _language) { switch (_language) { case AssemblyStack::Language::Assembly: - return yul::AsmFlavour::Loose; + return yul::Dialect::looseAssemblyForEVM(); case AssemblyStack::Language::StrictAssembly: - return yul::AsmFlavour::Strict; + return yul::Dialect::strictAssemblyForEVM(); case AssemblyStack::Language::Yul: - return yul::AsmFlavour::Yul; + return yul::Dialect::yul(); } solAssert(false, ""); - return yul::AsmFlavour::Yul; + return yul::Dialect::yul(); } } @@ -72,7 +72,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string m_errors.clear(); m_analysisSuccessful = false; m_scanner = make_shared(CharStream(_source, _sourceName)); - m_parserResult = yul::ObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); + m_parserResult = yul::ObjectParser(m_errorReporter, languageToDialect(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; solAssert(m_parserResult, ""); @@ -93,7 +93,7 @@ bool AssemblyStack::analyzeParsed() solAssert(m_parserResult, ""); solAssert(m_parserResult->code, ""); m_parserResult->analysisInfo = make_shared(); - yul::AsmAnalyzer analyzer(*m_parserResult->analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language)); + yul::AsmAnalyzer analyzer(*m_parserResult->analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToDialect(m_language)); m_analysisSuccessful = analyzer.analyze(*m_parserResult->code); return m_analysisSuccessful; } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index d2efdd9f6..5215e5c28 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -101,7 +101,7 @@ bool AsmAnalyzer::operator()(Literal const& _literal) } else if (_literal.kind == LiteralKind::Boolean) { - solAssert(m_flavour == AsmFlavour::Yul, ""); + solAssert(m_dialect.flavour == AsmFlavour::Yul, ""); solAssert(_literal.value == YulString{string("true")} || _literal.value == YulString{string("false")}, ""); } m_info.stackHeightInfo[&_literal] = m_stackHeight; @@ -164,7 +164,7 @@ bool AsmAnalyzer::operator()(Identifier const& _identifier) bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr) { - solAssert(m_flavour != AsmFlavour::Yul, ""); + solAssert(m_dialect.flavour != AsmFlavour::Yul, ""); bool success = true; for (auto const& arg: _instr.arguments | boost::adaptors::reversed) if (!expectExpression(arg)) @@ -182,9 +182,9 @@ bool AsmAnalyzer::operator()(ExpressionStatement const& _statement) { int initialStackHeight = m_stackHeight; bool success = boost::apply_visitor(*this, _statement.expression); - if (m_stackHeight != initialStackHeight && (m_flavour != AsmFlavour::Loose || m_errorTypeForLoose)) + if (m_stackHeight != initialStackHeight && (m_dialect.flavour != AsmFlavour::Loose || m_errorTypeForLoose)) { - Error::Type errorType = m_flavour == AsmFlavour::Loose ? *m_errorTypeForLoose : Error::Type::TypeError; + Error::Type errorType = m_dialect.flavour == AsmFlavour::Loose ? *m_errorTypeForLoose : Error::Type::TypeError; string msg = "Top-level expressions are not supposed to return values (this expression returns " + to_string(m_stackHeight - initialStackHeight) + @@ -563,7 +563,7 @@ Scope& AsmAnalyzer::scope(Block const* _block) } void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _location) { - if (m_flavour != AsmFlavour::Yul) + if (m_dialect.flavour != AsmFlavour::Yul) return; if (!builtinTypes.count(type)) @@ -623,7 +623,7 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio if (_instr == solidity::Instruction::JUMP || _instr == solidity::Instruction::JUMPI || _instr == solidity::Instruction::JUMPDEST) { - solAssert(m_flavour == AsmFlavour::Loose, ""); + solAssert(m_dialect.flavour == AsmFlavour::Loose, ""); m_errorReporter.error( m_errorTypeForLoose ? *m_errorTypeForLoose : Error::Type::Warning, _location, @@ -636,7 +636,7 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio void AsmAnalyzer::checkLooseFeature(SourceLocation const& _location, string const& _description) { - if (m_flavour != AsmFlavour::Loose) + if (m_dialect.flavour != AsmFlavour::Loose) solAssert(false, _description); else if (m_errorTypeForLoose) m_errorReporter.error(*m_errorTypeForLoose, _location, _description); diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 34e32eb01..ec2b88686 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -23,12 +23,12 @@ #include #include +#include #include +#include #include -#include - #include #include @@ -59,14 +59,14 @@ public: langutil::ErrorReporter& _errorReporter, dev::solidity::EVMVersion _evmVersion, boost::optional _errorTypeForLoose, - AsmFlavour _flavour = AsmFlavour::Loose, + Dialect _dialect = Dialect::looseAssemblyForEVM(), ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() ): m_resolver(_resolver), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_evmVersion(_evmVersion), - m_flavour(_flavour), + m_dialect(std::move(_dialect)), m_errorTypeForLoose(_errorTypeForLoose) {} @@ -115,7 +115,7 @@ private: AsmAnalysisInfo& m_info; langutil::ErrorReporter& m_errorReporter; dev::solidity::EVMVersion m_evmVersion; - AsmFlavour m_flavour = AsmFlavour::Loose; + Dialect m_dialect = Dialect::looseAssemblyForEVM(); boost::optional m_errorTypeForLoose; }; diff --git a/libyul/AsmDataForward.h b/libyul/AsmDataForward.h index 046c82487..de5644252 100644 --- a/libyul/AsmDataForward.h +++ b/libyul/AsmDataForward.h @@ -49,11 +49,4 @@ struct TypedName; using Expression = boost::variant; using Statement = boost::variant; -enum class AsmFlavour -{ - Loose, // no types, EVM instructions as function, jumps and direct stack manipulations - Strict, // no types, EVM instructions as functions, but no jumps and no direct stack manipulations - Yul // same as Strict mode with types -}; - } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 417c02516..5f393b29f 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -107,7 +107,7 @@ Statement Parser::parseStatement() return parseForLoop(); case Token::Assign: { - if (m_flavour != AsmFlavour::Loose) + if (m_dialect.flavour != AsmFlavour::Loose) break; StackAssignment assignment = createWithLocation(); advance(); @@ -174,7 +174,7 @@ Statement Parser::parseStatement() if (currentToken() == Token::Assign && peekNextToken() != Token::Colon) { Assignment assignment = createWithLocation(identifier.location); - if (m_flavour != AsmFlavour::Yul && instructions().count(identifier.name.str())) + if (m_dialect.flavour != AsmFlavour::Yul && instructions().count(identifier.name.str())) fatalParserError("Cannot use instruction names for identifier names."); advance(); assignment.variableNames.emplace_back(identifier); @@ -185,7 +185,7 @@ Statement Parser::parseStatement() else { // label - if (m_flavour != AsmFlavour::Loose) + if (m_dialect.flavour != AsmFlavour::Loose) fatalParserError("Labels are not supported."); Label label = createWithLocation