| 3414 | } |
| 3415 | |
| 3416 | std::string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to) |
| 3417 | { |
| 3418 | if (_from.category() == Type::Category::UserDefinedValueType) |
| 3419 | { |
| 3420 | solAssert(_from == _to || _to == dynamic_cast<UserDefinedValueType const&>(_from).underlyingType(), ""); |
| 3421 | return conversionFunction(dynamic_cast<UserDefinedValueType const&>(_from).underlyingType(), _to); |
| 3422 | } |
| 3423 | if (_to.category() == Type::Category::UserDefinedValueType) |
| 3424 | { |
| 3425 | solAssert(_from == _to || _from.isImplicitlyConvertibleTo(dynamic_cast<UserDefinedValueType const&>(_to).underlyingType()), ""); |
| 3426 | return conversionFunction(_from, dynamic_cast<UserDefinedValueType const&>(_to).underlyingType()); |
| 3427 | } |
| 3428 | if (_from.category() == Type::Category::Function) |
| 3429 | { |
| 3430 | solAssert(_to.category() == Type::Category::Function, ""); |
| 3431 | FunctionType const& fromType = dynamic_cast<FunctionType const&>(_from); |
| 3432 | FunctionType const& targetType = dynamic_cast<FunctionType const&>(_to); |
| 3433 | solAssert( |
| 3434 | fromType.isImplicitlyConvertibleTo(targetType) && |
| 3435 | fromType.sizeOnStack() == targetType.sizeOnStack() && |
| 3436 | (fromType.kind() == FunctionType::Kind::Internal || fromType.kind() == FunctionType::Kind::External) && |
| 3437 | fromType.kind() == targetType.kind(), |
| 3438 | "Invalid function type conversion requested." |
| 3439 | ); |
| 3440 | std::string const functionName = |
| 3441 | "convert_" + |
| 3442 | _from.identifier() + |
| 3443 | "_to_" + |
| 3444 | _to.identifier(); |
| 3445 | return m_functionCollector.createFunction(functionName, [&]() { |
| 3446 | return Whiskers(R"( |
| 3447 | function <functionName>(<?external>addr, </external>functionId) -> <?external>outAddr, </external>outFunctionId { |
| 3448 | <?external>outAddr := addr</external> |
| 3449 | outFunctionId := functionId |
| 3450 | } |
| 3451 | )") |
| 3452 | ("functionName", functionName) |
| 3453 | ("external", fromType.kind() == FunctionType::Kind::External) |
| 3454 | .render(); |
| 3455 | }); |
| 3456 | } |
| 3457 | else if (_from.category() == Type::Category::ArraySlice) |
| 3458 | { |
| 3459 | auto const& fromType = dynamic_cast<ArraySliceType const&>(_from); |
| 3460 | if (_to.category() == Type::Category::FixedBytes) |
| 3461 | { |
| 3462 | solAssert(fromType.arrayType().isByteArray(), "Array types other than bytes not convertible to bytesNN."); |
| 3463 | return bytesToFixedBytesConversionFunction(fromType.arrayType(), dynamic_cast<FixedBytesType const &>(_to)); |
| 3464 | } |
| 3465 | solAssert(_to.category() == Type::Category::Array); |
| 3466 | auto const& targetType = dynamic_cast<ArrayType const&>(_to); |
| 3467 | |
| 3468 | solAssert( |
| 3469 | fromType.arrayType().isImplicitlyConvertibleTo(targetType) || |
| 3470 | (fromType.arrayType().isByteArrayOrString() && targetType.isByteArrayOrString()) |
| 3471 | ); |
| 3472 | solAssert( |
| 3473 | fromType.arrayType().dataStoredIn(DataLocation::CallData) && |
no test coverage detected