Implement IR shortcut for <address>.code.length

This commit is contained in:
hrkrshnn 2021-01-21 20:26:01 +01:00
parent d6d880dc53
commit 526ceec152
2 changed files with 42 additions and 6 deletions

View File

@ -1554,6 +1554,28 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
}
}
bool IRGeneratorForStatements::visit(MemberAccess const& _memberAccess)
{
// A shortcut for <address>.code.length. We skip visiting <address>.code and directly visit
// <address>. The actual code is generated in endVisit.
if (
auto innerExpression = dynamic_cast<MemberAccess const*>(&_memberAccess.expression());
_memberAccess.memberName() == "length" &&
innerExpression &&
innerExpression->memberName() == "code" &&
innerExpression->expression().annotation().type->category() == Type::Category::Address
)
{
solAssert(innerExpression->annotation().type->category() == Type::Category::Array, "");
// Skip visiting <address>.code
innerExpression->expression().accept(*this);
return false;
}
return true;
}
void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
setLocation(_memberAccess);
@ -1846,13 +1868,26 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
case Type::Category::Array:
{
auto const& type = dynamic_cast<ArrayType const&>(*_memberAccess.expression().annotation().type);
if (member == "length")
define(_memberAccess) <<
m_utils.arrayLengthFunction(type) <<
"(" <<
IRVariable(_memberAccess.expression()).commaSeparatedList() <<
")\n";
{
// shortcut for <address>.code.length
if (
auto innerExpression = dynamic_cast<MemberAccess const*>(&_memberAccess.expression());
innerExpression &&
innerExpression->memberName() == "code" &&
innerExpression->expression().annotation().type->category() == Type::Category::Address
)
define(_memberAccess) <<
"extcodesize(" <<
expressionAsType(innerExpression->expression(), *TypeProvider::address()) <<
")\n";
else
define(_memberAccess) <<
m_utils.arrayLengthFunction(type) <<
"(" <<
IRVariable(_memberAccess.expression()).commaSeparatedList() <<
")\n";
}
else if (member == "pop" || member == "push")
{
solAssert(type.location() == DataLocation::Storage, "");

View File

@ -87,6 +87,7 @@ public:
bool visit(BinaryOperation const& _binOp) override;
void endVisit(FunctionCall const& _funCall) override;
void endVisit(FunctionCallOptions const& _funCallOptions) override;
bool visit(MemberAccess const& _memberAccess) override;
void endVisit(MemberAccess const& _memberAccess) override;
bool visit(InlineAssembly const& _inlineAsm) override;
void endVisit(IndexAccess const& _indexAccess) override;