Skip to content

Commit 17a4fce

Browse files
committed
[flang] REAL(KIND=3) and COMPLEX(KIND=3) descriptors
Update descriptor generation to correctly set the `type` field for REAL(3) and COMPLEX(3) objects.
1 parent 27f27d1 commit 17a4fce

File tree

8 files changed

+247
-211
lines changed

8 files changed

+247
-211
lines changed

flang/include/flang/ISO_Fortran_binding.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ typedef unsigned char CFI_attribute_t;
4343
typedef signed char CFI_type_t;
4444
/* These codes are required to be macros (i.e., #ifdef will work).
4545
* They are not required to be distinct, but neither are they required
46-
* to have had their synonyms combined. Codes marked as extensions may be
47-
* place holders for as yet unimplemented types.
46+
* to have had their synonyms combined.
4847
*/
4948
#define CFI_type_signed_char 1
5049
#define CFI_type_short 2
@@ -56,7 +55,7 @@ typedef signed char CFI_type_t;
5655
#define CFI_type_int16_t 8
5756
#define CFI_type_int32_t 9
5857
#define CFI_type_int64_t 10
59-
#define CFI_type_int128_t 11 /* extension */
58+
#define CFI_type_int128_t 11 /* extension kind=16 */
6059
#define CFI_type_int_least8_t 12
6160
#define CFI_type_int_least16_t 13
6261
#define CFI_type_int_least32_t 14
@@ -88,8 +87,8 @@ typedef signed char CFI_type_t;
8887
#define CFI_type_char 40
8988
#define CFI_type_cptr 41
9089
#define CFI_type_struct 42
91-
#define CFI_type_char16_t 43 /* extension */
92-
#define CFI_type_char32_t 44 /* extension */
90+
#define CFI_type_char16_t 43 /* extension kind=2 */
91+
#define CFI_type_char32_t 44 /* extension kind=4 */
9392
#define CFI_TYPE_LAST CFI_type_char32_t
9493
#define CFI_type_other (-1) // must be negative
9594

flang/include/flang/Optimizer/Support/TypeCode.h

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -13,80 +13,12 @@
1313
#ifndef FORTRAN_OPTIMIZER_SUPPORT_TYPECODE_H
1414
#define FORTRAN_OPTIMIZER_SUPPORT_TYPECODE_H
1515

16-
#include "flang/ISO_Fortran_binding.h"
17-
#include "llvm/Support/ErrorHandling.h"
16+
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
17+
#include "mlir/IR/Types.h"
1818

1919
namespace fir {
20-
21-
//===----------------------------------------------------------------------===//
22-
// Translations of category and bitwidths to the type codes defined in flang's
23-
// ISO_Fortran_binding.h.
24-
//===----------------------------------------------------------------------===//
25-
26-
inline int characterBitsToTypeCode(unsigned bitwidth) {
27-
// clang-format off
28-
switch (bitwidth) {
29-
case 8: return CFI_type_char;
30-
case 16: return CFI_type_char16_t;
31-
case 32: return CFI_type_char32_t;
32-
default: llvm_unreachable("unsupported character size");
33-
}
34-
// clang-format on
35-
}
36-
37-
inline int complexBitsToTypeCode(unsigned bitwidth) {
38-
// clang-format off
39-
switch (bitwidth) {
40-
case 16: return CFI_type_half_float_Complex; // CFI_type_bfloat_Complex ?
41-
case 32: return CFI_type_float_Complex;
42-
case 64: return CFI_type_double_Complex;
43-
case 80: return CFI_type_extended_double_Complex;
44-
case 128: return CFI_type_float128_Complex;
45-
default: llvm_unreachable("unsupported complex size");
46-
}
47-
// clang-format on
48-
}
49-
50-
inline int integerBitsToTypeCode(unsigned bitwidth) {
51-
// clang-format off
52-
switch (bitwidth) {
53-
case 8: return CFI_type_int8_t;
54-
case 16: return CFI_type_int16_t;
55-
case 32: return CFI_type_int32_t;
56-
case 64: return CFI_type_int64_t;
57-
case 128: return CFI_type_int128_t;
58-
default: llvm_unreachable("unsupported integer size");
59-
}
60-
// clang-format on
61-
}
62-
63-
inline int logicalBitsToTypeCode(unsigned bitwidth) {
64-
// clang-format off
65-
switch (bitwidth) {
66-
case 8: return CFI_type_Bool;
67-
case 16: return CFI_type_int_least16_t;
68-
case 32: return CFI_type_int_least32_t;
69-
case 64: return CFI_type_int_least64_t;
70-
default: llvm_unreachable("unsupported logical size");
71-
}
72-
// clang-format on
73-
}
74-
75-
inline int realBitsToTypeCode(unsigned bitwidth) {
76-
// clang-format off
77-
switch (bitwidth) {
78-
case 16: return CFI_type_half_float; // CFI_type_bfloat ?
79-
case 32: return CFI_type_float;
80-
case 64: return CFI_type_double;
81-
case 80: return CFI_type_extended_double;
82-
case 128: return CFI_type_float128;
83-
default: llvm_unreachable("unsupported real size");
84-
}
85-
// clang-format on
86-
}
87-
88-
static constexpr int derivedToTypeCode() { return CFI_type_struct; }
89-
20+
/// Return the ISO_Fortran_binding.h type code for mlir type \p ty.
21+
int getTypeCode(mlir::Type ty, KindMapping &kindMap);
9022
} // namespace fir
9123

