Remove error reporter from code generation phase.

This commit is contained in:
chriseth 2017-06-06 15:37:43 +02:00
parent 19f707aeaa
commit ef3d5874fe
8 changed files with 29 additions and 45 deletions

View File

@ -73,14 +73,14 @@ void CodeTransform::operator()(Assignment const& _assignment)
{ {
visitExpression(*_assignment.value); visitExpression(*_assignment.value);
m_assembly.setSourceLocation(_assignment.location); m_assembly.setSourceLocation(_assignment.location);
generateAssignment(_assignment.variableName, _assignment.location); generateAssignment(_assignment.variableName);
checkStackHeight(&_assignment); checkStackHeight(&_assignment);
} }
void CodeTransform::operator()(StackAssignment const& _assignment) void CodeTransform::operator()(StackAssignment const& _assignment)
{ {
m_assembly.setSourceLocation(_assignment.location); m_assembly.setSourceLocation(_assignment.location);
generateAssignment(_assignment.variableName, _assignment.location); generateAssignment(_assignment.variableName);
checkStackHeight(&_assignment); checkStackHeight(&_assignment);
} }
@ -172,7 +172,7 @@ void CodeTransform::operator()(assembly::Identifier const& _identifier)
if (m_scope->lookup(_identifier.name, Scope::NonconstVisitor( if (m_scope->lookup(_identifier.name, Scope::NonconstVisitor(
[=](Scope::Variable& _var) [=](Scope::Variable& _var)
{ {
if (int heightDiff = variableHeightDiff(_var, _identifier.location, false)) if (int heightDiff = variableHeightDiff(_var, false))
m_assembly.appendInstruction(solidity::dupInstruction(heightDiff)); m_assembly.appendInstruction(solidity::dupInstruction(heightDiff));
else else
// Store something to balance the stack // Store something to balance the stack
@ -320,7 +320,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_assembly.appendConstant(u256(0)); m_assembly.appendConstant(u256(0));
} }
CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment) CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment)
.run(_function.body); .run(_function.body);
{ {
@ -366,7 +366,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
void CodeTransform::operator()(Block const& _block) void CodeTransform::operator()(Block const& _block)
{ {
CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block); CodeTransform(m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block);
} }
AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier) AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier)
@ -394,14 +394,14 @@ void CodeTransform::visitExpression(Statement const& _expression)
expectDeposit(1, height); expectDeposit(1, height);
} }
void CodeTransform::generateAssignment(Identifier const& _variableName, SourceLocation const& _location) void CodeTransform::generateAssignment(Identifier const& _variableName)
{ {
solAssert(m_scope, ""); solAssert(m_scope, "");
auto var = m_scope->lookup(_variableName.name); auto var = m_scope->lookup(_variableName.name);
if (var) if (var)
{ {
Scope::Variable const& _var = boost::get<Scope::Variable>(*var); Scope::Variable const& _var = boost::get<Scope::Variable>(*var);
if (int heightDiff = variableHeightDiff(_var, _location, true)) if (int heightDiff = variableHeightDiff(_var, true))
m_assembly.appendInstruction(solidity::swapInstruction(heightDiff - 1)); m_assembly.appendInstruction(solidity::swapInstruction(heightDiff - 1));
m_assembly.appendInstruction(solidity::Instruction::POP); m_assembly.appendInstruction(solidity::Instruction::POP);
} }
@ -415,14 +415,12 @@ void CodeTransform::generateAssignment(Identifier const& _variableName, SourceLo
} }
} }
int CodeTransform::variableHeightDiff(solidity::assembly::Scope::Variable const& _var, SourceLocation const& _location, bool _forSwap) int CodeTransform::variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap)
{ {
int heightDiff = m_assembly.stackHeight() - _var.stackHeight; int heightDiff = m_assembly.stackHeight() - _var.stackHeight;
if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16)) if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16))
{ {
//@TODO move this to analysis phase. solUnimplemented(
m_errorReporter.typeError(
_location,
"Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")" "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")"
); );
return 0; return 0;

View File

