mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8685 from ethereum/yulForTypeType
Yul codegen for member access to type type
This commit is contained in:
commit
14fc9e740c
@ -985,12 +985,74 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
}
|
}
|
||||||
case Type::Category::TypeType:
|
case Type::Category::TypeType:
|
||||||
{
|
{
|
||||||
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.expression().annotation().type);
|
Type const& actualType = *dynamic_cast<TypeType const&>(
|
||||||
solUnimplementedAssert(type.actualType()->category() == Type::Category::Contract, "");
|
*_memberAccess.expression().annotation().type
|
||||||
FunctionType const* funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
|
).actualType();
|
||||||
solUnimplementedAssert(funType, "");
|
|
||||||
solUnimplementedAssert(funType->kind() == FunctionType::Kind::Declaration, "");
|
if (actualType.category() == Type::Category::Contract)
|
||||||
// Nothing to do for declaration.
|
{
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1208,28 +1270,7 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
|
|||||||
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
|
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
|
||||||
define(_identifier) << to_string(functionDef->resolveVirtual(m_context.mostDerivedContract()).id()) << "\n";
|
define(_identifier) << to_string(functionDef->resolveVirtual(m_context.mostDerivedContract()).id()) << "\n";
|
||||||
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
|
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||||
{
|
handleVariableReference(*varDecl, _identifier);
|
||||||
// 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.");
|
|
||||||
}
|
|
||||||
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
|
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
|
||||||
{
|
{
|
||||||
solUnimplementedAssert(!contract->isLibrary(), "Libraries not yet supported.");
|
solUnimplementedAssert(!contract->isLibrary(), "Libraries not yet supported.");
|
||||||
@ -1271,6 +1312,33 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
|
|||||||
return false;
|
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(
|
void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||||
FunctionCall const& _functionCall,
|
FunctionCall const& _functionCall,
|
||||||
vector<ASTPointer<Expression const>> const& _arguments
|
vector<ASTPointer<Expression const>> const& _arguments
|
||||||
@ -1890,4 +1958,3 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
|
|||||||
_clause.block().accept(*this);
|
_clause.block().accept(*this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,11 @@ private:
|
|||||||
/// Generates code to rethrow an exception.
|
/// Generates code to rethrow an exception.
|
||||||
void rethrow();
|
void rethrow();
|
||||||
|
|
||||||
|
void handleVariableReference(
|
||||||
|
VariableDeclaration const& _variable,
|
||||||
|
Expression const& _referencingExpression
|
||||||
|
);
|
||||||
|
|
||||||
/// Appends code to call an external function with the given arguments.
|
/// Appends code to call an external function with the given arguments.
|
||||||
/// All involved expressions have already been visited.
|
/// All involved expressions have already been visited.
|
||||||
void appendExternalFunctionCall(
|
void appendExternalFunctionCall(
|
||||||
|
@ -6,5 +6,7 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// answer() -> 1
|
// answer() -> 1
|
||||||
|
@ -12,5 +12,7 @@ contract test {
|
|||||||
ActionChoices choices;
|
ActionChoices choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// getChoice() -> 2
|
// getChoice() -> 2
|
||||||
|
@ -8,6 +8,7 @@ contract test is base {
|
|||||||
_ret = Choice.B;
|
_ret = Choice.B;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// answer() -> 1
|
// answer() -> 1
|
||||||
|
@ -8,6 +8,7 @@ contract test is base {
|
|||||||
_ret = base.Choice.B;
|
_ret = base.Choice.B;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// answer() -> 1
|
// answer() -> 1
|
||||||
|
@ -21,7 +21,8 @@ contract Derived is Base {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// g() -> 3
|
// g() -> 3
|
||||||
// f() -> 1
|
// f() -> 1
|
||||||
|
@ -14,6 +14,7 @@ contract B is A {
|
|||||||
return A.f();
|
return A.f();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// g() -> 1
|
// g() -> 1
|
||||||
|
@ -6,6 +6,7 @@ contract A {
|
|||||||
x = A.y;
|
x = A.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// a() -> 2
|
// a() -> 2
|
||||||
|
@ -5,6 +5,7 @@ contract Scope {
|
|||||||
stateVar = Scope.stateVar;
|
stateVar = Scope.stateVar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// getStateVar() -> 42
|
// getStateVar() -> 42
|
||||||
|
Loading…
Reference in New Issue
Block a user