Skip to content

Commit 21d2991

Browse files
[Flang] Enable support for conversion of recursive record types
Uses the recursive type conversion implemented in D113579, D113580. Tests check for recursive and mutually recursive types. Note: The downstream implementation for recursive types is a bit old and is based on a static map. This was removed while upstreaming (https://reviews.llvm.org/D112961) based on review comments. Since the recursive type conversion is now available in MLIR we are using that. If this patch is accepted we can use the same in the downstream implementation. Part of upstreaming flang from fir-dev branch of https://github.com/flang-compiler/f18-llvm-project. Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D115937 Co-authored-by: Eric Schweitz <[email protected]>
1 parent 4c2aba9 commit 21d2991

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

flang/lib/Optimizer/CodeGen/TypeConverter.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
8080
});
8181
addConversion(
8282
[&](fir::PointerType pointer) { return convertPointerLike(pointer); });
83-
addConversion(
84-
[&](fir::RecordType derived) { return convertRecordType(derived); });
83+
addConversion([&](fir::RecordType derived, SmallVectorImpl<Type> &results,
84+
ArrayRef<Type> callStack) {
85+
return convertRecordType(derived, results, callStack);
86+
});
8587
addConversion([&](fir::FieldType field) {
8688
// Convert to i32 because of LLVM GEP indexing restriction.
8789
return mlir::IntegerType::get(field.getContext(), 32);
@@ -127,16 +129,23 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
127129
mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); }
128130

129131
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
130-
mlir::Type convertRecordType(fir::RecordType derived) {
132+
llvm::Optional<LogicalResult>
133+
convertRecordType(fir::RecordType derived, SmallVectorImpl<Type> &results,
134+
ArrayRef<Type> callStack) {
131135
auto name = derived.getName();
132136
auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
137+
if (llvm::count(callStack, derived) > 1) {
138+
results.push_back(st);
139+
return success();
140+
}
133141
llvm::SmallVector<mlir::Type> members;
134142
for (auto mem : derived.getTypeList()) {
135143
members.push_back(convertType(mem.second).cast<mlir::Type>());
136144
}
137-
if (mlir::succeeded(st.setBody(members, /*isPacked=*/false)))
138-
return st;
139-
return mlir::Type();
145+
if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
146+
return failure();
147+
results.push_back(st);
148+
return success();
140149
}
141150

142151
// Is an extended descriptor needed given the element type of a fir.box type ?

flang/test/Fir/recursive-type.fir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Test lowering FIR to LLVM IR for recursive types
2+
3+
// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
4+
// RUN: fir-opt --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
5+
// RUN: fir-opt --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s
6+
// RUN: fir-opt --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s
7+
8+
!t1 = type !fir.type<t1 {a1:!fir.ptr<!fir.type<t1>>}>
9+
!t2 = type !fir.type<t2 {b1:f32,b2:!fir.ptr<!fir.type<t2>>,b3:i32,b4:!fir.ptr<!fir.type<t2>>}>
10+
!t3 = type !fir.type<t3 {c1:!fir.ptr<!fir.type<t4>>}>
11+
!t4 = type !fir.type<t4 {d1:!fir.ptr<!fir.type<t3>>}>
12+
13+
// CHECK-LABEL: llvm.func @recursiveTypes
14+
// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T1:.*]]", (ptr<struct<"[[T1]]">>)>
15+
// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T2:.*]]", (f32, ptr<struct<"[[T2]]">>, i32, ptr<struct<"[[T2]]">>)>
16+
// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T3:.*]]", (ptr<struct<"[[T4:.*]]", (ptr<struct<"[[T3]]">>)>>)>, %{{.*}}: !llvm.struct<"[[T4]]", (ptr<struct<"[[T3]]", (ptr<struct<"[[T4]]">>)>>)>)
17+
func @recursiveTypes(%a : !t1, %b : !t2, %c : !t3, %d : !t4) {
18+
return
19+
}

0 commit comments

Comments
 (0)