1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[DebugInfo] Support for DWARF attribute DW_AT_rank

This patch adds support for DWARF attribute DW_AT_rank.

  Summary:
Fortran assumed rank arrays have dynamic rank. DWARF attribute
DW_AT_rank is needed to support that.

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

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D89141
This commit is contained in:
Alok Kumar Sharma 2020-10-10 17:48:35 +05:30
parent d5dc3dc1f4
commit 0a8029e199
17 changed files with 404 additions and 72 deletions

View File

@ -4906,7 +4906,9 @@ arrays which can be attached to actual arrays, this attachment between pointer
and pointee is called association. The optional ``associated`` is a and pointee is called association. The optional ``associated`` is a
DIExpression that describes whether the pointer array is currently associated. DIExpression that describes whether the pointer array is currently associated.
The optional ``allocated`` is a DIExpression that describes whether the The optional ``allocated`` is a DIExpression that describes whether the
allocatable array is currently allocated. allocatable array is currently allocated. The optional ``rank`` is a
DIExpression that describes the rank (number of dimensions) of fortran assumed
rank array (rank is known at runtime).
For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator
descriptors <DIEnumerator>`, each representing the definition of an enumeration descriptors <DIEnumerator>`, each representing the definition of an enumeration

View File

@ -1026,14 +1026,14 @@ class DICompositeType : public DIType {
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams, StringRef Identifier, DITemplateParameterArray TemplateParams, StringRef Identifier,
DIDerivedType *Discriminator, Metadata *DataLocation, DIDerivedType *Discriminator, Metadata *DataLocation,
Metadata *Associated, Metadata *Allocated, StorageType Storage, Metadata *Associated, Metadata *Allocated, Metadata *Rank,
bool ShouldCreate = true) { StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, return getImpl(
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
Flags, Elements.get(), RuntimeLang, VTableHolder, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
TemplateParams.get(), RuntimeLang, VTableHolder, TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator, getCanonicalMDString(Context, Identifier), Discriminator, DataLocation,
DataLocation, Associated, Allocated, Storage, ShouldCreate); Associated, Allocated, Rank, Storage, ShouldCreate);
} }
static DICompositeType * static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@ -1042,16 +1042,17 @@ class DICompositeType : public DIType {
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
Metadata *Associated, Metadata *Allocated, StorageType Storage, Metadata *Associated, Metadata *Allocated, Metadata *Rank,
bool ShouldCreate = true); StorageType Storage, bool ShouldCreate = true);
TempDICompositeType cloneImpl() const { TempDICompositeType cloneImpl() const {
return getTemporary( return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getScope(), getBaseType(), getSizeInBits(),
getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), getAlignInBits(), getOffsetInBits(), getFlags(),
getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), getElements(), getRuntimeLang(), getVTableHolder(),
getTemplateParams(), getIdentifier(), getDiscriminator(), getTemplateParams(), getIdentifier(),
getRawDataLocation(), getRawAssociated(), getRawAllocated()); getDiscriminator(), getRawDataLocation(),
getRawAssociated(), getRawAllocated(), getRawRank());
} }
public: public:
@ -1064,10 +1065,10 @@ public:
DITemplateParameterArray TemplateParams = nullptr, DITemplateParameterArray TemplateParams = nullptr,
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, Metadata *DataLocation = nullptr, Metadata *Associated = nullptr,
Metadata *Allocated = nullptr), Metadata *Allocated = nullptr, Metadata *Rank = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation, Associated, Allocated)) Identifier, Discriminator, DataLocation, Associated, Allocated, Rank))
DEFINE_MDNODE_GET( DEFINE_MDNODE_GET(
DICompositeType, DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
@ -1076,10 +1077,11 @@ public:
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr,
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr,
Metadata *Associated = nullptr, Metadata *Allocated = nullptr), Metadata *Associated = nullptr, Metadata *Allocated = nullptr,
Metadata *Rank = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation, Associated, Allocated)) Identifier, Discriminator, DataLocation, Associated, Allocated, Rank))
TempDICompositeType clone() const { return cloneImpl(); } TempDICompositeType clone() const { return cloneImpl(); }
@ -1097,7 +1099,8 @@ public:
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated); Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
Metadata *Rank);
static DICompositeType *getODRTypeIfExists(LLVMContext &Context, static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
MDString &Identifier); MDString &Identifier);
@ -1110,13 +1113,15 @@ public:
/// ///
/// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns
/// nullptr. /// nullptr.
static DICompositeType *buildODRType( static DICompositeType *
LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated); Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated,
Metadata *Allocated, Metadata *Rank);
DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
DINodeArray getElements() const { DINodeArray getElements() const {
@ -1159,6 +1164,15 @@ public:
DIExpression *getAllocatedExp() const { DIExpression *getAllocatedExp() const {
return dyn_cast_or_null<DIExpression>(getRawAllocated()); return dyn_cast_or_null<DIExpression>(getRawAllocated());
} }
Metadata *getRawRank() const { return getOperand(12); }
ConstantInt *getRankConst() const {
if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank()))
return dyn_cast_or_null<ConstantInt>(MD->getValue());
return nullptr;
}
DIExpression *getRankExp() const {
return dyn_cast_or_null<DIExpression>(getRawRank());
}
/// Replace operands. /// Replace operands.
/// ///

View File

@ -4712,18 +4712,26 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(discriminator, MDField, ); \ OPTIONAL(discriminator, MDField, ); \
OPTIONAL(dataLocation, MDField, ); \ OPTIONAL(dataLocation, MDField, ); \
OPTIONAL(associated, MDField, ); \ OPTIONAL(associated, MDField, ); \
OPTIONAL(allocated, MDField, ); OPTIONAL(allocated, MDField, ); \
OPTIONAL(rank, MDSignedOrMDField, );
PARSE_MD_FIELDS(); PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS #undef VISIT_MD_FIELDS
Metadata *Rank = nullptr;
if (rank.isMDSignedField())
Rank = ConstantAsMetadata::get(ConstantInt::getSigned(
Type::getInt64Ty(Context), rank.getMDSignedValue()));
else if (rank.isMDField())
Rank = rank.getMDFieldValue();
// If this has an identifier try to build an ODR type. // If this has an identifier try to build an ODR type.
if (identifier.Val) if (identifier.Val)
if (auto *CT = DICompositeType::buildODRType( if (auto *CT = DICompositeType::buildODRType(
Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val, Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val,
scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val, scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val,
elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val, elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val,
discriminator.Val, dataLocation.Val, associated.Val, discriminator.Val, dataLocation.Val, associated.Val, allocated.Val,
allocated.Val)) { Rank)) {
Result = CT; Result = CT;
return false; return false;
} }
@ -4735,7 +4743,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
(Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val,
size.Val, align.Val, offset.Val, flags.Val, elements.Val, size.Val, align.Val, offset.Val, flags.Val, elements.Val,
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
discriminator.Val, dataLocation.Val, associated.Val, allocated.Val)); discriminator.Val, dataLocation.Val, associated.Val, allocated.Val,
Rank));
return false; return false;
} }

View File

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

View File

@ -1662,6 +1662,7 @@ void ModuleBitcodeWriter::writeDICompositeType(
Record.push_back(VE.getMetadataOrNullID(N->getRawDataLocation())); Record.push_back(VE.getMetadataOrNullID(N->getRawDataLocation()));
Record.push_back(VE.getMetadataOrNullID(N->getRawAssociated())); Record.push_back(VE.getMetadataOrNullID(N->getRawAssociated()));
Record.push_back(VE.getMetadataOrNullID(N->getRawAllocated())); Record.push_back(VE.getMetadataOrNullID(N->getRawAllocated()));
Record.push_back(VE.getMetadataOrNullID(N->getRawRank()));
Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev); Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
Record.clear(); Record.clear();

View File

@ -1472,6 +1472,17 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addBlock(Buffer, dwarf::DW_AT_allocated, DwarfExpr.finalize()); addBlock(Buffer, dwarf::DW_AT_allocated, DwarfExpr.finalize());
} }
if (auto *RankConst = CTy->getRankConst()) {
addSInt(Buffer, dwarf::DW_AT_rank, dwarf::DW_FORM_sdata,
RankConst->getSExtValue());
} else if (auto *RankExpr = CTy->getRankExp()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
DwarfExpr.setMemoryLocationKind();
DwarfExpr.addExpression(RankExpr);
addBlock(Buffer, dwarf::DW_AT_rank, DwarfExpr.finalize());
}
// Emit the element type. // Emit the element type.
addType(Buffer, CTy->getBaseType()); addType(Buffer, CTy->getBaseType());

View File

@ -1991,6 +1991,11 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
Printer.printMetadata("dataLocation", N->getRawDataLocation()); Printer.printMetadata("dataLocation", N->getRawDataLocation());
Printer.printMetadata("associated", N->getRawAssociated()); Printer.printMetadata("associated", N->getRawAssociated());
Printer.printMetadata("allocated", N->getRawAllocated()); Printer.printMetadata("allocated", N->getRawAllocated());
if (auto *RankConst = N->getRankConst())
Printer.printInt("rank", RankConst->getSExtValue(),
/* ShouldSkipZero */ false);
else
Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true);
Out << ")"; Out << ")";
} }

View File

@ -508,18 +508,19 @@ DICompositeType *DICompositeType::getImpl(
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
StorageType Storage, bool ShouldCreate) { Metadata *Rank, StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType. // Keep this in sync with buildODRType.
DEFINE_GETIMPL_LOOKUP(DICompositeType, DEFINE_GETIMPL_LOOKUP(
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, DICompositeType,
AlignInBits, OffsetInBits, Flags, Elements, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
RuntimeLang, VTableHolder, TemplateParams, Identifier, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Discriminator, DataLocation, Associated, Allocated)); Identifier, Discriminator, DataLocation, Associated, Allocated, Rank));
Metadata *Ops[] = {File, Scope, Name, BaseType, Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, Identifier, Elements, VTableHolder, TemplateParams, Identifier,
Discriminator, DataLocation, Associated, Allocated}; Discriminator, DataLocation, Associated, Allocated,
Rank};
DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
AlignInBits, OffsetInBits, Flags), AlignInBits, OffsetInBits, Flags),
Ops); Ops);
@ -531,7 +532,8 @@ DICompositeType *DICompositeType::buildODRType(
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated) { Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
Metadata *Rank) {
assert(!Identifier.getString().empty() && "Expected valid identifier"); assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes()) if (!Context.isODRUniquingDebugTypes())
return nullptr; return nullptr;
@ -541,7 +543,7 @@ DICompositeType *DICompositeType::buildODRType(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, &Identifier, Discriminator, VTableHolder, TemplateParams, &Identifier, Discriminator,
DataLocation, Associated, Allocated); DataLocation, Associated, Allocated, Rank);
// Only mutate CT if it's a forward declaration and the new operands aren't. // Only mutate CT if it's a forward declaration and the new operands aren't.
assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?"); assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@ -553,7 +555,8 @@ DICompositeType *DICompositeType::buildODRType(
Flags); Flags);
Metadata *Ops[] = {File, Scope, Name, BaseType, Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, &Identifier, Elements, VTableHolder, TemplateParams, &Identifier,
Discriminator, DataLocation, Associated, Allocated}; Discriminator, DataLocation, Associated, Allocated,
Rank};
assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() && assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
"Mismatched number of operands"); "Mismatched number of operands");
for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I) for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@ -568,7 +571,8 @@ DICompositeType *DICompositeType::getODRType(
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated) { Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
Metadata *Rank) {
assert(!Identifier.getString().empty() && "Expected valid identifier"); assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes()) if (!Context.isODRUniquingDebugTypes())
return nullptr; return nullptr;
@ -578,7 +582,7 @@ DICompositeType *DICompositeType::getODRType(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
TemplateParams, &Identifier, Discriminator, DataLocation, Associated, TemplateParams, &Identifier, Discriminator, DataLocation, Associated,
Allocated); Allocated, Rank);
return CT; return CT;
} }

View File

@ -538,6 +538,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Metadata *DataLocation; Metadata *DataLocation;
Metadata *Associated; Metadata *Associated;
Metadata *Allocated; Metadata *Allocated;
Metadata *Rank;
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
@ -546,14 +547,14 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator, MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *DataLocation, Metadata *Associated,
Metadata *Allocated) Metadata *Allocated, Metadata *Rank)
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
AlignInBits(AlignInBits), Flags(Flags), Elements(Elements), AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
RuntimeLang(RuntimeLang), VTableHolder(VTableHolder), RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
TemplateParams(TemplateParams), Identifier(Identifier), TemplateParams(TemplateParams), Identifier(Identifier),
Discriminator(Discriminator), DataLocation(DataLocation), Discriminator(Discriminator), DataLocation(DataLocation),
Associated(Associated), Allocated(Allocated) {} Associated(Associated), Allocated(Allocated), Rank(Rank) {}
MDNodeKeyImpl(const DICompositeType *N) MDNodeKeyImpl(const DICompositeType *N)
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
Line(N->getLine()), Scope(N->getRawScope()), Line(N->getLine()), Scope(N->getRawScope()),
@ -565,7 +566,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Identifier(N->getRawIdentifier()), Identifier(N->getRawIdentifier()),
Discriminator(N->getRawDiscriminator()), Discriminator(N->getRawDiscriminator()),
DataLocation(N->getRawDataLocation()), DataLocation(N->getRawDataLocation()),
Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()) {} Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()),
Rank(N->getRawRank()) {}
bool isKeyOf(const DICompositeType *RHS) const { bool isKeyOf(const DICompositeType *RHS) const {
return Tag == RHS->getTag() && Name == RHS->getRawName() && return Tag == RHS->getTag() && Name == RHS->getRawName() &&
@ -582,7 +584,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Discriminator == RHS->getRawDiscriminator() && Discriminator == RHS->getRawDiscriminator() &&
DataLocation == RHS->getRawDataLocation() && DataLocation == RHS->getRawDataLocation() &&
Associated == RHS->getRawAssociated() && Associated == RHS->getRawAssociated() &&
Allocated == RHS->getRawAllocated(); Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank();
} }
unsigned getHashValue() const { unsigned getHashValue() const {

View File

@ -1056,6 +1056,11 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type, AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"allocated can only appear in array type"); "allocated can only appear in array type");
} }
if (N.getRawRank()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"rank can only appear in array type");
}
} }
void Verifier::visitDISubroutineType(const DISubroutineType &N) { void Verifier::visitDISubroutineType(const DISubroutineType &N) {

41
test/Bitcode/rankConst.ll Normal file
View File

@ -0,0 +1,41 @@
;; This test checks rank field of DICompositeType
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
;; Test whether rank is generated.
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}}, rank: 7)
; ModuleID = 'rank.f90'
source_filename = "/dir/rank.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: "arank.f90", directory: "/dir")
!4 = !{}
!5 = !{!6}
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !16, rank: 7)
!7 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
!8 = !{!9, !10, !11, !12, !13, !14, !15}
!9 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!10 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!11 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!12 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!13 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!14 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!15 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!16 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial)
!17 = distinct !DISubprogram(name: "sub1", scope: !2, file: !3, line: 1, type: !18, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
!18 = !DISubroutineType(types: !19)
!19 = !{null, !20, !25}
!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !21)
!21 = !{!22}
!22 = !DISubrange(lowerBound: 1, upperBound: !23)
!23 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial)
!24 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed)
!25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 1024, align: 64, elements: !26)
!26 = !{!27}
!27 = !DISubrange(lowerBound: 1, upperBound: 16)

41
test/Bitcode/rankExp.ll Normal file
View File

@ -0,0 +1,41 @@
;; This test checks rank field of DICompositeType
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
;; Test whether rank is generated.
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}}, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref))
; ModuleID = 'rank.f90'
source_filename = "/dir/rank.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: "arank.f90", directory: "/dir")
!4 = !{}
!5 = !{!6}
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !16, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref))
!7 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
!8 = !{!9, !10, !11, !12, !13, !14, !15}
!9 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!10 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!11 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!12 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!13 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!14 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!15 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!16 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial)
!17 = distinct !DISubprogram(name: "sub1", scope: !2, file: !3, line: 1, type: !18, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
!18 = !DISubroutineType(types: !19)
!19 = !{null, !20, !25}
!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !21)
!21 = !{!22}
!22 = !DISubrange(lowerBound: 1, upperBound: !23)
!23 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial)
!24 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed)
!25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 1024, align: 64, elements: !26)
!26 = !{!27}
!27 = !DISubrange(lowerBound: 1, upperBound: 16)

View File

@ -0,0 +1,68 @@
;; This test checks whether DW_AT_rank attribute accepts DIExpression.
; RUN: llc %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_rank (7)
;; Test case is hand written with the help of below testcase
;;------------------------------
;;subroutine sub(arank)
;; real :: arank(..)
;; print *, RANK(arank)
;;end
;;------------------------------
; ModuleID = 'dwarfdump-rank.ll'
source_filename = "dwarfdump-rank.ll"
define void @sub_(i64* noalias %arank, i64* noalias %"arank$sd") !dbg !5 {
L.entry:
call void @llvm.dbg.value(metadata i64* %arank, metadata !17, metadata !DIExpression()), !dbg !18
call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !19, metadata !DIExpression()), !dbg !18
call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !29, metadata !DIExpression()), !dbg !18
ret void, !dbg !18
}
; 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: "rank.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "sub", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
!6 = !DISubroutineType(types: !7)
!7 = !{null, !8, !14}
!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !10)
!9 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
!10 = !{!11}
!11 = !DISubrange(lowerBound: 1, upperBound: !12)
!12 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial)
!13 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed)
!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 1024, align: 64, elements: !15)
!15 = !{!16}
!16 = !DISubrange(lowerBound: 1, upperBound: 16)
!17 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial)
!18 = !DILocation(line: 0, scope: !5)
!19 = !DILocalVariable(name: "arank", arg: 1, scope: !5, file: !3, line: 1, type: !20)
!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !21, dataLocation: !17, rank: 7)
!21 = !{!22, !23, !24, !25, !26, !27, !28}
!22 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!23 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!24 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!25 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!26 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!27 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!28 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!29 = !DILocalVariable(arg: 2, scope: !5, file: !3, line: 1, type: !14, flags: DIFlagArtificial)

View File

@ -0,0 +1,68 @@
;; This test checks whether DW_AT_rank attribute accepts DIExpression.
; RUN: llc %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_rank (DW_OP_push_object_address, DW_OP_plus_uconst 0x8, DW_OP_deref)
;; Test case is hand written with the help of below testcase
;;------------------------------
;;subroutine sub(arank)
;; real :: arank(..)
;; print *, RANK(arank)
;;end
;;------------------------------
; ModuleID = 'dwarfdump-rank.ll'
source_filename = "dwarfdump-rank.ll"
define void @sub_(i64* noalias %arank, i64* noalias %"arank$sd") !dbg !5 {
L.entry:
call void @llvm.dbg.value(metadata i64* %arank, metadata !17, metadata !DIExpression()), !dbg !18
call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !19, metadata !DIExpression()), !dbg !18
call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !29, metadata !DIExpression()), !dbg !18
ret void, !dbg !18
}
; 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: "rank.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "sub", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
!6 = !DISubroutineType(types: !7)
!7 = !{null, !8, !14}
!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !10)
!9 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
!10 = !{!11}
!11 = !DISubrange(lowerBound: 1, upperBound: !12)
!12 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial)
!13 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed)
!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 1024, align: 64, elements: !15)
!15 = !{!16}
!16 = !DISubrange(lowerBound: 1, upperBound: 16)
!17 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial)
!18 = !DILocation(line: 0, scope: !5)
!19 = !DILocalVariable(name: "arank", arg: 1, scope: !5, file: !3, line: 1, type: !20)
!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !21, dataLocation: !17, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref))
!21 = !{!22, !23, !24, !25, !26, !27, !28}
!22 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!23 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!24 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!25 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!26 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!27 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!28 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!29 = !DILocalVariable(arg: 2, scope: !5, file: !3, line: 1, type: !14, flags: DIFlagArtificial)

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, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref))
; CHECK: rank can only appear in array type

View File

@ -30,7 +30,7 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
EXPECT_FALSE(DICompositeType::getODRType( EXPECT_FALSE(DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, 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, nullptr, nullptr)); nullptr, nullptr, nullptr, nullptr));
// Enable the mapping. There still shouldn't be a type. // Enable the mapping. There still shouldn't be a type.
Context.enableDebugTypeODRUniquing(); Context.enableDebugTypeODRUniquing();
@ -40,20 +40,21 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
auto &CT = *DICompositeType::getODRType( auto &CT = *DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, 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, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(UUID.getString(), CT.getIdentifier()); EXPECT_EQ(UUID.getString(), CT.getIdentifier());
// Check that we get it back, even if we change a field. // Check that we get it back, even if we change a field.
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID)); EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(&CT, DICompositeType::getODRType( EXPECT_EQ(&CT,
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, DICompositeType::getODRType(
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(&CT, DICompositeType::getODRType( EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, Context, UUID, dwarf::DW_TAG_class_type,
MDString::get(Context, "name"), nullptr, 0, nullptr, MDString::get(Context, "name"), nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr)); nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
// Check that it's discarded with the type map. // Check that it's discarded with the type map.
Context.disableDebugTypeODRUniquing(); Context.disableDebugTypeODRUniquing();
@ -73,7 +74,7 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
auto &CT = *DICompositeType::buildODRType( auto &CT = *DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID)); EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag()); EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
@ -82,7 +83,7 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
DICompositeType::buildODRType( DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag()); EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with a definition. This time we should see a change. // Update with a definition. This time we should see a change.
@ -90,19 +91,21 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
DICompositeType::buildODRType( DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag()); EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
// Further updates should be ignored. // Further updates should be ignored.
EXPECT_EQ(&CT, DICompositeType::buildODRType( EXPECT_EQ(&CT,
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, DICompositeType::buildODRType(
0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0,
0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag()); EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
EXPECT_EQ(&CT, DICompositeType::buildODRType( EXPECT_EQ(&CT,
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, DICompositeType::buildODRType(
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); 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()); EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
} }
@ -115,7 +118,7 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
auto &CT = *DICompositeType::buildODRType( auto &CT = *DICompositeType::buildODRType(
Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr); nullptr, nullptr, nullptr);
// Create macros for running through all the fields except Identifier and Flags. // Create macros for running through all the fields except Identifier and Flags.
#define FOR_EACH_MDFIELD() \ #define FOR_EACH_MDFIELD() \
@ -149,7 +152,7 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
Context, UUID, Tag, Name, File, Line, Scope, BaseType, Context, UUID, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial, SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr, Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr,
nullptr, nullptr, nullptr)); nullptr, nullptr, nullptr, nullptr));
// Confirm that all the right fields got updated. // Confirm that all the right fields got updated.
#define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X()); #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());

View File

@ -1780,6 +1780,16 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
uint64_t Elements2[] = {dwarf::DW_OP_constu, 0}; uint64_t Elements2[] = {dwarf::DW_OP_constu, 0};
Metadata *DataLocation2 = DIExpression::get(Context, Elements2); Metadata *DataLocation2 = DIExpression::get(Context, Elements2);
uint64_t Elements3[] = {dwarf::DW_OP_constu, 3};
Metadata *Rank1 = DIExpression::get(Context, Elements3);
uint64_t Elements4[] = {dwarf::DW_OP_constu, 4};
Metadata *Rank2 = DIExpression::get(Context, Elements4);
ConstantInt *RankInt1 = ConstantInt::get(Context, APInt(7, 0));
ConstantAsMetadata *RankConst1 = ConstantAsMetadata::get(RankInt1);
ConstantInt *RankInt2 = ConstantInt::get(Context, APInt(6, 0));
ConstantAsMetadata *RankConst2 = ConstantAsMetadata::get(RankInt2);
auto *N1 = DICompositeType::get( auto *N1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
@ -1817,6 +1827,44 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
EXPECT_EQ(N2, Same2); EXPECT_EQ(N2, Same2);
EXPECT_NE(Same2, Other2); EXPECT_NE(Same2, Other2);
EXPECT_EQ(N2->getDataLocationExp(), DataLocation1); EXPECT_EQ(N2->getDataLocationExp(), DataLocation1);
auto *N3 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1, nullptr, nullptr, Rank1);
auto *Same3 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1, nullptr, nullptr, Rank1);
auto *Other3 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1, nullptr, nullptr, Rank2);
EXPECT_EQ(N3, Same3);
EXPECT_NE(Same3, Other3);
EXPECT_EQ(N3->getRankExp(), Rank1);
auto *N4 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1, nullptr, nullptr, RankConst1);
auto *Same4 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1, nullptr, nullptr, RankConst1);
auto *Other4 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
nullptr, DataLocation1, nullptr, nullptr, RankConst2);
EXPECT_EQ(N4, Same4);
EXPECT_NE(Same4, Other4);
EXPECT_EQ(N4->getRankConst(), RankInt1);
} }
typedef MetadataTest DISubroutineTypeTest; typedef MetadataTest DISubroutineTypeTest;