Implemented codegen for UserDefinedValueType

This commit is contained in:
hrkrshnn 2021-08-16 14:28:15 +02:00
parent ce75790e8d
commit 54484e9795
4 changed files with 98 additions and 0 deletions

View File

@ -772,6 +772,33 @@ void CompilerUtils::convertType(
Type::Category stackTypeCategory = _typeOnStack.category();
Type::Category targetTypeCategory = _targetType.category();
if (stackTypeCategory == Type::Category::UserDefinedValueType)
{
solAssert(_cleanupNeeded, "");
auto& userDefined = dynamic_cast<UserDefinedValueType const&>(_typeOnStack);
solAssert(_typeOnStack == _targetType || _targetType == userDefined.underlyingType(), "");
return convertType(
userDefined.underlyingType(),
_targetType,
_cleanupNeeded,
_chopSignBits,
_asPartOfArgumentDecoding
);
}
if (targetTypeCategory == Type::Category::UserDefinedValueType)
{
solAssert(_cleanupNeeded, "");
auto& userDefined = dynamic_cast<UserDefinedValueType const&>(_targetType);
solAssert(_typeOnStack.isImplicitlyConvertibleTo(userDefined.underlyingType()), "");
return convertType(
_typeOnStack,
userDefined.underlyingType(),
_cleanupNeeded,
_chopSignBits,
_asPartOfArgumentDecoding
);
}
if (auto contrType = dynamic_cast<ContractType const*>(&_typeOnStack))
solAssert(!contrType->isSuper(), "Cannot convert magic variable \"super\"");

View File

@ -957,6 +957,35 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
);
break;
}
case FunctionType::Kind::Wrap:
case FunctionType::Kind::Unwrap:
{
solAssert(arguments.size() == 1, "");
Type const* argumentType = arguments.at(0)->annotation().type;
Type const* functionCallType = _functionCall.annotation().type;
solAssert(argumentType, "");
solAssert(functionCallType, "");
FunctionType::Kind kind = functionType->kind();
if (kind == FunctionType::Kind::Wrap)
{
solAssert(
argumentType->isImplicitlyConvertibleTo(
dynamic_cast<UserDefinedValueType const&>(*functionCallType).underlyingType()
),
""
);
solAssert(argumentType->isImplicitlyConvertibleTo(*function.parameterTypes()[0]), "");
}
else
solAssert(
dynamic_cast<UserDefinedValueType const&>(*argumentType) ==
dynamic_cast<UserDefinedValueType const&>(*function.parameterTypes()[0]),
""
);
acceptAndConvert(*arguments[0], *function.parameterTypes()[0]);
break;
}
case FunctionType::Kind::BlockHash:
{
acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true);
@ -2157,6 +2186,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
{
// no-op
}
else if (dynamic_cast<UserDefinedValueTypeDefinition const*>(declaration))
{
// no-op
}
else if (dynamic_cast<StructDefinition const*>(declaration))
{
// no-op

View File

@ -3168,6 +3168,16 @@ string YulUtilFunctions::allocateAndInitializeMemoryStructFunction(StructType co
string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
{
if (_from.category() == Type::Category::UserDefinedValueType)
{
solAssert(_from == _to || _to == dynamic_cast<UserDefinedValueType const&>(_from).underlyingType(), "");
return conversionFunction(dynamic_cast<UserDefinedValueType const&>(_from).underlyingType(), _to);
}
if (_to.category() == Type::Category::UserDefinedValueType)
{
solAssert(_from == _to || _from.isImplicitlyConvertibleTo(dynamic_cast<UserDefinedValueType const&>(_to).underlyingType()), "");
return conversionFunction(_from, dynamic_cast<UserDefinedValueType const&>(_to).underlyingType());
}
if (_from.category() == Type::Category::Function)
{
solAssert(_to.category() == Type::Category::Function, "");
@ -3696,6 +3706,9 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy
string YulUtilFunctions::cleanupFunction(Type const& _type)
{
if (auto userDefinedValueType = dynamic_cast<UserDefinedValueType const*>(&_type))
return cleanupFunction(userDefinedValueType->underlyingType());
string functionName = string("cleanup_") + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
@ -3816,6 +3829,7 @@ string YulUtilFunctions::validatorFunction(Type const& _type, bool _revertOnFail
case Type::Category::Mapping:
case Type::Category::FixedBytes:
case Type::Category::Contract:
case Type::Category::UserDefinedValueType:
{
templ("condition", "eq(value, " + cleanupFunction(_type) + "(value))");
break;

View File

@ -1051,6 +1051,24 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
);
break;
}
case FunctionType::Kind::Wrap:
case FunctionType::Kind::Unwrap:
{
solAssert(arguments.size() == 1, "");
FunctionType::Kind kind = functionType->kind();
if (kind == FunctionType::Kind::Wrap)
solAssert(
type(*arguments.at(0)).isImplicitlyConvertibleTo(
dynamic_cast<UserDefinedValueType const&>(type(_functionCall)).underlyingType()
),
""
);
else
solAssert(type(*arguments.at(0)).category() == Type::Category::UserDefinedValueType, "");
define(_functionCall, *arguments.at(0));
break;
}
case FunctionType::Kind::Assert:
case FunctionType::Kind::Require:
{
@ -2004,6 +2022,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
}
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(&actualType))
define(_memberAccess) << to_string(enumType->memberValue(_memberAccess.memberName())) << "\n";
else if (dynamic_cast<UserDefinedValueType const*>(&actualType))
solAssert(member == "wrap" || member == "unwrap", "");
else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType))
solAssert(arrayType->isByteArray() && member == "concat", "");
else
@ -2314,6 +2334,10 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
{
// no-op
}
else if (dynamic_cast<UserDefinedValueTypeDefinition const*>(declaration))
{
// no-op
}
else
{
solAssert(false, "Identifier type not expected in expression context.");