diff options
-rw-r--r-- | flang/lib/Optimizer/CodeGen/TypeConverter.h | 21 | ||||
-rw-r--r-- | flang/test/Fir/recursive-type.fir | 19 |
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 +} |