mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Report locations of unimplemented features.
This commit is contained in:
parent
b1ccf73511
commit
930646ba2b
@ -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();
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <libyul/Dialect.h>
|
||||
#include <libyul/optimiser/ASTCopier.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
#include <libsolutil/Keccak256.h>
|
||||
@ -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<langutil::errinfo_sourceLocation>(_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<langutil::errinfo_sourceLocation>(_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<ReferenceType const*>(type))
|
||||
if (refType->dataStoredIn(DataLocation::Storage) && refType->isPointer())
|
||||
return;
|
||||
auto const* type = _varDecl.type();
|
||||
if (auto const* refType = dynamic_cast<ReferenceType const*>(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<langutil::errinfo_sourceLocation>(_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<langutil::errinfo_sourceLocation>(_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 <functionName>() -> <ret> {
|
||||
<code>
|
||||
<ret> := <value>
|
||||
}
|
||||
)");
|
||||
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 <functionName>() -> <ret> {
|
||||
<code>
|
||||
<ret> := <value>
|
||||
}
|
||||
)");
|
||||
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<langutil::errinfo_sourceLocation>(_error))
|
||||
_error << langutil::errinfo_sourceLocation(m_currentLocation);
|
||||
throw _error;
|
||||
}
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement)
|
||||
|
@ -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.
|
||||
|
@ -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<langutil::errinfo_sourceLocation>(_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();
|
||||
|
Loading…
Reference in New Issue
Block a user