diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -852,42 +852,48 @@ static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *StringLength, - Metadata *StrLenExp, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, - StorageType Storage, bool ShouldCreate = true) { + Metadata *StrLenExp, Metadata *StrLocationExp, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - StringLength, StrLenExp, SizeInBits, AlignInBits, Encoding, - Storage, ShouldCreate); + StringLength, StrLenExp, StrLocationExp, SizeInBits, + AlignInBits, Encoding, Storage, ShouldCreate); } static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *StringLength, - Metadata *StrLenExp, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, - StorageType Storage, bool ShouldCreate = true); + Metadata *StrLenExp, Metadata *StrLocationExp, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, StorageType Storage, + bool ShouldCreate = true); TempDIStringType cloneImpl() const { return getTemporary(getContext(), getTag(), getRawName(), getRawStringLength(), getRawStringLengthExp(), - getSizeInBits(), getAlignInBits(), getEncoding()); + getRawStringLocationExp(), getSizeInBits(), + getAlignInBits(), getEncoding()); } public: DEFINE_MDNODE_GET(DIStringType, (unsigned Tag, StringRef Name, uint64_t SizeInBits, uint32_t AlignInBits), - (Tag, Name, nullptr, nullptr, SizeInBits, AlignInBits, 0)) + (Tag, Name, nullptr, nullptr, nullptr, SizeInBits, + AlignInBits, 0)) DEFINE_MDNODE_GET(DIStringType, (unsigned Tag, MDString *Name, Metadata *StringLength, - Metadata *StringLengthExp, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding), - (Tag, Name, StringLength, StringLengthExp, SizeInBits, - AlignInBits, Encoding)) + Metadata *StringLengthExp, Metadata *StringLocationExp, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding), + (Tag, Name, StringLength, StringLengthExp, + StringLocationExp, SizeInBits, AlignInBits, Encoding)) DEFINE_MDNODE_GET(DIStringType, (unsigned Tag, StringRef Name, Metadata *StringLength, - Metadata *StringLengthExp, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding), - (Tag, Name, StringLength, StringLengthExp, SizeInBits, - AlignInBits, Encoding)) + Metadata *StringLengthExp, Metadata *StringLocationExp, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding), + (Tag, Name, StringLength, StringLengthExp, + StringLocationExp, SizeInBits, AlignInBits, Encoding)) TempDIStringType clone() const { return cloneImpl(); } @@ -903,11 +909,17 @@ return cast_or_null(getRawStringLengthExp()); } + DIExpression *getStringLocationExp() const { + return cast_or_null(getRawStringLocationExp()); + } + unsigned getEncoding() const { return Encoding; } Metadata *getRawStringLength() const { return getOperand(3); } Metadata *getRawStringLengthExp() const { return getOperand(4); } + + Metadata *getRawStringLocationExp() const { return getOperand(5); } }; /// Derived types. diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4550,16 +4550,17 @@ OPTIONAL(name, MDStringField, ); \ OPTIONAL(stringLength, MDField, ); \ OPTIONAL(stringLengthExpression, MDField, ); \ + OPTIONAL(stringLocationExpression, MDField, ); \ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DIStringType, - (Context, tag.Val, name.Val, stringLength.Val, - stringLengthExpression.Val, size.Val, align.Val, - encoding.Val)); + Result = GET_OR_DISTINCT( + DIStringType, + (Context, tag.Val, name.Val, stringLength.Val, stringLengthExpression.Val, + stringLocationExpression.Val, size.Val, align.Val, encoding.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1423,15 +1423,21 @@ break; } case bitc::METADATA_STRING_TYPE: { - if (Record.size() != 8) + if (Record.size() > 9 || Record.size() < 8) return error("Invalid record"); IsDistinct = Record[0]; + bool SizeIs8 = Record.size() == 8; + // StringLocationExp (i.e. Record[5]) is added at a later time + // than the other fields. The code here enables backward compatibility. + Metadata *StringLocationExp = SizeIs8 ? nullptr : getMDOrNull(Record[5]); + unsigned Offset = SizeIs8 ? 5 : 6; MetadataList.assignValue( GET_OR_DISTINCT(DIStringType, (Context, Record[1], getMDString(Record[2]), getMDOrNull(Record[3]), getMDOrNull(Record[4]), - Record[5], Record[6], Record[7])), + StringLocationExp, Record[Offset], Record[Offset + 1], + Record[Offset + 2])), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1657,6 +1657,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getStringLength())); Record.push_back(VE.getMetadataOrNullID(N->getStringLengthExp())); + Record.push_back(VE.getMetadataOrNullID(N->getStringLocationExp())); Record.push_back(N->getSizeInBits()); Record.push_back(N->getAlignInBits()); Record.push_back(N->getEncoding()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -742,6 +742,16 @@ addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size); } + if (DIExpression *Expr = STy->getStringLocationExp()) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc); + // This is to describe the memory location of the + // string, so lock it down as such. + DwarfExpr.setMemoryLocationKind(); + DwarfExpr.addExpression(Expr); + addBlock(Buffer, dwarf::DW_AT_data_location, DwarfExpr.finalize()); + } + if (STy->getEncoding()) { // For eventual Unicode support. addUInt(Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1986,6 +1986,8 @@ Printer.printString("name", N->getName()); Printer.printMetadata("stringLength", N->getRawStringLength()); Printer.printMetadata("stringLengthExpression", N->getRawStringLengthExp()); + Printer.printMetadata("stringLocationExpression", + N->getRawStringLocationExp()); Printer.printInt("size", N->getSizeInBits()); Printer.printInt("align", N->getAlignInBits()); Printer.printDwarfEnum("encoding", N->getEncoding(), diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -567,13 +567,16 @@ DIStringType *DIStringType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *StringLength, Metadata *StringLengthExp, + Metadata *StringLocationExp, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DIStringType, (Tag, Name, StringLength, StringLengthExp, - SizeInBits, AlignInBits, Encoding)); - Metadata *Ops[] = {nullptr, nullptr, Name, StringLength, StringLengthExp}; + DEFINE_GETIMPL_LOOKUP(DIStringType, + (Tag, Name, StringLength, StringLengthExp, + StringLocationExp, SizeInBits, AlignInBits, Encoding)); + Metadata *Ops[] = {nullptr, nullptr, Name, + StringLength, StringLengthExp, StringLocationExp}; DEFINE_GETIMPL_STORE(DIStringType, (Tag, SizeInBits, AlignInBits, Encoding), Ops); } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -428,20 +428,22 @@ MDString *Name; Metadata *StringLength; Metadata *StringLengthExp; + Metadata *StringLocationExp; uint64_t SizeInBits; uint32_t AlignInBits; unsigned Encoding; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *StringLength, - Metadata *StringLengthExp, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding) + Metadata *StringLengthExp, Metadata *StringLocationExp, + uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding) : Tag(Tag), Name(Name), StringLength(StringLength), - StringLengthExp(StringLengthExp), SizeInBits(SizeInBits), - AlignInBits(AlignInBits), Encoding(Encoding) {} + StringLengthExp(StringLengthExp), StringLocationExp(StringLocationExp), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding) {} MDNodeKeyImpl(const DIStringType *N) : Tag(N->getTag()), Name(N->getRawName()), StringLength(N->getRawStringLength()), StringLengthExp(N->getRawStringLengthExp()), + StringLocationExp(N->getRawStringLocationExp()), SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()) {} diff --git a/llvm/test/Bitcode/distringtype-backward.ll b/llvm/test/Bitcode/distringtype-backward.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/distringtype-backward.ll @@ -0,0 +1,47 @@ +; This test verifies the backward compatibility of DIStringType. +;; Specifically, it makes sure that bitcode for DIStringType without +;; the StringLocationExp field can be disassembled. +; REQUIRES: x86_64-linux + +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +; CHECK: !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8)) + +; ModuleID = 'distringtype-backward.bc' +source_filename = "distringtype.f90" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%"QNCA_a0$i8*$rank0$" = type { i8*, i64, i64, i64, i64, i64 } + +@"assumedlength_$DEFERRED" = internal global %"QNCA_a0$i8*$rank0$" zeroinitializer, !dbg !0 +@0 = internal unnamed_addr constant i32 2 + +; Function Attrs: noinline nounwind optnone uwtable +define void @MAIN__() #0 !dbg !2 { +alloca_0: + ret void +} + +declare i32 @for_set_reentrancy(i32* nocapture readonly) + +declare i32 @for_alloc_allocatable_handle(i64, i8** nocapture, i32, i8*) + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "intel-lang"="fortran" "target-cpu"="x86-64" } + +!llvm.module.flags = !{!10, !11} +!llvm.dbg.cu = !{!6} +!omp_offload.info = !{} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "deferred", linkageName: "assumedlength_$DEFERRED", scope: !2, file: !3, line: 2, type: !9, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "assumedlength", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !6, retainedNodes: !8) +!3 = !DIFile(filename: "test2.f90", directory: "/iusers/cchen15/examples/tests/jr33383") +!4 = !DISubroutineType(types: !5) +!5 = !{null} +!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 22.0-1258", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !7, splitDebugInlining: false, nameTableKind: None) +!7 = !{!0} +!8 = !{} +!9 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8)) +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 2, !"Dwarf Version", i32 4} diff --git a/llvm/test/Bitcode/distringtype-backward.ll.bc b/llvm/test/Bitcode/distringtype-backward.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@