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 @@ -111,11 +111,15 @@ }); addConversion([&](mlir::TupleType tuple) { LLVM_DEBUG(llvm::dbgs() << "type convert: " << tuple << '\n'); - llvm::SmallVector inMembers; - tuple.getFlattenedTypes(inMembers); llvm::SmallVector members; - for (auto mem : inMembers) - members.push_back(convertType(mem).cast()); + for (auto mem : tuple.getTypes()) { + // Prevent fir.box from degenerating to a pointer to a descriptor in the + // context of a tuple type. + if (auto box = mem.dyn_cast()) + members.push_back(convertBoxTypeAsStruct(box)); + else + members.push_back(convertType(mem).cast()); + } return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), members, /*isPacked=*/false); }); @@ -140,7 +144,12 @@ } llvm::SmallVector members; for (auto mem : derived.getTypeList()) { - members.push_back(convertType(mem.second).cast()); + // Prevent fir.box from degenerating to a pointer to a descriptor in the + // context of a record type. + if (auto box = mem.second.dyn_cast()) + members.push_back(convertBoxTypeAsStruct(box)); + else + members.push_back(convertType(mem.second).cast()); } if (mlir::failed(st.setBody(members, /*isPacked=*/false))) return failure(); @@ -227,6 +236,14 @@ /*isPacked=*/false)); } + /// Convert fir.box type to the corresponding llvm struct type instead of a + /// pointer to this struct type. + mlir::Type convertBoxTypeAsStruct(BoxType box) { + return convertBoxType(box) + .cast() + .getElementType(); + } + unsigned characterBitsize(fir::CharacterType charTy) { return kindMapping.getCharacterBitsize(charTy.getFKind()); } diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -61,11 +61,11 @@ } bool verifyRecordMemberType(mlir::Type ty) { - return !(ty.isa() || ty.isa() || - ty.isa() || ty.isa() || - ty.isa() || ty.isa() || - ty.isa() || ty.isa() || ty.isa() || - ty.isa() || ty.isa()); + return !(ty.isa() || ty.isa() || + ty.isa() || ty.isa() || + ty.isa() || ty.isa() || ty.isa() || + ty.isa() || ty.isa() || + ty.isa()); } bool verifySameLists(llvm::ArrayRef a1, diff --git a/flang/test/Fir/types-to-llvm.fir b/flang/test/Fir/types-to-llvm.fir --- a/flang/test/Fir/types-to-llvm.fir +++ b/flang/test/Fir/types-to-llvm.fir @@ -400,3 +400,21 @@ func private @foo3(%arg : !fir.tdesc>) // CHECK-LABEL: foo3 // CHECK-SAME: !llvm.ptr + +// ----- + +// Test nested tuple types +func private @foo0(%arg0: tuple>) +// CHECK-LABEL: foo0 +// CHECK-SAME: !llvm.struct<(i64, struct<(f32, i64)>)> + +// ----- + +// Test that fir.box inside tuple and derived type are lowered to struct type. +func private @foo0(%arg0: tuple>) +// CHECK-LABEL: foo0 +// CHECK-SAME: !llvm.struct<(i64, struct<(ptr, i{{.*}})>)> + +func private @foo1(%arg0: !fir.type}>) +// CHECK-LABEL: foo1 +// CHECK-SAME: !llvm.struct<"derived8", (i64, struct<(ptr, i{{.*}})>)>