mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Yul IR generation for member access to type types.
This commit is contained in:
@@ -985,12 +985,74 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
case Type::Category::TypeType:
|
||||
{
|
||||
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.expression().annotation().type);
|
||||
solUnimplementedAssert(type.actualType()->category() == Type::Category::Contract, "");
|
||||
FunctionType const* funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
|
||||
solUnimplementedAssert(funType, "");
|
||||
solUnimplementedAssert(funType->kind() == FunctionType::Kind::Declaration, "");
|
||||
// Nothing to do for declaration.
|
||||
Type const& actualType = *dynamic_cast<TypeType const&>(
|
||||
*_memberAccess.expression().annotation().type
|
||||
).actualType();
|
||||
|
||||
if (actualType.category() == Type::Category::Contract)
|
||||
{
|
||||
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
handleVariableReference(*variable, _memberAccess);
|
||||
else if (auto const* funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
|
||||
{
|
||||
switch (funType->kind())
|
||||
{
|
||||
case FunctionType::Kind::Declaration:
|
||||
break;
|
||||
case FunctionType::Kind::Internal:
|
||||
if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
define(_memberAccess) << to_string(function->id()) << "\n";
|
||||
else
|
||||
solAssert(false, "Function not found in member access");
|
||||
break;
|
||||
case FunctionType::Kind::Event:
|
||||
solAssert(
|
||||
dynamic_cast<EventDefinition const*>(_memberAccess.annotation().referencedDeclaration),
|
||||
"Event not found"
|
||||
);
|
||||
// the call will do the resolving
|
||||
break;
|
||||
case FunctionType::Kind::DelegateCall:
|
||||
define(IRVariable(_memberAccess).part("address"), _memberAccess.expression());
|
||||
define(IRVariable(_memberAccess).part("functionIdentifier")) << formatNumber(funType->externalIdentifier()) << "\n";
|
||||
break;
|
||||
case FunctionType::Kind::External:
|
||||
case FunctionType::Kind::Creation:
|
||||
case FunctionType::Kind::Send:
|
||||
case FunctionType::Kind::BareCall:
|
||||
case FunctionType::Kind::BareCallCode:
|
||||
case FunctionType::Kind::BareDelegateCall:
|
||||
case FunctionType::Kind::BareStaticCall:
|
||||
case FunctionType::Kind::Transfer:
|
||||
case FunctionType::Kind::Log0:
|
||||
case FunctionType::Kind::Log1:
|
||||
case FunctionType::Kind::Log2:
|
||||
case FunctionType::Kind::Log3:
|
||||
case FunctionType::Kind::Log4:
|
||||
case FunctionType::Kind::ECRecover:
|
||||
case FunctionType::Kind::SHA256:
|
||||
case FunctionType::Kind::RIPEMD160:
|
||||
default:
|
||||
solAssert(false, "unsupported member function");
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type))
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
else
|
||||
// The old code generator had a generic "else" case here
|
||||
// without any specific code being generated,
|
||||
// but it would still be better to have an exhaustive list.
|
||||
solAssert(false, "");
|
||||
}
|
||||
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(&actualType))
|
||||
define(_memberAccess) << to_string(enumType->memberValue(_memberAccess.memberName())) << "\n";
|
||||
else
|
||||
// The old code generator had a generic "else" case here
|
||||
// without any specific code being generated,
|
||||
// but it would still be better to have an exhaustive list.
|
||||
solAssert(false, "");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1208,28 +1270,7 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
|
||||
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
|
||||
define(_identifier) << to_string(functionDef->resolveVirtual(m_context.mostDerivedContract()).id()) << "\n";
|
||||
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
{
|
||||
// TODO for the constant case, we have to be careful:
|
||||
// If the value is visited twice, `defineExpression` is called twice on
|
||||
// the same expression.
|
||||
solUnimplementedAssert(!varDecl->isConstant(), "");
|
||||
solUnimplementedAssert(!varDecl->immutable(), "");
|
||||
if (m_context.isLocalVariable(*varDecl))
|
||||
setLValue(_identifier, IRLValue{
|
||||
*varDecl->annotation().type,
|
||||
IRLValue::Stack{m_context.localVariable(*varDecl)}
|
||||
});
|
||||
else if (m_context.isStateVariable(*varDecl))
|
||||
setLValue(_identifier, IRLValue{
|
||||
*varDecl->annotation().type,
|
||||
IRLValue::Storage{
|
||||
toCompactHexWithPrefix(m_context.storageLocationOfVariable(*varDecl).first),
|
||||
m_context.storageLocationOfVariable(*varDecl).second
|
||||
}
|
||||
});
|
||||
else
|
||||
solAssert(false, "Invalid variable kind.");
|
||||
}
|
||||
handleVariableReference(*varDecl, _identifier);
|
||||
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
|
||||
{
|
||||
solUnimplementedAssert(!contract->isLibrary(), "Libraries not yet supported.");
|
||||
@@ -1271,6 +1312,33 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
|
||||
return false;
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::handleVariableReference(
|
||||
VariableDeclaration const& _variable,
|
||||
Expression const& _referencingExpression
|
||||
)
|
||||
{
|
||||
// TODO for the constant case, we have to be careful:
|
||||
// If the value is visited twice, `defineExpression` is called twice on
|
||||
// the same expression.
|
||||
solUnimplementedAssert(!_variable.isConstant(), "");
|
||||
solUnimplementedAssert(!_variable.immutable(), "");
|
||||
if (m_context.isLocalVariable(_variable))
|
||||
setLValue(_referencingExpression, IRLValue{
|
||||
*_variable.annotation().type,
|
||||
IRLValue::Stack{m_context.localVariable(_variable)}
|
||||
});
|
||||
else if (m_context.isStateVariable(_variable))
|
||||
setLValue(_referencingExpression, IRLValue{
|
||||
*_variable.annotation().type,
|
||||
IRLValue::Storage{
|
||||
toCompactHexWithPrefix(m_context.storageLocationOfVariable(_variable).first),
|
||||
m_context.storageLocationOfVariable(_variable).second
|
||||
}
|
||||
});
|
||||
else
|
||||
solAssert(false, "Invalid variable kind.");
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
FunctionCall const& _functionCall,
|
||||
vector<ASTPointer<Expression const>> const& _arguments
|
||||
@@ -1890,4 +1958,3 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
|
||||
_clause.block().accept(*this);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user