Skip to content

Commit 262b3f7

Browse files
authored
[flang] Remove runtime dependence on C++ support for types (#134164)
Fortran::runtime::Descriptor::BytesFor() only works for Fortran intrinsic types for which a C++ type counterpart exists, so it crashes on some types that are legitimate Fortran types like REAL(2). Move some logic from Evaluate into a new header in flang/Common, then use it to avoid this needless dependence on C++.
1 parent 3674a5f commit 262b3f7

File tree

12 files changed

+94
-62
lines changed

12 files changed

+94
-62
lines changed

flang-rt/lib/runtime/descriptor.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
#include "flang-rt/runtime/derived.h"
1414
#include "flang-rt/runtime/stat.h"
1515
#include "flang-rt/runtime/terminator.h"
16-
#include "flang-rt/runtime/tools.h"
1716
#include "flang-rt/runtime/type-info.h"
17+
#include "flang/Common/type-kinds.h"
1818
#include <cassert>
1919
#include <cstdlib>
2020
#include <cstring>
@@ -61,18 +61,11 @@ RT_API_ATTRS void Descriptor::Establish(TypeCode t, std::size_t elementBytes,
6161
}
6262
}
6363

64-
namespace {
65-
template <TypeCategory CAT, int KIND> struct TypeSizeGetter {
66-
constexpr RT_API_ATTRS std::size_t operator()() const {
67-
CppTypeFor<CAT, KIND> arr[2];
68-
return sizeof arr / 2;
69-
}
70-
};
71-
} // namespace
72-
7364
RT_API_ATTRS std::size_t Descriptor::BytesFor(TypeCategory category, int kind) {
7465
Terminator terminator{__FILE__, __LINE__};
75-
return ApplyType<TypeSizeGetter, std::size_t>(category, kind, terminator);
66+
int bytes{common::TypeSizeInBytes(category, kind)};
67+
RUNTIME_CHECK(terminator, bytes > 0);
68+
return bytes;
7669
}
7770

