BytesFor() used to return KIND for the size, which is not always correct, so I changed it to return the size of the actual CppType corresponding to the given category and kind. MinElemLen() used to calculate size incorrectly (e.g. CFI_type_extended_double was sized 10, whereas it may occupy more bytes on a target), so I changed it to call BytesFor(). Additional changes were needed to resolve new failures for transformational intrinsics. These intrinsics used to work for not fully supported data types (e.g. REAL(3)), but now stopped working because CppType cannot be computed for those categories/kinds. The solution is to use known element size from the source argument(s) for establishing the destination descriptor - the element size is all that is needed for transformational intrinsics to keep working. Note that this does not help cases, where runtime still has to compute the element size, e.g. when it creates descriptors for components of derived types. If the component has unsupported data type, BytesFor() will still fail. So these cases require adding support for the missing types. New regression unit test in Runtime/Transformational.cpp demonstrates the case that will start working properly with this commit.
209 lines
6.2 KiB
C++
209 lines
6.2 KiB
C++
//===-- runtime/type-code.cpp ---------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Runtime/type-code.h"
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
TypeCode::TypeCode(TypeCategory f, int kind) {
|
|
switch (f) {
|
|
case TypeCategory::Integer:
|
|
switch (kind) {
|
|
case 1:
|
|
raw_ = CFI_type_int8_t;
|
|
break;
|
|
case 2:
|
|
raw_ = CFI_type_int16_t;
|
|
break;
|
|
case 4:
|
|
raw_ = CFI_type_int32_t;
|
|
break;
|
|
case 8:
|
|
raw_ = CFI_type_int64_t;
|
|
break;
|
|
case 16:
|
|
raw_ = CFI_type_int128_t;
|
|
break;
|
|
}
|
|
break;
|
|
case TypeCategory::Real:
|
|
switch (kind) {
|
|
case 2:
|
|
raw_ = CFI_type_half_float;
|
|
break;
|
|
case 3:
|
|
raw_ = CFI_type_bfloat;
|
|
break;
|
|
case 4:
|
|
raw_ = CFI_type_float;
|
|
break;
|
|
case 8:
|
|
raw_ = CFI_type_double;
|
|
break;
|
|
case 10:
|
|
raw_ = CFI_type_extended_double;
|
|
break;
|
|
case 16:
|
|
raw_ = CFI_type_float128;
|
|
break;
|
|
}
|
|
break;
|
|
case TypeCategory::Complex:
|
|
switch (kind) {
|
|
case 2:
|
|
raw_ = CFI_type_half_float_Complex;
|
|
break;
|
|
case 3:
|
|
raw_ = CFI_type_bfloat_Complex;
|
|
break;
|
|
case 4:
|
|
raw_ = CFI_type_float_Complex;
|
|
break;
|
|
case 8:
|
|
raw_ = CFI_type_double_Complex;
|
|
break;
|
|
case 10:
|
|
raw_ = CFI_type_extended_double_Complex;
|
|
break;
|
|
case 16:
|
|
raw_ = CFI_type_long_double_Complex;
|
|
break;
|
|
}
|
|
break;
|
|
case TypeCategory::Character:
|
|
switch (kind) {
|
|
case 1:
|
|
raw_ = CFI_type_char;
|
|
break;
|
|
case 2:
|
|
raw_ = CFI_type_char16_t;
|
|
break;
|
|
case 4:
|
|
raw_ = CFI_type_char32_t;
|
|
break;
|
|
}
|
|
break;
|
|
case TypeCategory::Logical:
|
|
switch (kind) {
|
|
case 1:
|
|
raw_ = CFI_type_Bool;
|
|
break;
|
|
case 2:
|
|
raw_ = CFI_type_int_least16_t;
|
|
break;
|
|
case 4:
|
|
raw_ = CFI_type_int_least32_t;
|
|
break;
|
|
case 8:
|
|
raw_ = CFI_type_int_least64_t;
|
|
break;
|
|
}
|
|
break;
|
|
case TypeCategory::Derived:
|
|
raw_ = CFI_type_struct;
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::optional<std::pair<TypeCategory, int>>
|
|
TypeCode::GetCategoryAndKind() const {
|
|
switch (raw_) {
|
|
case CFI_type_signed_char:
|
|
return std::make_pair(TypeCategory::Character, sizeof(signed char));
|
|
case CFI_type_short:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(short));
|
|
case CFI_type_int:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(int));
|
|
case CFI_type_long:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(long));
|
|
case CFI_type_long_long:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(long long));
|
|
case CFI_type_size_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::size_t));
|
|
case CFI_type_int8_t:
|
|
return std::make_pair(TypeCategory::Integer, 1);
|
|
case CFI_type_int16_t:
|
|
return std::make_pair(TypeCategory::Integer, 2);
|
|
case CFI_type_int32_t:
|
|
return std::make_pair(TypeCategory::Integer, 4);
|
|
case CFI_type_int64_t:
|
|
return std::make_pair(TypeCategory::Integer, 8);
|
|
case CFI_type_int128_t:
|
|
return std::make_pair(TypeCategory::Integer, 16);
|
|
case CFI_type_int_least8_t:
|
|
return std::make_pair(TypeCategory::Logical, 1);
|
|
case CFI_type_int_least16_t:
|
|
return std::make_pair(TypeCategory::Logical, 2);
|
|
case CFI_type_int_least32_t:
|
|
return std::make_pair(TypeCategory::Logical, 4);
|
|
case CFI_type_int_least64_t:
|
|
return std::make_pair(TypeCategory::Logical, 8);
|
|
case CFI_type_int_least128_t:
|
|
return std::make_pair(TypeCategory::Integer, 16);
|
|
case CFI_type_int_fast8_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::int_fast8_t));
|
|
case CFI_type_int_fast16_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::int_fast16_t));
|
|
case CFI_type_int_fast32_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::int_fast32_t));
|
|
case CFI_type_int_fast64_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::int_fast64_t));
|
|
case CFI_type_int_fast128_t:
|
|
return std::make_pair(TypeCategory::Integer, 16);
|
|
case CFI_type_intmax_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::intmax_t));
|
|
case CFI_type_intptr_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::intptr_t));
|
|
case CFI_type_ptrdiff_t:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(std::ptrdiff_t));
|
|
case CFI_type_half_float:
|
|
return std::make_pair(TypeCategory::Real, 2);
|
|
case CFI_type_bfloat:
|
|
return std::make_pair(TypeCategory::Real, 3);
|
|
case CFI_type_float:
|
|
return std::make_pair(TypeCategory::Real, 4);
|
|
case CFI_type_double:
|
|
return std::make_pair(TypeCategory::Real, 8);
|
|
case CFI_type_extended_double:
|
|
return std::make_pair(TypeCategory::Real, 10);
|
|
case CFI_type_long_double:
|
|
return std::make_pair(TypeCategory::Real, 16);
|
|
case CFI_type_float128:
|
|
return std::make_pair(TypeCategory::Real, 16);
|
|
case CFI_type_half_float_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 2);
|
|
case CFI_type_bfloat_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 3);
|
|
case CFI_type_float_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 4);
|
|
case CFI_type_double_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 8);
|
|
case CFI_type_extended_double_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 10);
|
|
case CFI_type_long_double_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 16);
|
|
case CFI_type_float128_Complex:
|
|
return std::make_pair(TypeCategory::Complex, 16);
|
|
case CFI_type_Bool:
|
|
return std::make_pair(TypeCategory::Logical, 1);
|
|
case CFI_type_char:
|
|
return std::make_pair(TypeCategory::Character, 1);
|
|
case CFI_type_cptr:
|
|
return std::make_pair(TypeCategory::Integer, sizeof(void *));
|
|
case CFI_type_struct:
|
|
return std::make_pair(TypeCategory::Derived, 0);
|
|
case CFI_type_char16_t:
|
|
return std::make_pair(TypeCategory::Character, 2);
|
|
case CFI_type_char32_t:
|
|
return std::make_pair(TypeCategory::Character, 4);
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
} // namespace Fortran::runtime
|