diff options
author | chriseth <chris@ethereum.org> | 2017-03-22 02:38:37 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2017-04-25 22:49:03 +0800 |
commit | c6fa78c73e3a23661014fd03b92d74d2e7df9e81 (patch) | |
tree | 7ad6f3ff22eb5bccd72cd868d153f0370203783a | |
parent | e0849f2f3bbb23ebddb37cd770f46266967e789d (diff) | |
download | dexon-solidity-c6fa78c73e3a23661014fd03b92d74d2e7df9e81.tar.gz dexon-solidity-c6fa78c73e3a23661014fd03b92d74d2e7df9e81.tar.zst dexon-solidity-c6fa78c73e3a23661014fd03b92d74d2e7df9e81.zip |
Use actual type checking phase of assembler.
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 10 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 11 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 24 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 8 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 15 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.h | 3 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmStack.cpp | 7 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmStack.h | 11 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 2 |
9 files changed, 49 insertions, 42 deletions
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 5ff4ee2d..a50fc6a0 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -25,7 +25,7 @@ #include <libsolidity/analysis/NameAndTypeResolver.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/analysis/ConstantEvaluator.h> -#include <libsolidity/inlineasm/AsmCodeGen.h> +#include <libsolidity/inlineasm/AsmAnalysis.h> #include <libsolidity/inlineasm/AsmData.h> using namespace std; @@ -163,9 +163,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) // The only purpose of this step is to fill the inline assembly annotation with // external references. ErrorList errorsIgnored; - assembly::CodeGenerator codeGen(_inlineAssembly.operations(), errorsIgnored); - assembly::ExternalIdentifierAccess identifierAccess; - identifierAccess.resolve = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext) { + assembly::ExternalIdentifierAccess::Resolver resolver = + [&](assembly::Identifier const& _identifier, assembly::IdentifierContext) { auto declarations = m_resolver.nameFromCurrentScope(_identifier.name); if (declarations.size() != 1) return size_t(-1); @@ -173,7 +172,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) // At this stage we do not yet know the stack size of the identifier, so we just return 1. return size_t(1); }; - codeGen.typeCheck(identifierAccess); + assembly::AsmAnalyzer::Scopes scopes; + assembly::AsmAnalyzer(scopes, errorsIgnored, resolver).analyze(_inlineAssembly.operations()); return false; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 808914ae..11c27238 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -24,8 +24,7 @@ #include <memory> #include <boost/range/adaptor/reversed.hpp> #include <libsolidity/ast/AST.h> -#include <libevmasm/Assembly.h> // needed for inline assembly -#include <libsolidity/inlineasm/AsmCodeGen.h> +#include <libsolidity/inlineasm/AsmAnalysis.h> using namespace std; using namespace dev; @@ -630,8 +629,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) { // External references have already been resolved in a prior stage and stored in the annotation. // We run the resolve step again regardless. - assembly::ExternalIdentifierAccess identifierAccess; - identifierAccess.resolve = [&]( + assembly::ExternalIdentifierAccess::Resolver identifierAccess = [&]( assembly::Identifier const& _identifier, assembly::IdentifierContext _context ) @@ -682,8 +680,9 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) ref->second.valueSize = valueSize; return valueSize; }; - assembly::CodeGenerator codeGen(_inlineAssembly.operations(), m_errors); - if (!codeGen.typeCheck(identifierAccess)) + assembly::AsmAnalyzer::Scopes scopes; + assembly::AsmAnalyzer analyzer(scopes, m_errors, identifierAccess); + if (!analyzer.analyze(_inlineAssembly.operations())) return false; return true; } diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 51105ad2..ec562419 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -38,8 +38,12 @@ using namespace dev::solidity; using namespace dev::solidity::assembly; -AsmAnalyzer::AsmAnalyzer(AsmAnalyzer::Scopes& _scopes, ErrorList& _errors, bool _allowFailedLookups): - m_allowFailedLookups(_allowFailedLookups), m_scopes(_scopes), m_errors(_errors) +AsmAnalyzer::AsmAnalyzer( + AsmAnalyzer::Scopes& _scopes, + ErrorList& _errors, + ExternalIdentifierAccess::Resolver const& _resolver +): + m_resolver(_resolver), m_scopes(_scopes), m_errors(_errors) { } @@ -92,7 +96,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) ))) { } - else if (!m_allowFailedLookups) + else if (!m_resolver || m_resolver(_identifier, IdentifierContext::RValue) == size_t(-1)) { m_errors.push_back(make_shared<Error>( Error::Type::DeclarationError, @@ -223,10 +227,11 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable) { if (!(*this)(_variable)) return false; - else if (!m_allowFailedLookups) + + if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name)) { // Check that it is a variable - if (m_currentScope->lookup(_variable.name)->type() != typeid(Scope::Variable)) + if (var->type() != typeid(Scope::Variable)) { m_errors.push_back(make_shared<Error>( Error::Type::TypeError, @@ -236,6 +241,15 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable) return false; } } + else if (!m_resolver || m_resolver(_variable, IdentifierContext::LValue) == size_t(-1)) + { + m_errors.push_back(make_shared<Error>( + Error::Type::DeclarationError, + "Variable not found.", + _variable.location + )); + return false; + } return true; } diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index c81b7a82..c6d23227 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -20,6 +20,8 @@ #pragma once +#include <libsolidity/inlineasm/AsmStack.h> + #include <libsolidity/interface/Exceptions.h> #include <boost/variant.hpp> @@ -57,9 +59,7 @@ class AsmAnalyzer: public boost::static_visitor<bool> { public: using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; - /// @param _allowFailedLookups if true, allow failed lookups for variables (they - /// will be provided from the environment later on) - AsmAnalyzer(Scopes& _scopes, ErrorList& _errors, bool _allowFailedLookups); + AsmAnalyzer(Scopes& _scopes, ErrorList& _errors, ExternalIdentifierAccess::Resolver const& _resolver); bool analyze(assembly::Block const& _block); @@ -79,7 +79,7 @@ private: bool checkAssignment(assembly::Identifier const& _assignment); Scope& scope(assembly::Block const* _block); - bool m_allowFailedLookups = false; + ExternalIdentifierAccess::Resolver const& m_resolver; Scope* m_currentScope = nullptr; Scopes& m_scopes; ErrorList& m_errors; diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index d094aa97..c1efa292 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -308,22 +308,11 @@ private: ExternalIdentifierAccess m_identifierAccess; }; -bool assembly::CodeGenerator::typeCheck(ExternalIdentifierAccess const& _identifierAccess) -{ - size_t initialErrorLen = m_errors.size(); - eth::Assembly assembly; - GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) - return false; - CodeTransform(state, m_parsedData, _identifierAccess); - return m_errors.size() == initialErrorLen; -} - eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& _identifierAccess) { eth::Assembly assembly; GeneratorState state(m_errors, assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); return assembly; @@ -332,7 +321,7 @@ eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess) { GeneratorState state(m_errors, _assembly); - if (!(AsmAnalyzer(state.scopes, m_errors, !!_identifierAccess.resolve)).analyze(m_parsedData)) + if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) solAssert(false, "Assembly error"); CodeTransform(state, m_parsedData, _identifierAccess); } diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h index f259a36c..ed61a7eb 100644 --- a/libsolidity/inlineasm/AsmCodeGen.h +++ b/libsolidity/inlineasm/AsmCodeGen.h @@ -44,9 +44,6 @@ class CodeGenerator public: CodeGenerator(Block const& _parsedData, ErrorList& _errors): m_parsedData(_parsedData), m_errors(_errors) {} - /// Performs type checks and @returns false on error. - /// Actually runs the full code generation but discards the result. - bool typeCheck(ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()); /// Performs code generation and @returns the result. eth::Assembly assemble(ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()); /// Performs code generation and appends generated to to _assembly. diff --git a/libsolidity/inlineasm/AsmStack.cpp b/libsolidity/inlineasm/AsmStack.cpp index 09084642..146fc114 100644 --- a/libsolidity/inlineasm/AsmStack.cpp +++ b/libsolidity/inlineasm/AsmStack.cpp @@ -39,7 +39,10 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::assembly; -bool InlineAssemblyStack::parse(shared_ptr<Scanner> const& _scanner) +bool InlineAssemblyStack::parse( + shared_ptr<Scanner> const& _scanner, + ExternalIdentifierAccess::Resolver const& _resolver +) { m_parserResult = make_shared<Block>(); Parser parser(m_errors); @@ -49,7 +52,7 @@ bool InlineAssemblyStack::parse(shared_ptr<Scanner> const& _scanner) *m_parserResult = std::move(*result); AsmAnalyzer::Scopes scopes; - return (AsmAnalyzer(scopes, m_errors, false)).analyze(*m_parserResult); + return (AsmAnalyzer(scopes, m_errors, _resolver)).analyze(*m_parserResult); } string InlineAssemblyStack::toString() diff --git a/libsolidity/inlineasm/AsmStack.h b/libsolidity/inlineasm/AsmStack.h index b6e4952a..77a7e02a 100644 --- a/libsolidity/inlineasm/AsmStack.h +++ b/libsolidity/inlineasm/AsmStack.h @@ -47,13 +47,15 @@ enum class IdentifierContext { LValue, RValue }; /// to inline assembly (not used in standalone assembly mode). struct ExternalIdentifierAccess { + using Resolver = std::function<size_t(assembly::Identifier const&, IdentifierContext)>; /// Resolve a an external reference given by the identifier in the given context. /// @returns the size of the value (number of stack slots) or size_t(-1) if not found. - std::function<size_t(assembly::Identifier const&, IdentifierContext)> resolve; + Resolver resolve; + using CodeGenerator = std::function<void(assembly::Identifier const&, IdentifierContext, eth::Assembly&)>; /// Generate code for retrieving the value (rvalue context) or storing the value (lvalue context) /// of an identifier. The code should be appended to the assembly. In rvalue context, the value is supposed /// to be put onto the stack, in lvalue context, the value is assumed to be at the top of the stack. - std::function<void(assembly::Identifier const&, IdentifierContext, eth::Assembly&)> generateCode; + CodeGenerator generateCode; }; class InlineAssemblyStack @@ -61,7 +63,10 @@ class InlineAssemblyStack public: /// Parse the given inline assembly chunk starting with `{` and ending with the corresponding `}`. /// @return false or error. - bool parse(std::shared_ptr<Scanner> const& _scanner); + bool parse( + std::shared_ptr<Scanner> const& _scanner, + ExternalIdentifierAccess::Resolver const& _externalIdentifierResolver = ExternalIdentifierAccess::Resolver() + ); /// Converts the parser result back into a string form (not necessarily the same form /// as the source form, but it should parse into the same parsed form again). std::string toString(); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index b98c3706..2bd9decf 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -5058,7 +5058,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage) } } )"; - CHECK_ERROR(text, DeclarationError, "not found, not unique or not lvalue."); + CHECK_ERROR(text, DeclarationError, "Variable not found."); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) |