1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[DebugInfo] support for DW_AT_data_location in llvm

This patch adds support for DWARF attribute DW_AT_data_location.

Summary:
Dynamic arrays in fortran are described by array descriptor and
data allocation address. Former is mapped to DW_AT_location and
later is mapped to DW_AT_data_location.

Testing:
unit test cases added (hand-written)
check llvm
check debug-info

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D79592
This commit is contained in:
Alok Kumar Sharma 2020-05-15 11:24:27 +05:30 committed by Sourabh Singh Tomar
parent 428c7cec26
commit 1daff0ecf4
17 changed files with 365 additions and 82 deletions

View File

@ -4810,7 +4810,12 @@ The following ``tag:`` values are valid:
For ``DW_TAG_array_type``, the ``elements:`` should be :ref:`subrange
descriptors <DISubrange>`, each representing the range of subscripts at that
level of indexing. The ``DIFlagVector`` flag to ``flags:`` indicates that an
array type is a native packed vector.
array type is a native packed vector. The optional ``dataLocation`` is a
DIExpression that describes how to get from an object's address to the actual
raw data, if they aren't equivalent. This is only supported for array types,
particularly to describe Fortran arrays, which have an array descriptor in
addition to the array data. Alternatively it can also be DIVariable which
has the address of the actual raw data.
For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator
descriptors <DIEnumerator>`, each representing the definition of an enumeration

View File

@ -931,13 +931,14 @@ class DICompositeType : public DIType {
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams, StringRef Identifier,
DIDerivedType *Discriminator, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(
Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
RuntimeLang, VTableHolder, TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator, Storage, ShouldCreate);
DIDerivedType *Discriminator, Metadata *DataLocation,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
Flags, Elements.get(), RuntimeLang, VTableHolder,
TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator,
DataLocation, Storage, ShouldCreate);
}
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@ -945,7 +946,7 @@ class DICompositeType : public DIType {
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator,
MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
StorageType Storage, bool ShouldCreate = true);
TempDICompositeType cloneImpl() const {
@ -953,34 +954,34 @@ class DICompositeType : public DIType {
getScope(), getBaseType(), getSizeInBits(),
getAlignInBits(), getOffsetInBits(), getFlags(),
getElements(), getRuntimeLang(), getVTableHolder(),
getTemplateParams(), getIdentifier(), getDiscriminator());
getTemplateParams(), getIdentifier(),
getDiscriminator(), getRawDataLocation());
}
public:
DEFINE_MDNODE_GET(DICompositeType,
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
DINodeArray Elements, unsigned RuntimeLang,
DIType *VTableHolder,
DITemplateParameterArray TemplateParams = nullptr,
StringRef Identifier = "",
DIDerivedType *Discriminator = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Identifier, Discriminator))
DEFINE_MDNODE_GET(DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File,
unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams = nullptr,
MDString *Identifier = nullptr,
Metadata *Discriminator = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Identifier, Discriminator))
DEFINE_MDNODE_GET(
DICompositeType,
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams = nullptr,
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
Metadata *DataLocation = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation))
DEFINE_MDNODE_GET(
DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr,
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation))
TempDICompositeType clone() const { return cloneImpl(); }
@ -997,7 +998,8 @@ public:
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator);
Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation);
static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
MDString &Identifier);
@ -1016,7 +1018,8 @@ public:
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator);
Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation);
DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
DINodeArray getElements() const {
@ -1038,6 +1041,13 @@ public:
MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
Metadata *getRawDiscriminator() const { return getOperand(8); }
DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); }
Metadata *getRawDataLocation() const { return getOperand(9); }
DIVariable *getDataLocation() const {
return dyn_cast_or_null<DIVariable>(getRawDataLocation());
}
DIExpression *getDataLocationExp() const {
return dyn_cast_or_null<DIExpression>(getRawDataLocation());
}
/// Replace operands.
///

View File

@ -4617,7 +4617,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(vtableHolder, MDField, ); \
OPTIONAL(templateParams, MDField, ); \
OPTIONAL(identifier, MDStringField, ); \
OPTIONAL(discriminator, MDField, );
OPTIONAL(discriminator, MDField, ); \
OPTIONAL(dataLocation, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
@ -4626,8 +4627,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
if (auto *CT = DICompositeType::buildODRType(
Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val,
scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val,
elements.Val, runtimeLang.Val, vtableHolder.Val,
templateParams.Val, discriminator.Val)) {
elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val,
discriminator.Val, dataLocation.Val)) {
Result = CT;
return false;
}
@ -4639,7 +4640,7 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
(Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val,
size.Val, align.Val, offset.Val, flags.Val, elements.Val,
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
discriminator.Val));
discriminator.Val, dataLocation.Val));
return false;
}

View File

@ -1340,7 +1340,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_COMPOSITE_TYPE: {
if (Record.size() < 16 || Record.size() > 17)
if (Record.size() < 16 || Record.size() > 18)
return error("Invalid record");
// If we have a UUID and this is not a forward declaration, lookup the
@ -1364,6 +1364,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Metadata *VTableHolder = nullptr;
Metadata *TemplateParams = nullptr;
Metadata *Discriminator = nullptr;
Metadata *DataLocation = nullptr;
auto *Identifier = getMDString(Record[15]);
// If this module is being parsed so that it can be ThinLTO imported
// into another module, composite types only need to be imported
@ -1386,13 +1387,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
TemplateParams = getMDOrNull(Record[14]);
if (Record.size() > 16)
Discriminator = getMDOrNull(Record[16]);
if (Record.size() > 17)
DataLocation = getMDOrNull(Record[17]);
}
DICompositeType *CT = nullptr;
if (Identifier)
CT = DICompositeType::buildODRType(
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Discriminator);
VTableHolder, TemplateParams, Discriminator, DataLocation);
// Create a node if we didn't get a lazy ODR type.
if (!CT)
@ -1400,7 +1403,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
(Context, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags,
Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator));
Identifier, Discriminator, DataLocation));
if (!IsNotUsedInTypeRef && Identifier)
MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));

View File

@ -1627,6 +1627,7 @@ void ModuleBitcodeWriter::writeDICompositeType(
Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier()));
Record.push_back(VE.getMetadataOrNullID(N->getDiscriminator()));
Record.push_back(VE.getMetadataOrNullID(N->getRawDataLocation()));
Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
Record.clear();

View File

@ -764,6 +764,8 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
auto *Array = dyn_cast<DICompositeType>(Var->getType());
if (!Array || Array->getTag() != dwarf::DW_TAG_array_type)
return Result;
if (auto *DLVar = Array->getDataLocation())
Result.push_back(DLVar);
for (auto *El : Array->getElements()) {
if (auto *Subrange = dyn_cast<DISubrange>(El)) {
auto Count = Subrange->getCount();

View File

@ -1414,6 +1414,17 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
CTy->getSizeInBits() / CHAR_BIT);
}
if (DIVariable *Var = CTy->getDataLocation()) {
if (auto *VarDIE = getDIE(Var))
addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE);
} else if (DIExpression *Expr = CTy->getDataLocationExp()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
DwarfExpr.setMemoryLocationKind();
DwarfExpr.addExpression(Expr);
addBlock(Buffer, dwarf::DW_AT_data_location, DwarfExpr.finalize());
}
// Emit the element type.
addType(Buffer, CTy->getBaseType());

View File

@ -1931,6 +1931,7 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
Printer.printMetadata("templateParams", N->getRawTemplateParams());
Printer.printString("identifier", N->getIdentifier());
Printer.printMetadata("discriminator", N->getRawDiscriminator());
Printer.printMetadata("dataLocation", N->getRawDataLocation());
Out << ")";
}

View File

@ -405,17 +405,18 @@ DICompositeType *DICompositeType::getImpl(
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
StorageType Storage, bool ShouldCreate) {
Metadata *DataLocation, StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType.
DEFINE_GETIMPL_LOOKUP(
DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Identifier, Discriminator));
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, Identifier,
Discriminator};
DEFINE_GETIMPL_LOOKUP(DICompositeType,
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements,
RuntimeLang, VTableHolder, TemplateParams, Identifier,
Discriminator, DataLocation));
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, Identifier,
Discriminator, DataLocation};
DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
AlignInBits, OffsetInBits, Flags),
Ops);
@ -426,7 +427,8 @@ DICompositeType *DICompositeType::buildODRType(
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@ -435,7 +437,8 @@ DICompositeType *DICompositeType::buildODRType(
return CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, &Identifier, Discriminator);
VTableHolder, TemplateParams, &Identifier, Discriminator,
DataLocation);
// Only mutate CT if it's a forward declaration and the new operands aren't.
assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@ -445,9 +448,9 @@ DICompositeType *DICompositeType::buildODRType(
// Mutate CT in place. Keep this in sync with getImpl.
CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
Flags);
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, &Identifier,
Discriminator};
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, &Identifier,
Discriminator, DataLocation};
assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
"Mismatched number of operands");
for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@ -461,7 +464,8 @@ DICompositeType *DICompositeType::getODRType(
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@ -470,7 +474,7 @@ DICompositeType *DICompositeType::getODRType(
CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
TemplateParams, &Identifier, Discriminator);
TemplateParams, &Identifier, Discriminator, DataLocation);
return CT;
}

View File

@ -510,19 +510,21 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Metadata *TemplateParams;
MDString *Identifier;
Metadata *Discriminator;
Metadata *DataLocation;
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator)
MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation)
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
TemplateParams(TemplateParams), Identifier(Identifier),
Discriminator(Discriminator) {}
Discriminator(Discriminator), DataLocation(DataLocation) {}
MDNodeKeyImpl(const DICompositeType *N)
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
Line(N->getLine()), Scope(N->getRawScope()),
@ -532,7 +534,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
TemplateParams(N->getRawTemplateParams()),
Identifier(N->getRawIdentifier()),
Discriminator(N->getRawDiscriminator()) {}
Discriminator(N->getRawDiscriminator()),
DataLocation(N->getRawDataLocation()) {}
bool isKeyOf(const DICompositeType *RHS) const {
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
@ -546,7 +549,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
VTableHolder == RHS->getRawVTableHolder() &&
TemplateParams == RHS->getRawTemplateParams() &&
Identifier == RHS->getRawIdentifier() &&
Discriminator == RHS->getRawDiscriminator();
Discriminator == RHS->getRawDiscriminator() &&
DataLocation == RHS->getRawDataLocation();
}
unsigned getHashValue() const {

View File

@ -1011,6 +1011,11 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
"discriminator can only appear on variant part");
}
if (N.getRawDataLocation()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"dataLocation can only appear in array type");
}
}
void Verifier::visitDISubroutineType(const DISubroutineType &N) {

View File

@ -0,0 +1,31 @@
;; This test checks dataLocation field of DICompositeType
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}})
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !DIExpression(DW_OP_constu, 3412))
; ModuleID = 'dataLocation.f90'
source_filename = "/dir/dataLocation.ll"
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4)
!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
!4 = !{}
!5 = !{!6, !16}
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !10)
!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!8 = !{!9}
!9 = !DISubrange(count: 19, lowerBound: 2)
!10 = distinct !DILocalVariable(scope: !11, file: !3, type: !15, flags: DIFlagArtificial)
!11 = !DILexicalBlock(scope: !12, file: !3, line: 1, column: 1)
!12 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !13, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!13 = !DISubroutineType(cc: DW_CC_program, types: !14)
!14 = !{null}
!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !DIExpression(DW_OP_constu, 3412))

View File

@ -0,0 +1,66 @@
;; This test checks whether DW_AT_data_location attribute
;; accepts DIExpression.
; RUN: llc mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK-LABEL: DW_TAG_array_type
; CHECK: DW_AT_data_location (DW_OP_constu 0x1a85)
; CHECK: DW_TAG_subrange_type
;; Test case is hand written with the help of below testcase
;;------------------------------
;;program main
;;integer, allocatable :: arr(:)
;;allocate(arr(2:20))
;;arr(2)=99
;;print *, arr
;;end program main
;;------------------------------
; ModuleID = 'fortsubrange.ll'
source_filename = "fortsubrange.ll"
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"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0640_333 = alloca i32*, align 8
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !14
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !15, metadata !DIExpression()), !dbg !14
ret void, !dbg !17
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !9, file: !3, type: !10)
!9 = !DILexicalBlock(scope: !5, file: !3, line: 1, column: 1)
;; We intend to use DW_OP_push_object_address, since that is not available yet,
;; we are using meaning less expression
;;!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !DIExpression(DW_OP_constu, 6789))
!11 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!12 = !{!13}
!13 = !DISubrange(count: 19, lowerBound: 2)
!14 = !DILocation(line: 0, scope: !9)
!15 = distinct !DILocalVariable(scope: !9, file: !3, type: !16, flags: DIFlagArtificial)
!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32, align: 32)
!17 = !DILocation(line: 6, column: 1, scope: !9)

View File

@ -0,0 +1,65 @@
;; This test checks whether DW_AT_data_location attribute
;; accepts DIVariable
; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK: [[LOCDIE:0x.+]]: DW_TAG_variable
; CHECK: DW_AT_artificial (true)
; CHECK: DW_TAG_variable
; CHECK: DW_AT_name ("arr")
; CHECK: DW_TAG_array_type
; CHECK-NEXT: DW_AT_data_location ([[LOCDIE]])
;; Test case is hand written with the help of below testcase
;;------------------------------
;;program main
;;integer, allocatable :: arr(:)
;;allocate(arr(2:20))
;;arr(2)=99
;;print *, arr
;;end program main
;;------------------------------
; ModuleID = 'fortsubrange.ll'
source_filename = "fortsubrange.ll"
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"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0640_333 = alloca i32*, align 8
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !16
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !14, metadata !DIExpression()), !dbg !16
ret void, !dbg !17
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !9, file: !3, type: !10)
!9 = !DILexicalBlock(scope: !5, file: !3, line: 1, column: 1)
!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !14)
!11 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!12 = !{!13}
!13 = !DISubrange(count: 19, lowerBound: 2)
!14 = distinct !DILocalVariable(scope: !9, file: !3, type: !15, flags: DIFlagArtificial)
!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32, align: 32)
!16 = !DILocation(line: 0, scope: !9)
!17 = !DILocation(line: 6, column: 1, scope: !9)

View File

@ -0,0 +1,6 @@
; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s
!named = !{!0}
!0 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", size: 64, dataLocation: !DIExpression(DW_OP_constu, 6789))
; CHECK: dataLocation can only appear in array type

View File

@ -29,7 +29,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
// Without a type map, this should return null.
EXPECT_FALSE(DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr));
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
nullptr));
// Enable the mapping. There still shouldn't be a type.
Context.enableDebugTypeODRUniquing();
@ -38,7 +39,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
// Create some ODR-uniqued type.
auto &CT = *DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr);
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
nullptr);
EXPECT_EQ(UUID.getString(), CT.getIdentifier());
// Check that we get it back, even if we change a field.
@ -46,12 +48,12 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type,
MDString::get(Context, "name"), nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr,
nullptr, nullptr, nullptr));
EXPECT_EQ(&CT,
DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type,
MDString::get(Context, "name"), nullptr, 0, nullptr, nullptr, 0,
0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr));
// Check that it's discarded with the type map.
Context.disableDebugTypeODRUniquing();
@ -70,32 +72,35 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
MDString &UUID = *MDString::get(Context, "Type");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr);
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr,
nullptr, nullptr);
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with another forward decl. This should be a no-op.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr));
Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl,
nullptr, 0, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with a definition. This time we should see a change.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero,
nullptr, 0, nullptr, nullptr, nullptr));
nullptr, 0, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
// Further updates should be ignored.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr));
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr,
0, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr));
nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
}
@ -107,7 +112,7 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
MDString &UUID = *MDString::get(Context, "UUID");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr);
DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr);
// Create macros for running through all the fields except Identifier and Flags.
#define FOR_EACH_MDFIELD() \
@ -136,11 +141,11 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
#undef DO_FOR_FIELD
// Replace all the fields with new values that are distinct from each other.
EXPECT_EQ(&CT,
DICompositeType::buildODRType(
Context, UUID, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr));
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits,
DINode::FlagArtificial, Elements, RuntimeLang,
VTableHolder, TemplateParams, nullptr, nullptr));
// Confirm that all the right fields got updated.
#define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());

View File

@ -1623,6 +1623,69 @@ TEST_F(DICompositeTypeTest, variant_part) {
EXPECT_EQ(N->getDiscriminator(), Discriminator);
}
TEST_F(DICompositeTypeTest, dynamicArray) {
unsigned Tag = dwarf::DW_TAG_array_type;
StringRef Name = "some name";
DIFile *File = getFile();
unsigned Line = 1;
DILocalScope *Scope = getSubprogram();
DIType *BaseType = getCompositeType();
uint64_t SizeInBits = 32;
uint32_t AlignInBits = 32;
uint64_t OffsetInBits = 4;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(3);
unsigned RuntimeLang = 6;
StringRef Identifier = "some id";
DIType *Type = getDerivedType();
Metadata *DlVar1 = DILocalVariable::get(Context, Scope, "dl_var1", File, 8,
Type, 2, Flags, 8);
Metadata *DlVar2 = DILocalVariable::get(Context, Scope, "dl_var2", File, 8,
Type, 2, Flags, 8);
uint64_t Elements1[] = {dwarf::DW_OP_push_object_address, dwarf::DW_OP_deref};
Metadata *DataLocation1 = DIExpression::get(Context, Elements1);
uint64_t Elements2[] = {dwarf::DW_OP_constu, 0};
Metadata *DataLocation2 = DIExpression::get(Context, Elements2);
auto *N1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DlVar1);
auto *Same1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DlVar1);
auto *Other1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DlVar2);
EXPECT_EQ(N1, Same1);
EXPECT_NE(Same1, Other1);
EXPECT_EQ(N1->getDataLocation(), DlVar1);
auto *N2 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1);
auto *Same2 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1);
auto *Other2 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation2);
EXPECT_EQ(N2, Same2);
EXPECT_NE(Same2, Other2);
EXPECT_EQ(N2->getDataLocationExp(), DataLocation1);
}
typedef MetadataTest DISubroutineTypeTest;
TEST_F(DISubroutineTypeTest, get) {