@ -61,12 +61,11 @@ public:
/// Create the code transformer. /// Create the code transformer.
/// @param _identifierAccess used to resolve identifiers external to the inline assembly /// @param _identifierAccess used to resolve identifiers external to the inline assembly
CodeTransform( CodeTransform(
solidity::ErrorReporter& _errorReporter,
julia::AbstractAssembly& _assembly, julia::AbstractAssembly& _assembly,
solidity::assembly::AsmAnalysisInfo& _analysisInfo, solidity::assembly::AsmAnalysisInfo& _analysisInfo,
bool _evm15 = false, bool _evm15 = false,
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess() ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
): CodeTransform(_errorReporter, _assembly, _analysisInfo, _evm15, _identifierAccess, _assembly.stackHeight()) ): CodeTransform(_assembly, _analysisInfo, _evm15, _identifierAccess, _assembly.stackHeight())
{ {
} }
@ -75,14 +74,12 @@ public:
protected: protected:
CodeTransform( CodeTransform(
solidity::ErrorReporter& _errorReporter,
julia::AbstractAssembly& _assembly, julia::AbstractAssembly& _assembly,
solidity::assembly::AsmAnalysisInfo& _analysisInfo, solidity::assembly::AsmAnalysisInfo& _analysisInfo,
bool _evm15, bool _evm15,
ExternalIdentifierAccess const& _identifierAccess, ExternalIdentifierAccess const& _identifierAccess,
int _stackAdjustment int _stackAdjustment
): ):
m_errorReporter(_errorReporter),
m_assembly(_assembly), m_assembly(_assembly),
m_info(_analysisInfo), m_info(_analysisInfo),
m_evm15(_evm15), m_evm15(_evm15),
@ -109,12 +106,12 @@ private:
/// Generates code for an expression that is supposed to return a single value. /// Generates code for an expression that is supposed to return a single value.
void visitExpression(solidity::assembly::Statement const& _expression); void visitExpression(solidity::assembly::Statement const& _expression);
void generateAssignment(solidity::assembly::Identifier const& _variableName, SourceLocation const& _location); void generateAssignment(solidity::assembly::Identifier const& _variableName);
/// Determines the stack height difference to the given variables. Automatically generates /// Determines the stack height difference to the given variables. Throws
/// errors if it is not yet in scope or the height difference is too large. Returns 0 on /// if it is not yet in scope or the height difference is too large. Returns
/// errors and the (positive) stack height difference otherwise. /// the (positive) stack height difference otherwise.
int variableHeightDiff(solidity::assembly::Scope::Variable const& _var, SourceLocation const& _location, bool _forSwap); int variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap);
void expectDeposit(int _deposit, int _oldHeight); void expectDeposit(int _deposit, int _oldHeight);
@ -123,7 +120,6 @@ private:
/// Assigns the label's or function's id to a value taken from eth::Assembly if it has not yet been set. /// Assigns the label's or function's id to a value taken from eth::Assembly if it has not yet been set.
void assignLabelIdIfUnset(boost::optional<AbstractAssembly::LabelID>& _labelId); void assignLabelIdIfUnset(boost::optional<AbstractAssembly::LabelID>& _labelId);
solidity::ErrorReporter& m_errorReporter;
julia::AbstractAssembly& m_assembly; julia::AbstractAssembly& m_assembly;
solidity::assembly::AsmAnalysisInfo& m_info; solidity::assembly::AsmAnalysisInfo& m_info;
solidity::assembly::Scope* m_scope = nullptr; solidity::assembly::Scope* m_scope = nullptr;

View File

@ -524,9 +524,6 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{ {
ErrorList errors;
ErrorReporter errorReporter(errors);
assembly::CodeGenerator codeGen(errorReporter);
unsigned startStackHeight = m_context.stackHeight(); unsigned startStackHeight = m_context.stackHeight();
julia::ExternalIdentifierAccess identifierAccess; julia::ExternalIdentifierAccess identifierAccess;
identifierAccess.resolve = [&](assembly::Identifier const& _identifier, julia::IdentifierContext, bool) identifierAccess.resolve = [&](assembly::Identifier const& _identifier, julia::IdentifierContext, bool)
@ -648,13 +645,12 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
} }
}; };
solAssert(_inlineAssembly.annotation().analysisInfo, ""); solAssert(_inlineAssembly.annotation().analysisInfo, "");
codeGen.assemble( assembly::CodeGenerator::assemble(
_inlineAssembly.operations(), _inlineAssembly.operations(),
*_inlineAssembly.annotation().analysisInfo, *_inlineAssembly.annotation().analysisInfo,
m_context.nonConstAssembly(), m_context.nonConstAssembly(),
identifierAccess identifierAccess
); );
solAssert(Error::containsOnlyWarnings(errorReporter.errors()), "Code generation for inline assembly with errors requested.");
m_context.setStackOffset(startStackHeight); m_context.setStackOffset(startStackHeight);
return false; return false;
} }

View File

@ -140,7 +140,7 @@ eth::Assembly assembly::CodeGenerator::assemble(
{ {
eth::Assembly assembly; eth::Assembly assembly;
EthAssemblyAdapter assemblyAdapter(assembly); EthAssemblyAdapter assemblyAdapter(assembly);
julia::CodeTransform(m_errorReporter, assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData); julia::CodeTransform(assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData);
return assembly; return assembly;
} }
@ -152,5 +152,5 @@ void assembly::CodeGenerator::assemble(
) )
{ {
EthAssemblyAdapter assemblyAdapter(_assembly); EthAssemblyAdapter assemblyAdapter(_assembly);
julia::CodeTransform(m_errorReporter, assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData); julia::CodeTransform(assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData);
} }

View File

