Move analysis out of code generator.

This commit is contained in:
chriseth 2017-04-12 18:32:25 +02:00
parent 4afd54b235
commit dfb7d5ebd9
7 changed files with 55 additions and 26 deletions

View File

@ -692,8 +692,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
ref->second.valueSize = 1; ref->second.valueSize = 1;
return size_t(1); return size_t(1);
}; };
assembly::AsmAnalyzer::Scopes scopes; solAssert(_inlineAssembly.annotation().scopes.empty(), "");
assembly::AsmAnalyzer analyzer(scopes, m_errors, identifierAccess); assembly::AsmAnalyzer analyzer(_inlineAssembly.annotation().scopes, m_errors, identifierAccess);
if (!analyzer.analyze(_inlineAssembly.operations())) if (!analyzer.analyze(_inlineAssembly.operations()))
return false; return false;
return true; return true;

View File

@ -113,6 +113,8 @@ struct StatementAnnotation: ASTAnnotation, DocumentedAnnotation
namespace assembly namespace assembly
{ {
struct Identifier; // forward struct Identifier; // forward
struct Block; // forward
struct Scope; // forward
} }
struct InlineAssemblyAnnotation: StatementAnnotation struct InlineAssemblyAnnotation: StatementAnnotation
@ -125,6 +127,8 @@ struct InlineAssemblyAnnotation: StatementAnnotation
/// Mapping containing resolved references to external identifiers and their value size /// Mapping containing resolved references to external identifiers and their value size
std::map<assembly::Identifier const*, ExternalIdentifierInfo> externalReferences; std::map<assembly::Identifier const*, ExternalIdentifierInfo> externalReferences;
/// Mapping containing the scopes (the result of the analysis phase).
std::map<assembly::Block const*, std::shared_ptr<assembly::Scope>> scopes;
}; };
struct ReturnAnnotation: StatementAnnotation struct ReturnAnnotation: StatementAnnotation

View File

@ -520,7 +520,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{ {
ErrorList errors; ErrorList errors;
assembly::CodeGenerator codeGen(_inlineAssembly.operations(), errors); assembly::CodeGenerator codeGen(errors);
unsigned startStackHeight = m_context.stackHeight(); unsigned startStackHeight = m_context.stackHeight();
assembly::ExternalIdentifierAccess identifierAccess; assembly::ExternalIdentifierAccess identifierAccess;
identifierAccess.resolve = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext) identifierAccess.resolve = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext)
@ -598,6 +598,8 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
} }
}; };
codeGen.assemble( codeGen.assemble(
_inlineAssembly.operations(),
_inlineAssembly.annotation().scopes,
m_context.nonConstAssembly(), m_context.nonConstAssembly(),
identifierAccess identifierAccess
); );

View File

