From 54484e9795f1bd5c5916b25ee84b812f5d5b2072 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 16 Aug 2021 14:28:15 +0200 Subject: [PATCH] Implemented codegen for UserDefinedValueType --- libsolidity/codegen/CompilerUtils.cpp | 27 +++++++++++++++ libsolidity/codegen/ExpressionCompiler.cpp | 33 +++++++++++++++++++ libsolidity/codegen/YulUtilFunctions.cpp | 14 ++++++++ .../codegen/ir/IRGeneratorForStatements.cpp | 24 ++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 9ae1741dd..61eed4abd 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -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(_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(_targetType); + solAssert(_typeOnStack.isImplicitlyConvertibleTo(userDefined.underlyingType()), ""); + return convertType( + _typeOnStack, + userDefined.underlyingType(), + _cleanupNeeded, + _chopSignBits, + _asPartOfArgumentDecoding + ); + } + if (auto contrType = dynamic_cast(&_typeOnStack)) solAssert(!contrType->isSuper(), "Cannot convert magic variable \"super\""); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 210504868..8f364df1b 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -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(*functionCallType).underlyingType() + ), + "" + ); + solAssert(argumentType->isImplicitlyConvertibleTo(*function.parameterTypes()[0]), ""); + } + else + solAssert( + dynamic_cast(*argumentType) == + dynamic_cast(*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(declaration)) + { + // no-op + } else if (dynamic_cast(declaration)) { // no-op diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index f61a76d32..bb56c43df 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -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(_from).underlyingType(), ""); + return conversionFunction(dynamic_cast(_from).underlyingType(), _to); + } + if (_to.category() == Type::Category::UserDefinedValueType) + { + solAssert(_from == _to || _from.isImplicitlyConvertibleTo(dynamic_cast(_to).underlyingType()), ""); + return conversionFunction(_from, dynamic_cast(_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(&_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; diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 8f281a10e..0318b6226 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -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(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(&actualType)) define(_memberAccess) << to_string(enumType->memberValue(_memberAccess.memberName())) << "\n"; + else if (dynamic_cast(&actualType)) + solAssert(member == "wrap" || member == "unwrap", ""); else if (auto const* arrayType = dynamic_cast(&actualType)) solAssert(arrayType->isByteArray() && member == "concat", ""); else @@ -2314,6 +2334,10 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier) { // no-op } + else if (dynamic_cast(declaration)) + { + // no-op + } else { solAssert(false, "Identifier type not expected in expression context.");