summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKiran Chandramohan <kiran.chandramohan@arm.com>2022-01-04 13:43:40 +0000
committerKiran Chandramohan <kiran.chandramohan@arm.com>2022-01-04 13:53:58 +0000
commit21d299172e23a37fc251ce69dc31032a6a4a2bfe (patch)
tree05b023f782eb399ff9ff607ad57c8644014ad3b4
parent4c2aba999e54270871d5ff8f6c765e8b834dfe27 (diff)
downloadllvm-21d299172e23a37fc251ce69dc31032a6a4a2bfe.tar.gz
[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 <eschweitz@nvidia.com>
-rw-r--r--flang/lib/Optimizer/CodeGen/TypeConverter.h21
-rw-r--r--flang/test/Fir/recursive-type.fir19
2 files changed, 34 insertions, 6 deletions
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h
index 91e8ebfea7d7..d96b752be1b8 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.h
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h
@@ -80,8 +80,10 @@ public:
});
addConversion(
[&](fir::PointerType pointer) { return convertPointerLike(pointer); });
- addConversion(
- [&](fir::RecordType derived) { return convertRecordType(derived); });
+ addConversion([&](fir::RecordType derived, SmallVectorImpl<Type> &results,
+ ArrayRef<Type> callStack) {
+ return convertRecordType(derived, results, callStack);
+ });
addConversion([&](fir::FieldType field) {
// Convert to i32 because of LLVM GEP indexing restriction.
return mlir::IntegerType::get(field.getContext(), 32);
@@ -127,16 +129,23 @@ public:
mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); }
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
- mlir::Type convertRecordType(fir::RecordType derived) {
+ llvm::Optional<LogicalResult>
+ convertRecordType(fir::RecordType derived, SmallVectorImpl<Type> &results,
+ ArrayRef<Type> callStack) {
auto name = derived.getName();
auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
+ if (llvm::count(callStack, derived) > 1) {
+ results.push_back(st);
+ return success();
+ }
llvm::SmallVector<mlir::Type> members;
for (auto mem : derived.getTypeList()) {
members.push_back(convertType(mem.second).cast<mlir::Type>());
}
- if (mlir::succeeded(st.setBody(members, /*isPacked=*/false)))
- return st;
- return mlir::Type();
+ if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
+ return failure();
+ results.push_back(st);
+ return success();
}
// Is an extended descriptor needed given the element type of a fir.box type ?
diff --git a/flang/test/Fir/recursive-type.fir b/flang/test/Fir/recursive-type.fir
new file mode 100644
index 000000000000..bd97f9e6225e
--- /dev/null
+++ b/flang/test/Fir/recursive-type.fir
@@ -0,0 +1,19 @@
+// Test lowering FIR to LLVM IR for recursive types
+
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
+// RUN: fir-opt --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
+// RUN: fir-opt --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s
+// RUN: fir-opt --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s
+
+!t1 = type !fir.type<t1 {a1:!fir.ptr<!fir.type<t1>>}>
+!t2 = type !fir.type<t2 {b1:f32,b2:!fir.ptr<!fir.type<t2>>,b3:i32,b4:!fir.ptr<!fir.type<t2>>}>
+!t3 = type !fir.type<t3 {c1:!fir.ptr<!fir.type<t4>>}>
+!t4 = type !fir.type<t4 {d1:!fir.ptr<!fir.type<t3>>}>
+
+// CHECK-LABEL: llvm.func @recursiveTypes
+// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T1:.*]]", (ptr<struct<"[[T1]]">>)>
+// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T2:.*]]", (f32, ptr<struct<"[[T2]]">>, i32, ptr<struct<"[[T2]]">>)>
+// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T3:.*]]", (ptr<struct<"[[T4:.*]]", (ptr<struct<"[[T3]]">>)>>)>, %{{.*}}: !llvm.struct<"[[T4]]", (ptr<struct<"[[T3]]", (ptr<struct<"[[T4]]">>)>>)>)
+func @recursiveTypes(%a : !t1, %b : !t2, %c : !t3, %d : !t4) {
+ return
+}