diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index 407ecc8e327b4..0673070af362c 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -61,9 +61,11 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m) // descriptors like lower_bound and extent for each dimension. mlir::Type llvmDimsType = getDescFieldTypeModel()(context); mlir::Type llvmPtrType = getDescFieldTypeModel()(context); + mlir::Type llvmLenType = getDescFieldTypeModel()(context); dimsOffset = getComponentOffset(*dl, context, llvmDimsType); dimsSize = dl->getTypeSize(llvmDimsType); ptrSize = dl->getTypeSize(llvmPtrType); + lenOffset = getComponentOffset(*dl, context, llvmLenType); } static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, @@ -192,10 +194,8 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType( mlir::LLVM::DITypeAttr DebugTypeGenerator::convertCharacterType( fir::CharacterType charTy, mlir::LLVM::DIFileAttr fileAttr, - mlir::LLVM::DIScopeAttr scope, mlir::Location loc) { + mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool hasDescriptor) { mlir::MLIRContext *context = module.getContext(); - if (!charTy.hasConstantLen()) - return genPlaceholderType(context); // DWARF 5 says the following about the character encoding in 5.1.1.2. // "DW_ATE_ASCII and DW_ATE_UCS specify encodings for the Fortran 2003 @@ -205,16 +205,38 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertCharacterType( if (charTy.getFKind() != 1) encoding = llvm::dwarf::DW_ATE_UCS; + uint64_t sizeInBits = 0; + mlir::LLVM::DIExpressionAttr lenExpr = nullptr; + mlir::LLVM::DIExpressionAttr locExpr = nullptr; + + if (hasDescriptor) { + llvm::SmallVector ops; + auto addOp = [&](unsigned opc, llvm::ArrayRef vals) { + ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(context, opc, vals)); + }; + addOp(llvm::dwarf::DW_OP_push_object_address, {}); + addOp(llvm::dwarf::DW_OP_plus_uconst, {lenOffset}); + lenExpr = mlir::LLVM::DIExpressionAttr::get(context, ops); + ops.clear(); + + addOp(llvm::dwarf::DW_OP_push_object_address, {}); + addOp(llvm::dwarf::DW_OP_deref, {}); + locExpr = mlir::LLVM::DIExpressionAttr::get(context, ops); + } else if (charTy.hasConstantLen()) { + sizeInBits = + charTy.getLen() * kindMapping.getCharacterBitsize(charTy.getFKind()); + } else { + return genPlaceholderType(context); + } + // FIXME: Currently the DIStringType in llvm does not have the option to set // type of the underlying character. This restricts out ability to represent // string with non-default characters. Please see issue #95440 for more // details. return mlir::LLVM::DIStringTypeAttr::get( context, llvm::dwarf::DW_TAG_string_type, - mlir::StringAttr::get(context, ""), - charTy.getLen() * kindMapping.getCharacterBitsize(charTy.getFKind()), - /*alignInBits=*/0, /*stringLength=*/nullptr, - /*stringLengthExp=*/nullptr, /*stringLocationExp=*/nullptr, encoding); + mlir::StringAttr::get(context, ""), sizeInBits, /*alignInBits=*/0, + /*stringLength=*/nullptr, lenExpr, locExpr, encoding); } mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType( @@ -229,6 +251,9 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType( if (auto seqTy = mlir::dyn_cast_or_null(elTy)) return convertBoxedSequenceType(seqTy, fileAttr, scope, loc, genAllocated, genAssociated); + if (auto charTy = mlir::dyn_cast_or_null(elTy)) + return convertCharacterType(charTy, fileAttr, scope, loc, + /*hasDescriptor=*/true); mlir::LLVM::DITypeAttr elTyAttr = convertType(elTy, fileAttr, scope, loc); @@ -274,7 +299,8 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, } else if (auto seqTy = mlir::dyn_cast_or_null(Ty)) { return convertSequenceType(seqTy, fileAttr, scope, loc); } else if (auto charTy = mlir::dyn_cast_or_null(Ty)) { - return convertCharacterType(charTy, fileAttr, scope, loc); + return convertCharacterType(charTy, fileAttr, scope, loc, + /*hasDescriptor=*/false); } else if (auto boxTy = mlir::dyn_cast_or_null(Ty)) { auto elTy = boxTy.getElementType(); if (auto seqTy = mlir::dyn_cast_or_null(elTy)) diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h index 7816363e98821..ec881e8be7cad 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h @@ -48,7 +48,8 @@ class DebugTypeGenerator { mlir::LLVM::DITypeAttr convertCharacterType(fir::CharacterType charTy, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, - mlir::Location loc); + mlir::Location loc, + bool hasDescriptor); mlir::LLVM::DITypeAttr convertPointerLikeType(mlir::Type elTy, mlir::LLVM::DIFileAttr fileAttr, @@ -60,6 +61,7 @@ class DebugTypeGenerator { std::uint64_t dimsSize; std::uint64_t dimsOffset; std::uint64_t ptrSize; + std::uint64_t lenOffset; }; } // namespace fir diff --git a/flang/test/Integration/debug-char-type-1.f90 b/flang/test/Integration/debug-char-type-1.f90 index a0aebd3125c6e..5068663aa9e28 100644 --- a/flang/test/Integration/debug-char-type-1.f90 +++ b/flang/test/Integration/debug-char-type-1.f90 @@ -2,6 +2,7 @@ module helper character(len=40) :: str + character(len=:), allocatable :: str2 end module helper program test @@ -11,11 +12,14 @@ program test first = '3.14 = π' second = 'Fortran' str = 'Hello World!' + str2 = 'A quick brown fox jumps over a lazy dog' end program test ! CHECK-DAG: !DIGlobalVariable(name: "str"{{.*}}type: ![[TY40:[0-9]+]]{{.*}}) ! CHECK-DAG: ![[TY40]] = !DIStringType(size: 320, encoding: DW_ATE_ASCII) +! CHECK-DAG: !DIGlobalVariable(name: "str2"{{.*}}type: ![[TY:[0-9]+]]{{.*}}) +! CHECK-DAG: ![[TY]] = !DIStringType(stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref), encoding: DW_ATE_ASCII) ! CHECK-DAG: !DILocalVariable(name: "first"{{.*}}type: ![[TY8:[0-9]+]]) ! CHECK-DAG: ![[TY8]] = !DIStringType(size: 256, encoding: DW_ATE_UCS) ! CHECK-DAG: !DILocalVariable(name: "second"{{.*}}type: ![[TY10:[0-9]+]]) -! CHECK-DAG: ![[TY10]] = !DIStringType(size: 80, encoding: DW_ATE_ASCII) \ No newline at end of file +! CHECK-DAG: ![[TY10]] = !DIStringType(size: 80, encoding: DW_ATE_ASCII) diff --git a/flang/test/Transforms/debug-char-type-1.fir b/flang/test/Transforms/debug-char-type-1.fir index cdce3b7b8b334..630b52d96cb85 100644 --- a/flang/test/Transforms/debug-char-type-1.fir +++ b/flang/test/Transforms/debug-char-type-1.fir @@ -9,6 +9,12 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} { %0 = fir.zero_bits !fir.char<4,20> fir.has_value %0 : !fir.char<4,20> } loc(#loc1) + fir.global @_QMhelperEstr3 : !fir.box>> { + %c0 = arith.constant 0 : index + %0 = fir.zero_bits !fir.heap> + %1 = fir.embox %0 typeparams %c0 : (!fir.heap>, index) -> !fir.box>> + fir.has_value %1 : !fir.box>> + } loc(#loc1) } #loc1 = loc("string.f90":1:1) @@ -16,4 +22,5 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} { // CHECK-DAG: #llvm.di_global_variable<{{.*}}name = "str1"{{.*}}type = #[[TY1]]{{.*}}> // CHECK-DAG: #[[TY2:.*]] = #llvm.di_string_type // CHECK-DAG: #llvm.di_global_variable<{{.*}}name = "str2"{{.*}}type = #[[TY2]]{{.*}}> - +// CHECK-DAG: #[[TY3:.*]] = #llvm.di_string_type, stringLocationExp = <[DW_OP_push_object_address, DW_OP_deref]>, encoding = DW_ATE_ASCII> +// CHECK-DAG: #llvm.di_global_variable<{{.*}}name = "str3"{{.*}}type = #[[TY3]]{{.*}}>