Index: bindings/go/llvm/DIBuilderBindings.cpp =================================================================== --- bindings/go/llvm/DIBuilderBindings.cpp +++ bindings/go/llvm/DIBuilderBindings.cpp @@ -119,7 +119,7 @@ const char *Name) { DIBuilder *D = unwrap(Dref); return wrap(D->createPointerType(unwrap(PointeeType), SizeInBits, - AlignInBits, Name)); + AlignInBits, /* AddressSpace */ None, Name)); } LLVMMetadataRef Index: docs/AMDGPUUsage.rst =================================================================== --- docs/AMDGPUUsage.rst +++ docs/AMDGPUUsage.rst @@ -19,20 +19,24 @@ The AMDGPU back-end uses the following address space mapping: - ============= ============================================ - Address Space Memory Space - ============= ============================================ - 0 Private - 1 Global - 2 Constant - 3 Local - 4 Generic (Flat) - 5 Region - ============= ============================================ + ================== =================== ============== + LLVM Address Space DWARF Address Space Memory Space + ================== =================== ============== + 0 1 Private + 1 N/A Global + 2 N/A Constant + 3 2 Local + 4 N/A Generic (Flat) + 5 N/A Region + ================== =================== ============== The terminology in the table, aside from the region memory space, is from the OpenCL standard. +LLVM Address Space is used throughout LLVM (for example, in LLVM IR). DWARF +Address Space is emitted in DWARF, and is used by tools, such as debugger, +profiler and others. + Assembler ========= Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -168,12 +168,14 @@ DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy); /// Create debugging information entry for a pointer. - /// \param PointeeTy Type pointed by this pointer. - /// \param SizeInBits Size. - /// \param AlignInBits Alignment. (optional) - /// \param Name Pointer type name. (optional) + /// \param PointeeTy Type pointed by this pointer. + /// \param SizeInBits Size. + /// \param AlignInBits Alignment. (optional) + /// \param AddressSpace Address space. (optional) + /// \param Name Pointer type name. (optional) DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits, uint32_t AlignInBits = 0, + Optional AddressSpace = None, StringRef Name = ""); /// Create debugging information entry for a pointer to member. @@ -190,7 +192,8 @@ /// style reference or rvalue reference type. DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy, uint64_t SizeInBits = 0, - uint32_t AlignInBits = 0); + uint32_t AlignInBits = 0, + Optional AddressSpace = None); /// Create debugging information entry for a typedef. /// \param Ty Original type. Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -710,37 +710,45 @@ friend class LLVMContextImpl; friend class MDNode; + /// \brief The address space of the memory pointed to or referenced by a + /// pointer or reference type respectively. + Optional AddressSpace; + DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, ArrayRef Ops) + uint64_t OffsetInBits, Optional AddressSpace, + DIFlags Flags, ArrayRef Ops) : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, - AlignInBits, OffsetInBits, Flags, Ops) {} + AlignInBits, OffsetInBits, Flags, Ops), + AddressSpace(AddressSpace) {} ~DIDerivedType() = default; static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, + uint64_t OffsetInBits, + Optional AddressSpace, DIFlags Flags, Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - Flags, ExtraData, Storage, ShouldCreate); + AddressSpace, Flags, ExtraData, Storage, ShouldCreate); } static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, + uint64_t OffsetInBits, + Optional AddressSpace, DIFlags Flags, Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true); TempDIDerivedType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), - getAlignInBits(), getOffsetInBits(), getFlags(), - getExtraData()); + getAlignInBits(), getOffsetInBits(), getAddressSpace(), + getFlags(), getExtraData()); } public: @@ -748,24 +756,29 @@ (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, DIFlags Flags, - Metadata *ExtraData = nullptr), + uint64_t OffsetInBits, Optional AddressSpace, + DIFlags Flags, Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, ExtraData)) + AlignInBits, OffsetInBits, AddressSpace, Flags, ExtraData)) DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - DIFlags Flags, Metadata *ExtraData = nullptr), + Optional AddressSpace, DIFlags Flags, + Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, ExtraData)) + AlignInBits, OffsetInBits, AddressSpace, Flags, ExtraData)) TempDIDerivedType clone() const { return cloneImpl(); } - //// Get the base type this is derived from. + /// Get the base type this is derived from. DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } Metadata *getRawBaseType() const { return getOperand(3); } + /// \returns The address space of the memory pointed to or referenced by a + /// pointer or reference type respectively. + Optional getAddressSpace() const { return AddressSpace; } + /// Get extra data associated with this derived type. /// /// Class type for pointer-to-members, objective-c property node for ivars, Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -3908,7 +3908,8 @@ /// ParseDIDerivedType: /// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, /// line: 7, scope: !1, baseType: !2, size: 32, -/// align: 32, offset: 0, flags: 0, extraData: !3) +/// align: 32, offset: 0, flags: 0, extraData: !3, +/// addressSpace: 3) bool LLParser::ParseDIDerivedType(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(tag, DwarfTagField, ); \ @@ -3921,14 +3922,20 @@ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(extraData, MDField, ); + OPTIONAL(extraData, MDField, ); \ + OPTIONAL(addressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + Optional AddressSpace = None; + if (addressSpace.Val != UINT32_MAX) + AddressSpace = addressSpace.Val; + Result = GET_OR_DISTINCT(DIDerivedType, (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, size.Val, align.Val, - offset.Val, flags.Val, extraData.Val)); + offset.Val, AddressSpace, flags.Val, + extraData.Val)); return false; } Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -1110,9 +1110,15 @@ break; } case bitc::METADATA_DERIVED_TYPE: { - if (Record.size() != 12) + if (Record.size() < 12 || Record.size() > 13) return error("Invalid record"); + // Address space is encoded as N->getAddressSpace() + 1. 0 means that there + // is no address space associated with DIDerivedType. + Optional AddressSpace = None; + if (Record.size() > 12 && Record[12]) + AddressSpace = Record[12] - 1; + IsDistinct = Record[0]; DINode::DIFlags Flags = static_cast(Record[10]); MetadataList.assignValue( @@ -1121,7 +1127,8 @@ getMDOrNull(Record[3]), Record[4], getDITypeRefOrNull(Record[5]), getDITypeRefOrNull(Record[6]), Record[7], Record[8], - Record[9], Flags, getDITypeRefOrNull(Record[11]))), + Record[9], AddressSpace, Flags, + getDITypeRefOrNull(Record[11]))), NextMetadataNo); NextMetadataNo++; break; Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1473,6 +1473,13 @@ Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getExtraData())); + // Address space is encoded as N->getAddressSpace() + 1. 0 means that there is + // no address space associated with DIDerivedType. + if (const auto &AS = N->getAddressSpace()) + Record.push_back(*AS + 1); + else + Record.push_back(0); + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -841,6 +841,13 @@ // Add source line info if available and TyDesc is not a forward declaration. if (!DTy->isForwardDecl()) addSourceLine(Buffer, DTy); + + // If address space value is other than None, add it for pointer and reference + // types as DW_AT_address_class. + if (DTy->getAddressSpace() && (Tag == dwarf::DW_TAG_pointer_type || + Tag == dwarf::DW_TAG_reference_type)) + addUInt(Buffer, dwarf::DW_AT_address_class, dwarf::DW_FORM_data4, + DTy->getAddressSpace().getValue()); } void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) { Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1614,6 +1614,8 @@ Printer.printInt("offset", N->getOffsetInBits()); Printer.printDIFlags("flags", N->getFlags()); Printer.printMetadata("extraData", N->getRawExtraData()); + if (const auto &AS = N->getAddressSpace()) + Printer.printInt("addressSpace", *AS, /* ShouldSkipZero */ false); Out << ")"; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -241,17 +241,18 @@ DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, FromTy, 0, - 0, 0, DINode::FlagZero); + 0, 0, None, DINode::FlagZero); } DIDerivedType *DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits, uint32_t AlignInBits, + Optional AddressSpace, StringRef Name) { // FIXME: Why is there a name here? return DIDerivedType::get(VMContext, dwarf::DW_TAG_pointer_type, Name, nullptr, 0, nullptr, PointeeTy, SizeInBits, - AlignInBits, 0, DINode::FlagZero); + AlignInBits, 0, AddressSpace, DINode::FlagZero); } DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, @@ -261,15 +262,17 @@ DINode::DIFlags Flags) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_ptr_to_member_type, "", nullptr, 0, nullptr, PointeeTy, SizeInBits, - AlignInBits, 0, Flags, Base); + AlignInBits, 0, None, Flags, Base); } DIDerivedType *DIBuilder::createReferenceType(unsigned Tag, DIType *RTy, uint64_t SizeInBits, - uint32_t AlignInBits) { + uint32_t AlignInBits, + Optional AddressSpace) { assert(RTy && "Unable to create reference type"); return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, RTy, - SizeInBits, AlignInBits, 0, DINode::FlagZero); + SizeInBits, AlignInBits, 0, AddressSpace, + DINode::FlagZero); } DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, @@ -277,14 +280,14 @@ DIScope *Context) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, LineNo, getNonCompileUnitScope(Context), Ty, 0, 0, - 0, DINode::FlagZero); + 0, None, DINode::FlagZero); } DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { assert(Ty && "Invalid type!"); assert(FriendTy && "Invalid friend type!"); return DIDerivedType::get(VMContext, dwarf::DW_TAG_friend, "", nullptr, 0, Ty, - FriendTy, 0, 0, 0, DINode::FlagZero); + FriendTy, 0, 0, 0, None, DINode::FlagZero); } DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy, @@ -292,7 +295,7 @@ DINode::DIFlags Flags) { assert(Ty && "Unable to create inheritance"); return DIDerivedType::get(VMContext, dwarf::DW_TAG_inheritance, "", nullptr, - 0, Ty, BaseTy, 0, 0, BaseOffset, Flags); + 0, Ty, BaseTy, 0, 0, BaseOffset, None, Flags); } DIDerivedType *DIBuilder::createMemberType(DIScope *Scope, StringRef Name, @@ -303,7 +306,7 @@ DINode::DIFlags Flags, DIType *Ty) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, - SizeInBits, AlignInBits, OffsetInBits, Flags); + SizeInBits, AlignInBits, OffsetInBits, None, Flags); } static ConstantAsMetadata *getConstantOrNull(Constant *C) { @@ -320,7 +323,7 @@ return DIDerivedType::get( VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, SizeInBits, /* AlignInBits */ 0, - OffsetInBits, Flags, + OffsetInBits, None, Flags, ConstantAsMetadata::get(ConstantInt::get(IntegerType::get(VMContext, 64), StorageOffsetInBits))); } @@ -333,7 +336,8 @@ Flags |= DINode::FlagStaticMember; return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, 0, - AlignInBits, 0, Flags, getConstantOrNull(Val)); + AlignInBits, 0, None, Flags, + getConstantOrNull(Val)); } DIDerivedType * @@ -343,7 +347,7 @@ DIType *Ty, MDNode *PropertyNode) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(File), Ty, - SizeInBits, AlignInBits, OffsetInBits, Flags, + SizeInBits, AlignInBits, OffsetInBits, None, Flags, PropertyNode); } Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -245,16 +245,18 @@ DIDerivedType *DIDerivedType::getImpl( LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, - Metadata *ExtraData, StorageType Storage, bool ShouldCreate) { + uint32_t AlignInBits, uint64_t OffsetInBits, + Optional AddressSpace, DIFlags Flags, Metadata *ExtraData, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, Flags, ExtraData)); + AlignInBits, OffsetInBits, AddressSpace, Flags, + ExtraData)); Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData}; DEFINE_GETIMPL_STORE( - DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags), - Ops); + DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + AddressSpace, Flags), Ops); } DICompositeType *DICompositeType::getImpl( Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -352,22 +352,26 @@ uint64_t SizeInBits; uint64_t OffsetInBits; uint32_t AlignInBits; + Optional AddressSpace; unsigned Flags; Metadata *ExtraData; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + uint32_t AlignInBits, uint64_t OffsetInBits, + Optional AddressSpace, unsigned Flags, Metadata *ExtraData) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), - AlignInBits(AlignInBits), Flags(Flags), ExtraData(ExtraData) {} + AlignInBits(AlignInBits), AddressSpace(AddressSpace), Flags(Flags), + ExtraData(ExtraData) {} MDNodeKeyImpl(const DIDerivedType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()), - Flags(N->getFlags()), ExtraData(N->getRawExtraData()) {} + AddressSpace(N->getAddressSpace()), Flags(N->getFlags()), + ExtraData(N->getRawExtraData()) {} bool isKeyOf(const DIDerivedType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -375,7 +379,8 @@ Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && - OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && + OffsetInBits == RHS->getOffsetInBits() && + AddressSpace == RHS->getAddressSpace() && Flags == RHS->getFlags() && ExtraData == RHS->getRawExtraData(); } unsigned getHashValue() const { Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -901,6 +901,12 @@ AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope()); AssertDI(isType(N.getRawBaseType()), "invalid base type", &N, N.getRawBaseType()); + + if (N.getAddressSpace()) { + AssertDI(N.getTag() == dwarf::DW_TAG_pointer_type || + N.getTag() == dwarf::DW_TAG_reference_type, + "address space only applies to pointer or reference types", &N); + } } static bool hasConflictingReferenceFlags(unsigned Flags) { Index: test/Assembler/debug-info.ll =================================================================== --- test/Assembler/debug-info.ll +++ test/Assembler/debug-info.ll @@ -37,8 +37,8 @@ !13 = distinct !{} !14 = !DIFile(filename: "", directory: "") -; CHECK-NEXT: !13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 32, align: 32) -!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32) +; CHECK-NEXT: !13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 32, align: 32, addressSpace: 1) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32, addressSpace: 1) ; CHECK-NEXT: !14 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyType", file: !10, line: 2, size: 32, align: 32, identifier: "MangledMyType") ; CHECK-NEXT: !15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Base", scope: !14, file: !10, line: 3, size: 128, align: 32, offset: 64, flags: DIFlagPublic, elements: !16, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !15, templateParams: !18, identifier: "MangledBase") @@ -84,4 +84,4 @@ ; CHECK-NEXT: !33 = !DIFile(filename: "file", directory: "dir") !35 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "000102030405060708090a0b0c0d0e0f") !36 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None) -!37 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None, checksum: "") \ No newline at end of file +!37 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None, checksum: "") Index: test/Bitcode/upgrade-pointer-address-space.ll =================================================================== --- /dev/null +++ test/Bitcode/upgrade-pointer-address-space.ll @@ -0,0 +1,5 @@ +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +; CHECK-DAG: !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}) +; CHECK-DAG: !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}) +; CHECK-DAG: !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}) Index: test/DebugInfo/AMDGPU/pointer-address-space-dwarf-v1.ll =================================================================== --- /dev/null +++ test/DebugInfo/AMDGPU/pointer-address-space-dwarf-v1.ll @@ -0,0 +1,70 @@ +; RUN: llc -O0 -mtriple=amdgcn--amdhsa -mcpu=fiji -verify-machineinstrs -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s + +; LLVM IR generated with the following command and OpenCL source: +; +; $clang -cl-std=CL2.0 -g -O0 -target amdgcn-amd-amdhsa -S -emit-llvm +; +; kernel void kernel1() { +; global int *FuncVar0 = 0; +; constant int *FuncVar1 = 0; +; local int *FuncVar2 = 0; +; private int *FuncVar3 = 0; +; int *FuncVar4 = 0; +; } + +; DW_AT_address_class is available since Dwarf Version 2. +; CHECK-NOT: DW_AT_address_class + +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +define amdgpu_kernel void @kernel1() #0 !dbg !7 { +entry: + %FuncVar0 = alloca i32 addrspace(1)*, align 4 + %FuncVar1 = alloca i32 addrspace(2)*, align 4 + %FuncVar2 = alloca i32 addrspace(3)*, align 4 + %FuncVar3 = alloca i32*, align 4 + %FuncVar4 = alloca i32 addrspace(4)*, align 4 + call void @llvm.dbg.declare(metadata i32 addrspace(1)** %FuncVar0, metadata !10, metadata !13), !dbg !14 + store i32 addrspace(1)* null, i32 addrspace(1)** %FuncVar0, align 4, !dbg !14 + call void @llvm.dbg.declare(metadata i32 addrspace(2)** %FuncVar1, metadata !15, metadata !13), !dbg !16 + store i32 addrspace(2)* null, i32 addrspace(2)** %FuncVar1, align 4, !dbg !16 + call void @llvm.dbg.declare(metadata i32 addrspace(3)** %FuncVar2, metadata !17, metadata !13), !dbg !19 + store i32 addrspace(3)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(3)*), i32 addrspace(3)** %FuncVar2, align 4, !dbg !19 + call void @llvm.dbg.declare(metadata i32** %FuncVar3, metadata !20, metadata !13), !dbg !22 + store i32* addrspacecast (i32 addrspace(4)* null to i32*), i32** %FuncVar3, align 4, !dbg !22 + call void @llvm.dbg.declare(metadata i32 addrspace(4)** %FuncVar4, metadata !23, metadata !13), !dbg !24 + store i32 addrspace(4)* null, i32 addrspace(4)** %FuncVar4, align 4, !dbg !24 + ret void, !dbg !25 +} + +!llvm.dbg.cu = !{!0} +!opencl.ocl.version = !{!3} +!llvm.module.flags = !{!4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "pointer-address-space-dwarf-v1.cl", directory: "/some/random/directory") +!2 = !{} +!3 = !{i32 2, i32 0} +!4 = !{i32 2, !"Dwarf Version", i32 1} +!5 = !{i32 2, !"Debug Info Version", i32 3} +!6 = !{!""} +!7 = distinct !DISubprogram(name: "kernel1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocalVariable(name: "FuncVar0", scope: !7, file: !1, line: 2, type: !11) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DIExpression() +!14 = !DILocation(line: 2, column: 15, scope: !7) +!15 = !DILocalVariable(name: "FuncVar1", scope: !7, file: !1, line: 3, type: !11) +!16 = !DILocation(line: 3, column: 17, scope: !7) +!17 = !DILocalVariable(name: "FuncVar2", scope: !7, file: !1, line: 4, type: !18) +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 32, addressSpace: 2) +!19 = !DILocation(line: 4, column: 14, scope: !7) +!20 = !DILocalVariable(name: "FuncVar3", scope: !7, file: !1, line: 5, type: !21) +!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 32, addressSpace: 1) +!22 = !DILocation(line: 5, column: 16, scope: !7) +!23 = !DILocalVariable(name: "FuncVar4", scope: !7, file: !1, line: 6, type: !11) +!24 = !DILocation(line: 6, column: 8, scope: !7) +!25 = !DILocation(line: 7, column: 1, scope: !7) Index: test/DebugInfo/AMDGPU/pointer-address-space.ll =================================================================== --- /dev/null +++ test/DebugInfo/AMDGPU/pointer-address-space.ll @@ -0,0 +1,104 @@ +; RUN: llc -O0 -mtriple=amdgcn--amdhsa -mcpu=fiji -verify-machineinstrs -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s + +; LLVM IR generated with the following command and OpenCL source: +; +; $clang -cl-std=CL2.0 -g -O0 -target amdgcn-amd-amdhsa -S -emit-llvm +; +; kernel void kernel1() { +; global int *FuncVar0 = 0; +; constant int *FuncVar1 = 0; +; local int *FuncVar2 = 0; +; private int *FuncVar3 = 0; +; int *FuncVar4 = 0; +; } + +; CHECK: DW_AT_name {{.*}}"FuncVar0" +; CHECK-NEXT: DW_AT_decl_file +; CHECK-NEXT: DW_AT_decl_line +; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[a-f0-9]+}} => {0x[[NONE:[a-f0-9]+]]}) + +; CHECK: DW_AT_name {{.*}}"FuncVar1" +; CHECK-NEXT: DW_AT_decl_file +; CHECK-NEXT: DW_AT_decl_line +; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[a-f0-9]+}} => {0x[[NONE]]}) + +; CHECK: DW_AT_name {{.*}}"FuncVar2" +; CHECK-NEXT: DW_AT_decl_file +; CHECK-NEXT: DW_AT_decl_line +; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[a-f0-9]+}} => {0x[[LOCAL:[a-f0-9]+]]}) + +; CHECK: DW_AT_name {{.*}}"FuncVar3" +; CHECK-NEXT: DW_AT_decl_file +; CHECK-NEXT: DW_AT_decl_line +; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[a-f0-9]+}} => {0x[[PRIVATE:[a-f0-9]+]]}) + +; CHECK: DW_AT_name {{.*}}"FuncVar4" +; CHECK-NEXT: DW_AT_decl_file +; CHECK-NEXT: DW_AT_decl_line +; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[a-f0-9]+}} => {0x[[NONE]]}) + +; CHECK: 0x[[NONE]]: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type +; CHECK-NOT: DW_AT_address_class + +; CHECK: 0x[[LOCAL]]: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type +; CHECK-NEXT: DW_AT_address_class [DW_FORM_data4] (0x00000002) + +; CHECK: 0x[[PRIVATE]]: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type +; CHECK-NEXT: DW_AT_address_class [DW_FORM_data4] (0x00000001) + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +define amdgpu_kernel void @kernel1() !dbg !7 { +entry: + %FuncVar0 = alloca i32 addrspace(1)*, align 4 + %FuncVar1 = alloca i32 addrspace(2)*, align 4 + %FuncVar2 = alloca i32 addrspace(3)*, align 4 + %FuncVar3 = alloca i32*, align 4 + %FuncVar4 = alloca i32 addrspace(4)*, align 4 + call void @llvm.dbg.declare(metadata i32 addrspace(1)** %FuncVar0, metadata !10, metadata !13), !dbg !14 + store i32 addrspace(1)* null, i32 addrspace(1)** %FuncVar0, align 4, !dbg !14 + call void @llvm.dbg.declare(metadata i32 addrspace(2)** %FuncVar1, metadata !15, metadata !13), !dbg !16 + store i32 addrspace(2)* null, i32 addrspace(2)** %FuncVar1, align 4, !dbg !16 + call void @llvm.dbg.declare(metadata i32 addrspace(3)** %FuncVar2, metadata !17, metadata !13), !dbg !19 + store i32 addrspace(3)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(3)*), i32 addrspace(3)** %FuncVar2, align 4, !dbg !19 + call void @llvm.dbg.declare(metadata i32** %FuncVar3, metadata !20, metadata !13), !dbg !22 + store i32* addrspacecast (i32 addrspace(4)* null to i32*), i32** %FuncVar3, align 4, !dbg !22 + call void @llvm.dbg.declare(metadata i32 addrspace(4)** %FuncVar4, metadata !23, metadata !13), !dbg !24 + store i32 addrspace(4)* null, i32 addrspace(4)** %FuncVar4, align 4, !dbg !24 + ret void, !dbg !25 +} + +!llvm.dbg.cu = !{!0} +!opencl.ocl.version = !{!3} +!llvm.module.flags = !{!4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "pointer-address-space.ll", directory: "/some/random/directory") +!2 = !{} +!3 = !{i32 2, i32 0} +!4 = !{i32 2, !"Dwarf Version", i32 2} +!5 = !{i32 2, !"Debug Info Version", i32 3} +!6 = !{!""} +!7 = distinct !DISubprogram(name: "kernel1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocalVariable(name: "FuncVar0", scope: !7, file: !1, line: 2, type: !11) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DIExpression() +!14 = !DILocation(line: 2, column: 15, scope: !7) +!15 = !DILocalVariable(name: "FuncVar1", scope: !7, file: !1, line: 3, type: !11) +!16 = !DILocation(line: 3, column: 17, scope: !7) +!17 = !DILocalVariable(name: "FuncVar2", scope: !7, file: !1, line: 4, type: !18) +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 32, addressSpace: 2) +!19 = !DILocation(line: 4, column: 14, scope: !7) +!20 = !DILocalVariable(name: "FuncVar3", scope: !7, file: !1, line: 5, type: !21) +!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 32, addressSpace: 1) +!22 = !DILocation(line: 5, column: 16, scope: !7) +!23 = !DILocalVariable(name: "FuncVar4", scope: !7, file: !1, line: 6, type: !11) +!24 = !DILocation(line: 6, column: 8, scope: !7) +!25 = !DILocation(line: 7, column: 1, scope: !7) Index: test/Verifier/diderivedtype-address-space-atomic-type.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-atomic-type.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_atomic_type, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-const-type.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-const-type.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-friend.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-friend.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_friend, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-inheritance.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-inheritance.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_inheritance, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-member.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-member.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_member, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-ptr-to-member-type.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-ptr-to-member-type.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-restrict-type.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-restrict-type.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-rvalue-reference-type.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-rvalue-reference-type.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-typedef.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-typedef.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_typedef, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: test/Verifier/diderivedtype-address-space-volatile-type.ll =================================================================== --- /dev/null +++ test/Verifier/diderivedtype-address-space-volatile-type.ll @@ -0,0 +1,6 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0, !1} +!0 = !DIBasicType(tag: DW_TAG_base_type, name: "name", size: 1, align: 2, encoding: DW_ATE_unsigned_char) +; CHECK: address space only applies to pointer or reference types +!1 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !0, size: 32, align: 32, addressSpace: 1) Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -103,7 +103,7 @@ DIType *getDerivedType() { return DIDerivedType::getDistinct( Context, dwarf::DW_TAG_pointer_type, "", nullptr, 0, nullptr, - getBasicType("basictype"), 1, 2, 0, DINode::FlagZero); + getBasicType("basictype"), 1, 2, 0, None, DINode::FlagZero); } Constant *getConstant() { return ConstantInt::get(Type::getInt32Ty(Context), Counter++); @@ -1053,12 +1053,14 @@ DIScope *Scope = getSubprogram(); DIType *BaseType = getBasicType("basic"); MDTuple *ExtraData = getTuple(); + unsigned AddressSpace = 8; DINode::DIFlags Flags5 = static_cast(5); DINode::DIFlags Flags4 = static_cast(4); auto *N = DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, - 1, Scope, BaseType, 2, 3, 4, Flags5, ExtraData); + 1, Scope, BaseType, 2, 3, 4, AddressSpace, Flags5, + ExtraData); EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag()); EXPECT_EQ("something", N->getName()); EXPECT_EQ(File, N->getFile()); @@ -1068,45 +1070,51 @@ EXPECT_EQ(2u, N->getSizeInBits()); EXPECT_EQ(3u, N->getAlignInBits()); EXPECT_EQ(4u, N->getOffsetInBits()); + EXPECT_EQ(AddressSpace, N->getAddressSpace().getValue()); EXPECT_EQ(5u, N->getFlags()); EXPECT_EQ(ExtraData, N->getExtraData()); EXPECT_EQ(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, Flags5, ExtraData)); + 4, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_reference_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, Flags5, ExtraData)); + 4, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else", - File, 1, Scope, BaseType, 2, 3, 4, Flags5, - ExtraData)); + File, 1, Scope, BaseType, 2, 3, + 4, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", getFile(), 1, Scope, BaseType, 2, - 3, 4, Flags5, ExtraData)); + 3, 4, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 2, Scope, BaseType, 2, 3, - 4, Flags5, ExtraData)); + 4, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, getSubprogram(), - BaseType, 2, 3, 4, Flags5, ExtraData)); + BaseType, 2, 3, 4, AddressSpace, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get( Context, dwarf::DW_TAG_pointer_type, "something", File, 1, - Scope, getBasicType("basic2"), 2, 3, 4, Flags5, ExtraData)); + Scope, getBasicType("basic2"), 2, 3, 4, AddressSpace, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 3, 3, - 4, Flags5, ExtraData)); + 4, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 2, - 4, Flags5, ExtraData)); + 4, AddressSpace, Flags5, ExtraData)); + EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 2, 3, + 5, AddressSpace, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 5, Flags5, ExtraData)); + 4, AddressSpace + 1, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, Flags4, ExtraData)); + 4, AddressSpace, Flags4, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, Flags5, getTuple())); + 4, AddressSpace, Flags5, getTuple())); TempDIDerivedType Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -1121,10 +1129,12 @@ auto *N = DIDerivedType::get( Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, - BaseType, UINT64_MAX, UINT32_MAX - 1, UINT64_MAX - 2, Flags, ExtraData); + BaseType, UINT64_MAX, UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3, + Flags, ExtraData); EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits()); EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits()); + EXPECT_EQ(UINT32_MAX - 3, N->getAddressSpace().getValue()); } typedef MetadataTest DICompositeTypeTest;