aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-03-22 02:38:37 +0800
committerchriseth <chris@ethereum.org>2017-04-25 22:49:03 +0800
commitc6fa78c73e3a23661014fd03b92d74d2e7df9e81 (patch)
tree7ad6f3ff22eb5bccd72cd868d153f0370203783a
parente0849f2f3bbb23ebddb37cd770f46266967e789d (diff)
downloaddexon-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.cpp10
-rw-r--r--libsolidity/analysis/TypeChecker.cpp11
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp24
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h8
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp15
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.h3
-rw-r--r--libsolidity/inlineasm/AsmStack.cpp7
-rw-r--r--libsolidity/inlineasm/AsmStack.h11
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp2
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)