9224
#endif // FORTRAN_OPTIMIZER_SUPPORT_TYPECODE_H

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 27 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,119 +1272,42 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
12721272
mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
12731273
mlir::Type boxEleTy, mlir::ValueRange lenParams = {}) const {
12741274
auto i64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
1275-
auto getKindMap = [&]() -> fir::KindMapping & {
1276-
return this->lowerTy().getKindMap();
1277-
};
1278-
auto doInteger =
1279-
[&](mlir::Type type,
1280-
unsigned width) -> std::tuple<mlir::Value, mlir::Value> {
1281-
int typeCode = fir::integerBitsToTypeCode(width);
1282-
return {
1283-
genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)),
1284-
this->genConstantOffset(loc, rewriter, typeCode)};
1285-
};
1286-
auto doLogical =
1287-
[&](mlir::Type type,
1288-
unsigned width) -> std::tuple<mlir::Value, mlir::Value> {
1289-
int typeCode = fir::logicalBitsToTypeCode(width);
1290-
return {
1291-
genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)),
1292-
this->genConstantOffset(loc, rewriter, typeCode)};
1293-
};
1294-
auto doFloat = [&](mlir::Type type,
1295-
unsigned width) -> std::tuple<mlir::Value, mlir::Value> {
1296-
int typeCode = fir::realBitsToTypeCode(width);
1297-
return {
1298-
genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)),
1299-
this->genConstantOffset(loc, rewriter, typeCode)};
1300-
};
1301-
auto doComplex =
1302-
[&](mlir::Type type,
1303-
unsigned width) -> std::tuple<mlir::Value, mlir::Value> {
1304-
auto typeCode = fir::complexBitsToTypeCode(width);
1305-
return {
1306-
genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)),
1307-
this->genConstantOffset(loc, rewriter, typeCode)};
1308-
};
1309-
auto doCharacter = [&](fir::CharacterType type, mlir::ValueRange lenParams)
1310-
-> std::tuple<mlir::Value, mlir::Value> {
1311-
unsigned bitWidth = getKindMap().getCharacterBitsize(type.getFKind());
1312-
auto typeCode = fir::characterBitsToTypeCode(bitWidth);
1313-
auto typeCodeVal = this->genConstantOffset(loc, rewriter, typeCode);
1314-
1315-
bool lengthIsConst = (type.getLen() != fir::CharacterType::unknownLen());
1316-
mlir::Value eleSize =
1317-
genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type));
1318-
1319-
if (!lengthIsConst) {
1320-
// If length is constant, then the fir::CharacterType will be
1321-
// represented as an array of known size of elements having
1322-
// the corresponding LLVM type. In this case eleSize already
1323-
// holds correct memory size. If length is not constant, then
1324-
// the fir::CharacterType will decay to a scalar type,
1325-
// so we have to multiply it by the non-constant length
1326-
// to get its size in memory.
1275+
if (auto eleTy = fir::dyn_cast_ptrEleTy(boxEleTy))
1276+
boxEleTy = eleTy;
1277+
if (auto seqTy = boxEleTy.dyn_cast<fir::SequenceType>())
1278+
return getSizeAndTypeCode(loc, rewriter, seqTy.getEleTy(), lenParams);
1279+
if (boxEleTy.isa<mlir::NoneType>()) // unlimited polymorphic or assumed type
1280+
return {rewriter.create<mlir::LLVM::ConstantOp>(loc, i64Ty, 0),
1281+
this->genConstantOffset(loc, rewriter, CFI_type_other)};
1282+
mlir::Value typeCodeVal = this->genConstantOffset(
1283+
loc, rewriter,
1284+
fir::getTypeCode(boxEleTy, this->lowerTy().getKindMap()));
1285+
if (fir::isa_integer(boxEleTy) || boxEleTy.dyn_cast<fir::LogicalType>() ||
1286+
fir::isa_real(boxEleTy) || fir::isa_complex(boxEleTy))
1287+
return {genTypeStrideInBytes(loc, i64Ty, rewriter,
1288+
this->convertType(boxEleTy)),
1289+
typeCodeVal};
1290+
if (auto charTy = boxEleTy.dyn_cast<fir::CharacterType>()) {
1291+
mlir::Value size =
1292+
genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(charTy));
1293+
if (charTy.getLen() == fir::CharacterType::unknownLen()) {
1294+
// Multiply the single character size by the length.
13271295
assert(!lenParams.empty());
13281296
auto len64 = FIROpConversion<OP>::integerCast(loc, rewriter, i64Ty,
13291297
lenParams.back());
1330-
eleSize =
1331-
rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, eleSize, len64);
1298+
size = rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, size, len64);
13321299
}
1333-
return {eleSize, typeCodeVal};
1300+
return {size, typeCodeVal};
13341301
};
1335-
// Pointer-like types.
1336-
if (auto eleTy = fir::dyn_cast_ptrEleTy(boxEleTy))
1337-
boxEleTy = eleTy;
1338-
// Integer types.
1339-
if (fir::isa_integer(boxEleTy)) {
1340-
if (auto ty = boxEleTy.dyn_cast<mlir::IntegerType>())
1341-
return doInteger(ty, ty.getWidth());
1342-
auto ty = boxEleTy.cast<fir::IntegerType>();
1343-
return doInteger(ty, getKindMap().getIntegerBitsize(ty.getFKind()));
1344-
}
1345-
// Floating point types.
1346-
if (fir::isa_real(boxEleTy)) {
1347-
if (auto ty = boxEleTy.dyn_cast<mlir::FloatType>())
1348-
return doFloat(ty, ty.getWidth());
1349-
auto ty = boxEleTy.cast<fir::RealType>();
1350-
return doFloat(ty, getKindMap().getRealBitsize(ty.getFKind()));
1351-
}
1352-
// Complex types.
1353-
if (fir::isa_complex(boxEleTy)) {
1354-
if (auto ty = boxEleTy.dyn_cast<mlir::ComplexType>())
1355-
return doComplex(
1356-
ty, ty.getElementType().cast<mlir::FloatType>().getWidth());
1357-
auto ty = boxEleTy.cast<fir::ComplexType>();
1358-
return doComplex(ty, getKindMap().getRealBitsize(ty.getFKind()));
1359-
}
1360-
// Character types.
1361-
if (auto ty = boxEleTy.dyn_cast<fir::CharacterType>())
1362-
return doCharacter(ty, lenParams);
1363-
// Logical type.
1364-
if (auto ty = boxEleTy.dyn_cast<fir::LogicalType>())
1365-
return doLogical(ty, getKindMap().getLogicalBitsize(ty.getFKind()));
1366-
// Array types.
1367-
if (auto seqTy = boxEleTy.dyn_cast<fir::SequenceType>())
1368-
return getSizeAndTypeCode(loc, rewriter, seqTy.getEleTy(), lenParams);
1369-
// Derived-type types.
1370-
if (boxEleTy.isa<fir::RecordType>()) {
1371-
auto eleSize = genTypeStrideInBytes(loc, i64Ty, rewriter,
1372-
this->convertType(boxEleTy));
1373-
return {eleSize,
1374-
this->genConstantOffset(loc, rewriter, fir::derivedToTypeCode())};
1375-
}
1376-
// Reference type.
13771302
if (fir::isa_ref_type(boxEleTy)) {
13781303
auto ptrTy = mlir::LLVM::LLVMPointerType::get(
13791304
mlir::LLVM::LLVMVoidType::get(rewriter.getContext()));
1380-
mlir::Value size = genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy);
1381-
return {size, this->genConstantOffset(loc, rewriter, CFI_type_cptr)};
1305+
return {genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy), typeCodeVal};
13821306
}
1383-
// Unlimited polymorphic or assumed type. Use 0 and CFI_type_other since the
1384-
// information is not none at this point.
1385-
if (boxEleTy.isa<mlir::NoneType>())
1386-
return {rewriter.create<mlir::LLVM::ConstantOp>(loc, i64Ty, 0),
1387-
this->genConstantOffset(loc, rewriter, CFI_type_other)};
1307+
if (boxEleTy.isa<fir::RecordType>())
1308+
return {genTypeStrideInBytes(loc, i64Ty, rewriter,
1309+
this->convertType(boxEleTy)),
1310+
typeCodeVal};
13881311
fir::emitFatalError(loc, "unhandled type in fir.box code generation");
13891312
}
13901313