@ -34,7 +34,6 @@ class Assembly;
} }
namespace solidity namespace solidity
{ {
class ErrorReporter;
namespace assembly namespace assembly
{ {
struct Block; struct Block;
@ -42,24 +41,19 @@ struct Block;
class CodeGenerator class CodeGenerator
{ {
public: public:
CodeGenerator(ErrorReporter& _errorReporter):
m_errorReporter(_errorReporter) {}
/// Performs code generation and @returns the result. /// Performs code generation and @returns the result.
eth::Assembly assemble( static eth::Assembly assemble(
Block const& _parsedData, Block const& _parsedData,
AsmAnalysisInfo& _analysisInfo, AsmAnalysisInfo& _analysisInfo,
julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess() julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess()
); );
/// Performs code generation and appends generated to to _assembly. /// Performs code generation and appends generated to to _assembly.
void assemble( static void assemble(
Block const& _parsedData, Block const& _parsedData,
AsmAnalysisInfo& _analysisInfo, AsmAnalysisInfo& _analysisInfo,
eth::Assembly& _assembly, eth::Assembly& _assembly,
julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess() julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess()
); );
private:
ErrorReporter& m_errorReporter;
}; };
} }

View File

@ -66,8 +66,7 @@ eth::Assembly InlineAssemblyStack::assemble()
AsmAnalysisInfo analysisInfo; AsmAnalysisInfo analysisInfo;
AsmAnalyzer analyzer(analysisInfo, m_errorReporter); AsmAnalyzer analyzer(analysisInfo, m_errorReporter);
solAssert(analyzer.analyze(*m_parserResult), ""); solAssert(analyzer.analyze(*m_parserResult), "");
CodeGenerator codeGen(m_errorReporter); return CodeGenerator::assemble(*m_parserResult, analysisInfo);
return codeGen.assemble(*m_parserResult, analysisInfo);
} }
bool InlineAssemblyStack::parseAndAssemble( bool InlineAssemblyStack::parseAndAssemble(
@ -87,7 +86,8 @@ bool InlineAssemblyStack::parseAndAssemble(
AsmAnalysisInfo analysisInfo; AsmAnalysisInfo analysisInfo;
AsmAnalyzer analyzer(analysisInfo, errorReporter, false, _identifierAccess.resolve); AsmAnalyzer analyzer(analysisInfo, errorReporter, false, _identifierAccess.resolve);
solAssert(analyzer.analyze(*parserResult), ""); solAssert(analyzer.analyze(*parserResult), "");
CodeGenerator(errorReporter).assemble(*parserResult, analysisInfo, _assembly, _identifierAccess); solAssert(errorReporter.errors().empty(), "");
CodeGenerator::assemble(*parserResult, analysisInfo, _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.

View File

@ -76,7 +76,7 @@ bool AssemblyStack::analyzeParsed()
return m_analysisSuccessful; return m_analysisSuccessful;
} }
eth::LinkerObject AssemblyStack::assemble(Machine _machine) eth::LinkerObject AssemblyStack::assemble(Machine _machine) const
{ {
solAssert(m_analysisSuccessful, ""); solAssert(m_analysisSuccessful, "");
solAssert(m_parserResult, ""); solAssert(m_parserResult, "");
@ -86,13 +86,13 @@ eth::LinkerObject AssemblyStack::assemble(Machine _machine)
{ {
case Machine::EVM: case Machine::EVM:
{ {
auto assembly = assembly::CodeGenerator(m_errorReporter).assemble(*m_parserResult, *m_analysisInfo); auto assembly = assembly::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo);
return assembly.assemble(); return assembly.assemble();
} }
case Machine::EVM15: case Machine::EVM15:
{ {
julia::EVMAssembly assembly(true); julia::EVMAssembly assembly(true);
julia::CodeTransform(m_errorReporter, assembly, *m_analysisInfo, true).run(*m_parserResult); julia::CodeTransform(assembly, *m_analysisInfo, true).run(*m_parserResult);
return assembly.finalize(); return assembly.finalize();
} }
case Machine::eWasm: case Machine::eWasm:
@ -102,7 +102,7 @@ eth::LinkerObject AssemblyStack::assemble(Machine _machine)
return eth::LinkerObject(); return eth::LinkerObject();
} }
string AssemblyStack::print() string AssemblyStack::print() const
{ {
solAssert(m_parserResult, ""); solAssert(m_parserResult, "");
return assembly::AsmPrinter(m_language == Language::JULIA)(*m_parserResult); return assembly::AsmPrinter(m_language == Language::JULIA)(*m_parserResult);

View File

@ -65,13 +65,13 @@ public:
bool analyze(assembly::Block const& _block, Scanner const* _scanner = nullptr); bool analyze(assembly::Block const& _block, Scanner const* _scanner = nullptr);
/// Run the assembly step (should only be called after parseAndAnalyze). /// Run the assembly step (should only be called after parseAndAnalyze).
eth::LinkerObject assemble(Machine _machine); eth::LinkerObject assemble(Machine _machine) const;
/// @returns the errors generated during parsing, analysis (and potentially assembly). /// @returns the errors generated during parsing, analysis (and potentially assembly).
ErrorList const& errors() const { return m_errors; } ErrorList const& errors() const { return m_errors; }
/// Pretty-print the input after having parsed it. /// Pretty-print the input after having parsed it.
std::string print(); std::string print() const;
private: private:
bool analyzeParsed(); bool analyzeParsed();