7871
RT_API_ATTRS void Descriptor::Establish(TypeCategory c, int kind, void *p,

flang/include/flang/Common/Fortran-consts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef FORTRAN_COMMON_FORTRAN_CONSTS_H_
1010
#define FORTRAN_COMMON_FORTRAN_CONSTS_H_
1111

12-
#include "enum-set.h"
12+
#include "enum-class.h"
1313
#include <cstdint>
1414

1515
namespace Fortran::common {

flang/include/flang/Common/real.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// The various representations are distinguished by their binary precisions
1414
// (number of explicit significand bits and any implicit MSB in the fraction).
1515

16-
#include "api-attrs.h"
1716
#include <cinttypes>
1817

1918
namespace Fortran::common {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===-- include/flang/Common/type-kinds.h -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef FORTRAN_COMMON_TYPE_KINDS_H_
10+
#define FORTRAN_COMMON_TYPE_KINDS_H_
11+
12+
#include "Fortran-consts.h"
13+
#include "real.h"
14+
#include <cinttypes>
15+
16+
namespace Fortran::common {
17+
18+
static constexpr int maxKind{16};
19+
20+
// A predicate that is true when a kind value is a kind that could possibly
21+
// be supported for an intrinsic type category on some target instruction
22+
// set architecture.
23+
static constexpr bool IsValidKindOfIntrinsicType(
24+
TypeCategory category, std::int64_t kind) {
25+
switch (category) {
26+
case TypeCategory::Integer:
27+
case TypeCategory::Unsigned:
28+
return kind == 1 || kind == 2 || kind == 4 || kind == 8 || kind == 16;
29+
case TypeCategory::Real:
30+
case TypeCategory::Complex:
31+
return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 ||
32+
kind == 16;
33+
case TypeCategory::Character:
34+
return kind == 1 || kind == 2 || kind == 4;
35+
case TypeCategory::Logical:
36+
return kind == 1 || kind == 2 || kind == 4 || kind == 8;
37+
default:
38+
return false;
39+
}
40+
}
41+
42+
static constexpr int TypeSizeInBytes(TypeCategory category, std::int64_t kind) {
43+
if (IsValidKindOfIntrinsicType(category, kind)) {
44+
if (category == TypeCategory::Real || category == TypeCategory::Complex) {
45+
int precision{PrecisionOfRealKind(kind)};
46+
int bits{BitsForBinaryPrecision(precision)};
47+
if (bits == 80) { // x87 is stored in 16-byte containers
48+
bits = 128;
49+
}
50+
if (category == TypeCategory::Complex) {
51+
bits *= 2;
52+
}
53+
return bits >> 3;
54+
} else {
55+
return kind;
56+
}
57+
} else {
58+
return -1;
59+
}
60+
}
61+
62+
} // namespace Fortran::common
63+
#endif // FORTRAN_COMMON_TYPE_KINDS_H_

flang/include/flang/Evaluate/target.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "flang/Common/enum-class.h"
1616
#include "flang/Common/enum-set.h"
1717
#include "flang/Common/target-rounding.h"
18+
#include "flang/Common/type-kinds.h"
1819
#include "flang/Evaluate/common.h"
1920
#include "flang/Support/Fortran.h"
2021
#include <cstdint>
@@ -131,7 +132,7 @@ class TargetCharacteristics {
131132
const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }
132133

133134
private:
134-
static constexpr int maxKind{16};
135+
static constexpr int maxKind{common::maxKind};
135136
std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind + 1]{};
136137
std::uint8_t align_[common::TypeCategory_enumSize][maxKind + 1]{};
137138
bool isBigEndian_{false};

flang/include/flang/Evaluate/type.h

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "flang/Common/idioms.h"
2626
#include "flang/Common/real.h"
2727
#include "flang/Common/template.h"
28+
#include "flang/Common/type-kinds.h"
2829
#include "flang/Support/Fortran-features.h"
2930
#include "flang/Support/Fortran.h"
3031
#include <cinttypes>
@@ -62,28 +63,6 @@ using LogicalResult = Type<TypeCategory::Logical, 4>;
6263
using LargestReal = Type<TypeCategory::Real, 16>;
6364
using Ascii = Type<TypeCategory::Character, 1>;
6465

65-
// A predicate that is true when a kind value is a kind that could possibly
66-
// be supported for an intrinsic type category on some target instruction
67-
// set architecture.
68-
static constexpr bool IsValidKindOfIntrinsicType(
69-
TypeCategory category, std::int64_t kind) {
70-
switch (category) {
71-
case TypeCategory::Integer:
72-
case TypeCategory::Unsigned:
73-
return kind == 1 || kind == 2 || kind == 4 || kind == 8 || kind == 16;
74-
case TypeCategory::Real:
75-
case TypeCategory::Complex:
76-
return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 ||
77-
kind == 16;
78-
case TypeCategory::Character:
79-
return kind == 1 || kind == 2 || kind == 4;
80-
case TypeCategory::Logical:
81-
return kind == 1 || kind == 2 || kind == 4 || kind == 8;
82-
default:
83-
return false;
84-
}
85-
}
86-
8766
// DynamicType is meant to be suitable for use as the result type for
8867
// GetType() functions and member functions; consequently, it must be
8968
// capable of being used in a constexpr context. So it does *not*
@@ -95,15 +74,15 @@ static constexpr bool IsValidKindOfIntrinsicType(
9574
class DynamicType {
9675
public:
9776
constexpr DynamicType(TypeCategory cat, int k) : category_{cat}, kind_{k} {
98-
CHECK(IsValidKindOfIntrinsicType(category_, kind_));
77+
CHECK(common::IsValidKindOfIntrinsicType(category_, kind_));
9978
}
10079
DynamicType(int charKind, const semantics::ParamValue &len);
10180
// When a known length is presented, resolve it to its effective
10281
// length of zero if it is negative.
10382
constexpr DynamicType(int k, std::int64_t len)
10483
: category_{TypeCategory::Character}, kind_{k}, knownLength_{
10584
len >= 0 ? len : 0} {
106-
CHECK(IsValidKindOfIntrinsicType(category_, kind_));
85+
CHECK(common::IsValidKindOfIntrinsicType(category_, kind_));
10786
}
10887
explicit constexpr DynamicType(
10988
const semantics::DerivedTypeSpec &dt, bool poly = false)
@@ -360,7 +339,7 @@ using IndirectSubscriptIntegerExpr =
360339
// category that could possibly be supported on any target.
361340
template <TypeCategory CATEGORY, int KIND>
362341
using CategoryKindTuple =
363-
std::conditional_t<IsValidKindOfIntrinsicType(CATEGORY, KIND),
342+
std::conditional_t<common::IsValidKindOfIntrinsicType(CATEGORY, KIND),
364343
std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>;
365344

366345
template <TypeCategory CATEGORY, int... KINDS>

flang/lib/Evaluate/target.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "flang/Evaluate/target.h"
1010
#include "flang/Common/template.h"
11+
#include "flang/Common/type-kinds.h"
1112
#include "flang/Evaluate/common.h"
1213
#include "flang/Evaluate/type.h"
1314

@@ -19,21 +20,11 @@ TargetCharacteristics::TargetCharacteristics() {
1920
auto enableCategoryKinds{[this](TypeCategory category) {
2021
for (int kind{1}; kind <= maxKind; ++kind) {
2122
if (CanSupportType(category, kind)) {
22-
auto byteSize{static_cast<std::size_t>(kind)};
23-
if (category == TypeCategory::Real ||
24-
category == TypeCategory::Complex) {
25-
if (kind == 3) {
26-
// non-IEEE 16-bit format (truncated 32-bit)
27-
byteSize = 2;
28-
} else if (kind == 10) {
29-
// x87 floating-point
30-
// Follow gcc precedent for "long double"
31-
byteSize = 16;
32-
}
33-
}
23+
auto byteSize{
24+
static_cast<std::size_t>(common::TypeSizeInBytes(category, kind))};
3425
std::size_t align{byteSize};
3526
if (category == TypeCategory::Complex) {
36-
byteSize = 2 * byteSize;
27+
align /= 2;
3728
}
3829
EnableType(category, kind, byteSize, align);
3930
}
@@ -53,7 +44,7 @@ TargetCharacteristics::TargetCharacteristics() {
5344

5445
bool TargetCharacteristics::CanSupportType(
5546
TypeCategory category, std::int64_t kind) {
56-
return IsValidKindOfIntrinsicType(category, kind);
47+
return common::IsValidKindOfIntrinsicType(category, kind);
5748
}
5849

5950
bool TargetCharacteristics::EnableType(common::TypeCategory category,

flang/lib/Evaluate/tools.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "flang/Evaluate/tools.h"
1010
#include "flang/Common/idioms.h"
11+
#include "flang/Common/type-kinds.h"
1112
#include "flang/Evaluate/characteristics.h"
1213
#include "flang/Evaluate/traverse.h"
1314
#include "flang/Parser/message.h"
@@ -1349,7 +1350,7 @@ template <TypeCategory TO, TypeCategory FROM>
13491350
static std::optional<Expr<SomeType>> DataConstantConversionHelper(
13501351
FoldingContext &context, const DynamicType &toType,
13511352
const Expr<SomeType> &expr) {
1352-
if (!IsValidKindOfIntrinsicType(FROM, toType.kind())) {
1353+
if (!common::IsValidKindOfIntrinsicType(FROM, toType.kind())) {
13531354
return std::nullopt;
13541355
}
13551356
DynamicType sizedType{FROM, toType.kind()};

flang/lib/Evaluate/type.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "flang/Evaluate/type.h"
1010
#include "flang/Common/idioms.h"
11+
#include "flang/Common/type-kinds.h"
1112
#include "flang/Evaluate/expression.h"
1213
#include "flang/Evaluate/fold.h"
1314
#include "flang/Evaluate/target.h"
@@ -118,7 +119,7 @@ namespace Fortran::evaluate {
118119

119120
DynamicType::DynamicType(int k, const semantics::ParamValue &pv)
120121
: category_{TypeCategory::Character}, kind_{k} {
121-
CHECK(IsValidKindOfIntrinsicType(category_, kind_));
122+
CHECK(common::IsValidKindOfIntrinsicType(category_, kind_));
122123
if (auto n{ToInt64(pv.GetExplicit())}) {
123124
knownLength_ = *n > 0 ? *n : 0;
124125
} else {
@@ -660,7 +661,7 @@ std::optional<DynamicType> DynamicType::From(
660661
if (const auto *intrinsic{type.AsIntrinsic()}) {
661662
if (auto kind{ToInt64(intrinsic->kind())}) {
662663
TypeCategory category{intrinsic->category()};
663-
if (IsValidKindOfIntrinsicType(category, *kind)) {
664+
if (common::IsValidKindOfIntrinsicType(category, *kind)) {
664665
if (category == TypeCategory::Character) {
665666
const auto &charType{type.characterTypeSpec()};
666667
return DynamicType{static_cast<int>(*kind), charType.length()};

flang/lib/Lower/ConvertType.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "flang/Lower/ConvertType.h"
10+
#include "flang/Common/type-kinds.h"
1011
#include "flang/Lower/AbstractConverter.h"
1112
#include "flang/Lower/CallInterface.h"
1213
#include "flang/Lower/ConvertVariable.h"
@@ -32,7 +33,7 @@ using Fortran::common::VectorElementCategory;
3233
//===--------------------------------------------------------------------===//
3334

3435
static mlir::Type genRealType(mlir::MLIRContext *context, int kind) {
35-
if (Fortran::evaluate::IsValidKindOfIntrinsicType(
36+
if (Fortran::common::IsValidKindOfIntrinsicType(
3637
Fortran::common::TypeCategory::Real, kind)) {
3738
switch (kind) {
3839
case 2:
@@ -59,7 +60,7 @@ int getIntegerBits() {
5960
}
6061
static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind,
6162
bool isUnsigned = false) {
62-
if (Fortran::evaluate::IsValidKindOfIntrinsicType(
63+
if (Fortran::common::IsValidKindOfIntrinsicType(
6364
Fortran::common::TypeCategory::Integer, kind)) {
6465
mlir::IntegerType::SignednessSemantics signedness =
6566
(isUnsigned ? mlir::IntegerType::SignednessSemantics::Unsigned
@@ -82,7 +83,7 @@ static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind,
8283
}
8384

8485
static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) {
85-
if (Fortran::evaluate::IsValidKindOfIntrinsicType(
86+
if (Fortran::common::IsValidKindOfIntrinsicType(
8687
Fortran::common::TypeCategory::Logical, KIND))
8788
return fir::LogicalType::get(context, KIND);
8889
return {};
@@ -91,7 +92,7 @@ static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) {
9192
static mlir::Type genCharacterType(
9293
mlir::MLIRContext *context, int KIND,
9394
Fortran::lower::LenParameterTy len = fir::CharacterType::unknownLen()) {
94-
if (Fortran::evaluate::IsValidKindOfIntrinsicType(
95+
if (Fortran::common::IsValidKindOfIntrinsicType(
9596
Fortran::common::TypeCategory::Character, KIND))
9697
return fir::CharacterType::get(context, KIND, len);
9798
return {};

flang/lib/Semantics/expression.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "resolve-names-utils.h"
1313
#include "resolve-names.h"
1414
#include "flang/Common/idioms.h"
15+
#include "flang/Common/type-kinds.h"
1516
#include "flang/Evaluate/common.h"
1617
#include "flang/Evaluate/fold.h"
1718
#include "flang/Evaluate/tools.h"
@@ -1058,7 +1059,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
10581059
if (const semantics::IntrinsicTypeSpec *
10591060
intrinType{typeSpec->AsIntrinsic()}) {
10601061
if (auto k{ToInt64(Fold(semantics::KindExpr{intrinType->kind()}))};
1061-
k && IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) {
1062+
k &&
1063+
common::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) {
10621064
kind = *k;
10631065
}
10641066
}

flang/lib/Semantics/type.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "flang/Semantics/type.h"
1010
#include "check-declarations.h"
1111
#include "compute-offsets.h"
12+
#include "flang/Common/type-kinds.h"
1213
#include "flang/Evaluate/fold.h"
1314
#include "flang/Evaluate/tools.h"
1415
#include "flang/Evaluate/type.h"
@@ -125,7 +126,7 @@ void DerivedTypeSpec::EvaluateParameters(SemanticsContext &context) {
125126
auto restorer{foldingContext.WithPDTInstance(*this)};
126127
auto folded{Fold(foldingContext, KindExpr{intrinType->kind()})};
127128
if (auto k{evaluate::ToInt64(folded)}; k &&
128-
evaluate::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) {
129+
common::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) {
129130
parameterKind = static_cast<int>(*k);
130131
} else {
131132
messages.Say(

0 commit comments

Comments
 (0)