flang/lib/Optimizer/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
33
add_flang_library(FIRSupport
44
InitFIR.cpp
55
InternalNames.cpp
6+
TypeCode.cpp
67

78
DEPENDS
89
FIROpsIncGen
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//===-- Optimizer/Support/TypeCode.cpp ------------------------------------===//
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+
#include "flang/Optimizer/Support/TypeCode.h"
10+
#include "flang/ISO_Fortran_binding.h"
11+
#include "flang/Optimizer/Dialect/FIRType.h"
12+
#include "llvm/Support/ErrorHandling.h"
13+
14+
namespace fir {
15+
16+
/// Return the ISO_C_BINDING intrinsic module value of type \p ty.
17+
int getTypeCode(mlir::Type ty, fir::KindMapping &kindMap) {
18+
unsigned width = 0;
19+
if (mlir::IntegerType intTy = ty.dyn_cast<mlir::IntegerType>()) {
20+
switch (intTy.getWidth()) {
21+
case 8:
22+
return CFI_type_int8_t;
23+
case 16:
24+
return CFI_type_int16_t;
25+
case 32:
26+
return CFI_type_int32_t;
27+
case 64:
28+
return CFI_type_int64_t;
29+
case 128:
30+
return CFI_type_int128_t;
31+
}
32+
llvm_unreachable("unsupported integer type");
33+
}
34+
if (fir::LogicalType logicalTy = ty.dyn_cast<fir::LogicalType>()) {
35+
switch (kindMap.getLogicalBitsize(logicalTy.getFKind())) {
36+
case 8:
37+
return CFI_type_Bool;
38+
case 16:
39+
return CFI_type_int_least16_t;
40+
case 32:
41+
return CFI_type_int_least32_t;
42+
case 64:
43+
return CFI_type_int_least64_t;
44+
}
45+
llvm_unreachable("unsupported logical type");
46+
}
47+
if (mlir::FloatType floatTy = ty.dyn_cast<mlir::FloatType>()) {
48+
switch (floatTy.getWidth()) {
49+
case 16:
50+
return floatTy.isBF16() ? CFI_type_bfloat : CFI_type_half_float;
51+
case 32:
52+
return CFI_type_float;
53+
case 64:
54+
return CFI_type_double;
55+
case 80:
56+
return CFI_type_extended_double;
57+
case 128:
58+
return CFI_type_float128;
59+
}
60+
llvm_unreachable("unsupported real type");
61+
}
62+
if (fir::isa_complex(ty)) {
63+
if (mlir::ComplexType complexTy = ty.dyn_cast<mlir::ComplexType>()) {
64+
mlir::FloatType floatTy =
65+
complexTy.getElementType().cast<mlir::FloatType>();
66+
if (floatTy.isBF16())
67+
return CFI_type_bfloat_Complex;
68+
width = floatTy.getWidth();
69+
} else if (fir::ComplexType complexTy = ty.dyn_cast<fir::ComplexType>()) {
70+
auto FKind = complexTy.getFKind();
71+
if (FKind == 3)
72+
return CFI_type_bfloat_Complex;
73+
width = kindMap.getRealBitsize(FKind);
74+
}
75+
switch (width) {
76+
case 16:
77+
return CFI_type_half_float_Complex;
78+
case 32:
79+
return CFI_type_float_Complex;
80+
case 64:
81+
return CFI_type_double_Complex;
82+
case 80:
83+
return CFI_type_extended_double_Complex;
84+
case 128:
85+
return CFI_type_float128_Complex;
86+
}
87+
llvm_unreachable("unsupported complex size");
88+
}
89+
if (fir::CharacterType charTy = ty.dyn_cast<fir::CharacterType>()) {
90+
switch (kindMap.getCharacterBitsize(charTy.getFKind())) {
91+
case 8:
92+
return CFI_type_char;
93+
case 16:
94+
return CFI_type_char16_t;
95+
case 32:
96+
return CFI_type_char32_t;
97+
}
98+
llvm_unreachable("unsupported character type");
99+
}
100+
if (fir::isa_ref_type(ty))
101+
return CFI_type_cptr;
102+
if (ty.isa<fir::RecordType>())
103+
return CFI_type_struct;
104+
llvm_unreachable("unsupported type");
105+
}
106+
107+
} // namespace fir

0 commit comments

Comments
 (0)