mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move analysis out of code generator.
This commit is contained in:
parent
4afd54b235
commit
dfb7d5ebd9
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
);
|
);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user