@ -59,7 +59,11 @@ class AsmAnalyzer: public boost::static_visitor<bool>
{ {
public: public:
using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>;
AsmAnalyzer(Scopes& _scopes, ErrorList& _errors, ExternalIdentifierAccess::Resolver const& _resolver); AsmAnalyzer(
Scopes& _scopes,
ErrorList& _errors,
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver()
);
bool analyze(assembly::Block const& _block); bool analyze(assembly::Block const& _block);

View File

@ -47,8 +47,8 @@ using namespace dev::solidity::assembly;
struct GeneratorState struct GeneratorState
{ {
GeneratorState(ErrorList& _errors, eth::Assembly& _assembly): GeneratorState(ErrorList& _errors, AsmAnalyzer::Scopes& _scopes, eth::Assembly& _assembly):
errors(_errors), assembly(_assembly) {} errors(_errors), scopes(_scopes), assembly(_assembly) {}
size_t newLabelId() size_t newLabelId()
{ {
@ -62,8 +62,8 @@ struct GeneratorState
return size_t(id); return size_t(id);
} }
AsmAnalyzer::Scopes scopes;
ErrorList& errors; ErrorList& errors;
AsmAnalyzer::Scopes scopes;
eth::Assembly& assembly; eth::Assembly& assembly;
}; };
@ -260,20 +260,25 @@ private:
ExternalIdentifierAccess m_identifierAccess; ExternalIdentifierAccess m_identifierAccess;
}; };
eth::Assembly assembly::CodeGenerator::assemble(ExternalIdentifierAccess const& _identifierAccess) eth::Assembly assembly::CodeGenerator::assemble(
Block const& _parsedData,
AsmAnalyzer::Scopes& _scopes,
ExternalIdentifierAccess const& _identifierAccess
)
{ {
eth::Assembly assembly; eth::Assembly assembly;
GeneratorState state(m_errors, assembly); GeneratorState state(m_errors, _scopes, assembly);
if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) CodeTransform(state, _parsedData, _identifierAccess);
solAssert(false, "Assembly error");
CodeTransform(state, m_parsedData, _identifierAccess);
return assembly; return assembly;
} }
void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess) void assembly::CodeGenerator::assemble(
Block const& _parsedData,
AsmAnalyzer::Scopes& _scopes,
eth::Assembly& _assembly,
ExternalIdentifierAccess const& _identifierAccess
)
{ {
GeneratorState state(m_errors, _assembly); GeneratorState state(m_errors, _scopes, _assembly);
if (!(AsmAnalyzer(state.scopes, m_errors, _identifierAccess.resolve)).analyze(m_parsedData)) CodeTransform(state, _parsedData, _identifierAccess);
solAssert(false, "Assembly error");
CodeTransform(state, m_parsedData, _identifierAccess);
} }

View File

@ -22,8 +22,8 @@
#pragma once #pragma once
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/Exceptions.h>
#include <libsolidity/inlineasm/AsmStack.h>
#include <functional> #include <functional>
@ -42,15 +42,23 @@ struct Block;
class CodeGenerator class CodeGenerator
{ {
public: public:
CodeGenerator(Block const& _parsedData, ErrorList& _errors): CodeGenerator(ErrorList& _errors):
m_parsedData(_parsedData), m_errors(_errors) {} m_errors(_errors) {}
/// Performs code generation and @returns the result. /// Performs code generation and @returns the result.
eth::Assembly assemble(ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()); eth::Assembly assemble(
Block const& _parsedData,
AsmAnalyzer::Scopes& _scopes,
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
);
/// Performs code generation and appends generated to to _assembly. /// Performs code generation and appends generated to to _assembly.
void assemble(eth::Assembly& _assembly, ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()); void assemble(
Block const& _parsedData,
AsmAnalyzer::Scopes& _scopes,
eth::Assembly& _assembly,
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
);
private: private:
Block const& m_parsedData;
ErrorList& m_errors; ErrorList& m_errors;
}; };

View File

@ -62,8 +62,11 @@ string InlineAssemblyStack::toString()
eth::Assembly InlineAssemblyStack::assemble() eth::Assembly InlineAssemblyStack::assemble()
{ {
CodeGenerator codeGen(*m_parserResult, m_errors); AsmAnalyzer::Scopes scopes;
return codeGen.assemble(); AsmAnalyzer analyzer(scopes, m_errors);
solAssert(analyzer.analyze(*m_parserResult), "");
CodeGenerator codeGen(m_errors);
return codeGen.assemble(*m_parserResult, scopes);
} }
bool InlineAssemblyStack::parseAndAssemble( bool InlineAssemblyStack::parseAndAssemble(
@ -78,7 +81,10 @@ bool InlineAssemblyStack::parseAndAssemble(
if (!errors.empty()) if (!errors.empty())
return false; return false;
CodeGenerator(*parserResult, errors).assemble(_assembly, _identifierAccess); AsmAnalyzer::Scopes scopes;
AsmAnalyzer analyzer(scopes, m_errors);
solAssert(analyzer.analyze(*m_parserResult), "");
CodeGenerator(errors).assemble(*parserResult, scopes, _assembly, _identifierAccess);
// At this point, the assembly might be messed up, but we should throw an // At this point, the assembly might be messed up, but we should throw an
// internal compiler error anyway. // internal compiler error anyway.