diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 8fb932d01..151b8c9fd 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -164,7 +164,7 @@ string IRGenerator::generate( string IRGenerator::generate(Block const& _block) { IRGeneratorForStatements generator(m_context, m_utils); - _block.accept(generator); + generator.generate(_block); return generator.code(); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 9b9675562..176f876bd 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -38,6 +38,8 @@ #include #include +#include + #include #include #include @@ -152,74 +154,124 @@ string IRGeneratorForStatements::code() const return m_code.str(); } +void IRGeneratorForStatements::generate(Block const& _block) +{ + try + { + _block.accept(*this); + } + catch (langutil::UnimplementedFeatureError const& _error) + { + if (!boost::get_error_info(_error)) + _error << langutil::errinfo_sourceLocation(m_currentLocation); + throw _error; + } +} + void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _varDecl) { - setLocation(_varDecl); + try + { + setLocation(_varDecl); - solAssert(_varDecl.immutable() || m_context.isStateVariable(_varDecl), "Must be immutable or a state variable."); - solAssert(!_varDecl.isConstant(), ""); - if (!_varDecl.value()) - return; + solAssert(_varDecl.immutable() || m_context.isStateVariable(_varDecl), "Must be immutable or a state variable."); + solAssert(!_varDecl.isConstant(), ""); + if (!_varDecl.value()) + return; - _varDecl.value()->accept(*this); - writeToLValue( - _varDecl.immutable() ? - IRLValue{*_varDecl.annotation().type, IRLValue::Immutable{&_varDecl}} : - IRLValue{*_varDecl.annotation().type, IRLValue::Storage{ - util::toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_varDecl).first), - m_context.storageLocationOfStateVariable(_varDecl).second - }}, - *_varDecl.value() - ); + _varDecl.value()->accept(*this); + writeToLValue( + _varDecl.immutable() ? + IRLValue{*_varDecl.annotation().type, IRLValue::Immutable{&_varDecl}} : + IRLValue{*_varDecl.annotation().type, IRLValue::Storage{ + util::toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_varDecl).first), + m_context.storageLocationOfStateVariable(_varDecl).second + }}, + *_varDecl.value() + ); + } + catch (langutil::UnimplementedFeatureError const& _error) + { + if (!boost::get_error_info(_error)) + _error << langutil::errinfo_sourceLocation(m_currentLocation); + throw _error; + } } void IRGeneratorForStatements::initializeLocalVar(VariableDeclaration const& _varDecl) { - setLocation(_varDecl); + try + { + setLocation(_varDecl); - solAssert(m_context.isLocalVariable(_varDecl), "Must be a local variable."); + solAssert(m_context.isLocalVariable(_varDecl), "Must be a local variable."); - auto const* type = _varDecl.type(); - if (auto const* refType = dynamic_cast(type)) - if (refType->dataStoredIn(DataLocation::Storage) && refType->isPointer()) - return; + auto const* type = _varDecl.type(); + if (auto const* refType = dynamic_cast(type)) + if (refType->dataStoredIn(DataLocation::Storage) && refType->isPointer()) + return; - IRVariable zero = zeroValue(*type); - assign(m_context.localVariable(_varDecl), zero); + IRVariable zero = zeroValue(*type); + assign(m_context.localVariable(_varDecl), zero); + } + catch (langutil::UnimplementedFeatureError const& _error) + { + if (!boost::get_error_info(_error)) + _error << langutil::errinfo_sourceLocation(m_currentLocation); + throw _error; + } } IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expression, Type const& _targetType) { - setLocation(_expression); + try + { + setLocation(_expression); - _expression.accept(*this); - IRVariable variable{m_context.newYulVariable(), _targetType}; - define(variable, _expression); - return variable; + _expression.accept(*this); + IRVariable variable{m_context.newYulVariable(), _targetType}; + define(variable, _expression); + return variable; + } + catch (langutil::UnimplementedFeatureError const& _error) + { + if (!boost::get_error_info(_error)) + _error << langutil::errinfo_sourceLocation(m_currentLocation); + throw _error; + } } string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant) { - setLocation(_constant); + try + { + setLocation(_constant); - string functionName = IRNames::constantValueFunction(_constant); - return m_context.functionCollector().createFunction(functionName, [&] { - Whiskers templ(R"( - function () -> { - - := - } - )"); - templ("functionName", functionName); - IRGeneratorForStatements generator(m_context, m_utils); - solAssert(_constant.value(), ""); - Type const& constantType = *_constant.type(); - templ("value", generator.evaluateExpression(*_constant.value(), constantType).commaSeparatedList()); - templ("code", generator.code()); - templ("ret", IRVariable("ret", constantType).commaSeparatedList()); + string functionName = IRNames::constantValueFunction(_constant); + return m_context.functionCollector().createFunction(functionName, [&] { + Whiskers templ(R"( + function () -> { + + := + } + )"); + templ("functionName", functionName); + IRGeneratorForStatements generator(m_context, m_utils); + solAssert(_constant.value(), ""); + Type const& constantType = *_constant.type(); + templ("value", generator.evaluateExpression(*_constant.value(), constantType).commaSeparatedList()); + templ("code", generator.code()); + templ("ret", IRVariable("ret", constantType).commaSeparatedList()); - return templ.render(); - }); + return templ.render(); + }); + } + catch (langutil::UnimplementedFeatureError const& _error) + { + if (!boost::get_error_info(_error)) + _error << langutil::errinfo_sourceLocation(m_currentLocation); + throw _error; + } } void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index e746e9ed0..3d87eae57 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -47,6 +47,9 @@ public: std::string code() const; + /// Generate the code for the statements in the block; + void generate(Block const& _block); + /// Generates code to initialize the given state variable. void initializeStateVar(VariableDeclaration const& _varDecl); /// Generates code to initialize the given local variable. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 79380a703..32469e566 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -524,6 +524,10 @@ bool CompilerStack::compile() { if (m_generateEvmBytecode) compileContract(*contract, otherCompilers); + if (m_generateIR || m_generateEwasm) + generateIR(*contract); + if (m_generateEwasm) + generateEwasm(*contract); } catch (Error const& _error) { @@ -532,10 +536,28 @@ bool CompilerStack::compile() m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); return false; } - if (m_generateIR || m_generateEwasm) - generateIR(*contract); - if (m_generateEwasm) - generateEwasm(*contract); + catch (UnimplementedFeatureError const& _unimplementedError) + { + if ( + SourceLocation const* sourceLocation = + boost::get_error_info(_unimplementedError) + ) + { + string const* comment = _unimplementedError.comment(); + m_errorReporter.error( + 1834_error, + Error::Type::CodeGenerationError, + *sourceLocation, + "Unimplemented feature error" + + ((comment && !comment->empty()) ? ": " + *comment : string{}) + + " in " + + _unimplementedError.lineInfo() + ); + return false; + } + else + throw; + } } m_stackState = CompilationSuccessful; this->link();