From 3a57925b071f16c64af6a729078dce58510a0da9 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Mon, 24 Jun 2024 18:04:19 +0100 Subject: [flang][debug] Handle allocatable strings. (#95906) The allocatable strings also use DIStringType but provide dwarf expressions to find the location and length of the string. With this change in place, the debugging of the allocatable strings looks like this: character(len=:), allocatable :: first character(len=:), allocatable :: second character(len=:), allocatable :: third first = 'Mount' second = 'Everest' third = first // " " // second print *, third (gdb) p third $1 = "" (gdb) n 18 print *, third (gdb) p third $2 = 'Mount Everest' (gdb) ptype third type = character (13) --- .../Optimizer/Transforms/DebugTypeGenerator.cpp | 42 +++++++++++++++++----- .../lib/Optimizer/Transforms/DebugTypeGenerator.h | 4 ++- flang/test/Integration/debug-char-type-1.f90 | 6 +++- flang/test/Transforms/debug-char-type-1.fir | 9 ++++- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index 407ecc8..0673070 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 7816363..ec881e8 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h @@ -48,7 +48,8 @@ private: 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 @@ private: 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 a0aebd3..5068663 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 cdce3b7..630b52d 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]]{{.*}}> -- cgit v1.1