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(); }
return cast_or_null<DIExpression>(getRawStringLengthExp());
}
+ DIExpression *getStringLocationExp() const {
+ return cast_or_null<DIExpression>(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.
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;
}
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;
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());
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,
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(),
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);
}
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()) {}
--- /dev/null
+; 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}
;; generates DW_AT_string_length attribute
;; !DIStringType(name: "character(*)", stringLength: !{{[0-9]+}})
;; !DIStringType(name: "character(*)", stringLengthExpr: !DIExpression(...))
+;;
+;; !DIStringType has an optional stringLocationExpr field. This
+;; tests also verifies that field gets emitted as DW_AT_data_location
+;; in the DIE.
; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
; CHECK: DW_TAG_string_type
; CHECK: DW_AT_name (".str.DEFERRED")
; CHECK-NEXT: DW_AT_string_length (DW_OP_push_object_address, DW_OP_plus_uconst 0x8)
+; CHECK-NEXT: DW_AT_data_location (DW_OP_push_object_address, DW_OP_deref)
; CHECK: DW_TAG_string_type
; CHECK: DW_AT_name ("character(*)!2")
; CHECK-NEXT: DW_AT_string_length
!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2142", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None)
!7 = !{}
!8 = !{!0}
-!9 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8))
+!9 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
!10 = !{i32 2, !"Debug Info Version", i32 3}
!11 = !{i32 2, !"Dwarf Version", i32 4}
!12 = !DILocation(line: 1, column: 9, scope: !2)
; CHECK: !DIStringType(name: "character(*)", stringLength: !{{[0-9]+}}, stringLengthExpression: !DIExpression(), size: 32)
; CHECK: !DIStringType(name: "character(10)", size: 80, align: 8)
; CHECK: !DIBasicType(tag: DW_TAG_string_type
-; CHECK: !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8))
+; CHECK: !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!11 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed)
!12 = !DIStringType(name: "character(10)", size: 80, align: 8)
!13 = !DIBasicType(tag: DW_TAG_string_type, name: "character")
-!14 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8))
+!14 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref))