diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h --- a/flang/lib/Optimizer/CodeGen/TypeConverter.h +++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h @@ -80,8 +80,10 @@ }); addConversion( [&](fir::PointerType pointer) { return convertPointerLike(pointer); }); - addConversion( - [&](fir::RecordType derived) { return convertRecordType(derived); }); + addConversion([&](fir::RecordType derived, SmallVectorImpl &results, + ArrayRef 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 @@ mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); } // fir.type --> llvm<"%name = { ty... }"> - mlir::Type convertRecordType(fir::RecordType derived) { + llvm::Optional + convertRecordType(fir::RecordType derived, SmallVectorImpl &results, + ArrayRef 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 members; for (auto mem : derived.getTypeList()) { members.push_back(convertType(mem.second).cast()); } - 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 --- /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>}> +!t2 = type !fir.type>,b3:i32,b4:!fir.ptr>}> +!t3 = type !fir.type>}> +!t4 = type !fir.type>}> + +// CHECK-LABEL: llvm.func @recursiveTypes +// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T1:.*]]", (ptr>)> +// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T2:.*]]", (f32, ptr>, i32, ptr>)> +// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T3:.*]]", (ptr>)>>)>, %{{.*}}: !llvm.struct<"[[T4]]", (ptr>)>>)>) +func @recursiveTypes(%a : !t1, %b : !t2, %c : !t3, %d : !t4) { + return +}