diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index e387e27533a00..0337bfa573fb3 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -271,6 +271,19 @@ static bool canCacheThisType(mlir::LLVM::DICompositeTypeAttr comTy) { return true; } +std::pair +DebugTypeGenerator::getFieldSizeAndAlign(mlir::Type fieldTy) { + mlir::Type llvmTy; + if (auto boxTy = mlir::dyn_cast_or_null(fieldTy)) + llvmTy = llvmTypeConverter.convertBoxTypeAsStruct(boxTy, getBoxRank(boxTy)); + else + llvmTy = llvmTypeConverter.convertType(fieldTy); + + uint64_t byteSize = dataLayout->getTypeSize(llvmTy); + unsigned short byteAlign = dataLayout->getTypeABIAlignment(llvmTy); + return std::pair{byteSize, byteAlign}; +} + mlir::LLVM::DITypeAttr DebugTypeGenerator::convertRecordType( fir::RecordType Ty, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp) { @@ -303,15 +316,7 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertRecordType( mlir::IntegerType intTy = mlir::IntegerType::get(context, 64); std::uint64_t offset = 0; for (auto [fieldName, fieldTy] : Ty.getTypeList()) { - mlir::Type llvmTy; - if (auto boxTy = mlir::dyn_cast_or_null(fieldTy)) - llvmTy = - llvmTypeConverter.convertBoxTypeAsStruct(boxTy, getBoxRank(boxTy)); - else - llvmTy = llvmTypeConverter.convertType(fieldTy); - - uint64_t byteSize = dataLayout->getTypeSize(llvmTy); - unsigned short byteAlign = dataLayout->getTypeABIAlignment(llvmTy); + auto [byteSize, byteAlign] = getFieldSizeAndAlign(fieldTy); std::optional> lowerBounds = fir::getComponentLowerBoundsIfNonDefault(Ty, fieldName, module, symbolTable); @@ -368,6 +373,42 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertRecordType( return finalAttr; } +mlir::LLVM::DITypeAttr DebugTypeGenerator::convertTupleType( + mlir::TupleType Ty, mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp) { + // Check if this type has already been converted. + auto iter = typeCache.find(Ty); + if (iter != typeCache.end()) + return iter->second; + + llvm::SmallVector elements; + mlir::MLIRContext *context = module.getContext(); + + std::uint64_t offset = 0; + for (auto fieldTy : Ty.getTypes()) { + auto [byteSize, byteAlign] = getFieldSizeAndAlign(fieldTy); + mlir::LLVM::DITypeAttr elemTy = + convertType(fieldTy, fileAttr, scope, /*declOp=*/nullptr); + offset = llvm::alignTo(offset, byteAlign); + mlir::LLVM::DIDerivedTypeAttr tyAttr = mlir::LLVM::DIDerivedTypeAttr::get( + context, llvm::dwarf::DW_TAG_member, mlir::StringAttr::get(context, ""), + elemTy, byteSize * 8, byteAlign * 8, offset * 8, + /*optional
=*/std::nullopt, + /*extra data=*/nullptr); + elements.push_back(tyAttr); + offset += llvm::alignTo(byteSize, byteAlign); + } + + auto typeAttr = mlir::LLVM::DICompositeTypeAttr::get( + context, llvm::dwarf::DW_TAG_structure_type, + mlir::StringAttr::get(context, ""), fileAttr, /*line=*/0, scope, + /*baseType=*/nullptr, mlir::LLVM::DIFlags::Zero, offset * 8, + /*alignInBits=*/0, elements, /*dataLocation=*/nullptr, /*rank=*/nullptr, + /*allocated=*/nullptr, /*associated=*/nullptr); + typeCache[Ty] = typeAttr; + return typeAttr; +} + mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType( fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp) { @@ -574,6 +615,8 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, /*hasDescriptor=*/false); } else if (auto recTy = mlir::dyn_cast_or_null(Ty)) { return convertRecordType(recTy, fileAttr, scope, declOp); + } else if (auto tupleTy = mlir::dyn_cast_if_present(Ty)) { + return convertTupleType(tupleTy, fileAttr, scope, declOp); } else if (auto refTy = mlir::dyn_cast_if_present(Ty)) { auto elTy = refTy.getEleTy(); return convertPointerLikeType(elTy, fileAttr, scope, declOp, diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h index eeefb6c463d93..c1fce4bdae5ce 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h @@ -39,6 +39,10 @@ class DebugTypeGenerator { mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp); + mlir::LLVM::DITypeAttr convertTupleType(mlir::TupleType Ty, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope, + fir::cg::XDeclareOp declOp); mlir::LLVM::DITypeAttr convertSequenceType(fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, @@ -73,6 +77,8 @@ class DebugTypeGenerator { mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp); + std::pair + getFieldSizeAndAlign(mlir::Type fieldTy); mlir::ModuleOp module; mlir::SymbolTable *symbolTable; diff --git a/flang/test/Transforms/debug-tuple-type.fir b/flang/test/Transforms/debug-tuple-type.fir new file mode 100644 index 0000000000000..c9b0d16c06e1a --- /dev/null +++ b/flang/test/Transforms/debug-tuple-type.fir @@ -0,0 +1,15 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<>} { + func.func private @fn1(!fir.ref>) + func.func private @_FortranAioOutputDerivedType(!fir.ref>) +} + +// CHECK: #[[F64:.*]] = #llvm.di_basic_type +// CHECK: #[[CU:.*]] = #llvm.di_compile_unit<{{.*}}> +// CHECK: #[[DTY1:.*]] = #llvm.di_derived_type +// CHECK: #[[DTY2:.*]] = #llvm.di_derived_type +// CHECK: #[[COM_TY1:.*]] = #llvm.di_composite_type +// CHECK: #[[COM_TY2:.*]] = #llvm.di_composite_type +// CHECK: #llvm.di_subroutine_type +// CHECK: #llvm.di_subroutine_type