[DWARF] Versioning for DWARF constants; verify FORMs

Associate the version-when-defined with definitions of standard DWARF
constants.  Identify the "vendor" for DWARF extensions.
Use this information to verify FORMs in .debug_abbrev are defined as
of the DWARF version specified in the associated unit.
Removed two tests that had specified DWARF v1 (which essentially does
not exist).

Differential Revision: http://reviews.llvm.org/D30785


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300875 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Paul Robinson 2017-04-20 19:16:51 +00:00
parent 1ec650ee5f
commit ce35560497
9 changed files with 800 additions and 748 deletions

View File

@ -236,7 +236,7 @@ template <> struct MappingTraits<DWARFYAML::InitialLength> {
static void mapping(IO &IO, DWARFYAML::InitialLength &DWARF);
};
#define HANDLE_DW_TAG(unused, name) \
#define HANDLE_DW_TAG(unused, name, unused2, unused3) \
io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name);
template <> struct ScalarEnumerationTraits<dwarf::Tag> {
@ -266,7 +266,7 @@ template <> struct ScalarEnumerationTraits<dwarf::LineNumberExtendedOps> {
}
};
#define HANDLE_DW_AT(unused, name) \
#define HANDLE_DW_AT(unused, name, unused2, unused3) \
io.enumCase(value, "DW_AT_" #name, dwarf::DW_AT_##name);
template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
@ -276,7 +276,7 @@ template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
}
};
#define HANDLE_DW_FORM(unused, name) \
#define HANDLE_DW_FORM(unused, name, unused2, unused3) \
io.enumCase(value, "DW_FORM_" #name, dwarf::DW_FORM_##name);
template <> struct ScalarEnumerationTraits<dwarf::Form> {

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,15 @@ enum LLVMConstants : uint32_t {
DWARF_VERSION = 4, // Default dwarf version we output.
DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes.
DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames.
DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges.
DW_ARANGES_VERSION = 2, // Section version number for .debug_aranges.
// Identifiers we use to distinguish vendor extensions.
DWARF_VENDOR_DWARF = 0, // Defined in v2 or later of the DWARF standard.
DWARF_VENDOR_APPLE = 1,
DWARF_VENDOR_BORLAND = 2,
DWARF_VENDOR_GNU = 3,
DWARF_VENDOR_GOOGLE = 4,
DWARF_VENDOR_LLVM = 5,
DWARF_VENDOR_MIPS = 6
};
// Special ID values that distinguish a CIE from a FDE in DWARF CFI.
@ -55,7 +63,7 @@ const uint32_t DW_CIE_ID = UINT32_MAX;
const uint64_t DW64_CIE_ID = UINT64_MAX;
enum Tag : uint16_t {
#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID,
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) DW_TAG_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_TAG_lo_user = 0x4080,
DW_TAG_hi_user = 0xffff,
@ -92,20 +100,20 @@ inline bool isType(Tag T) {
/// Attributes.
enum Attribute : uint16_t {
#define HANDLE_DW_AT(ID, NAME) DW_AT_##NAME = ID,
#define HANDLE_DW_AT(ID, NAME, VERSION, VENDOR) DW_AT_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_AT_lo_user = 0x2000,
DW_AT_hi_user = 0x3fff,
};
enum Form : uint16_t {
#define HANDLE_DW_FORM(ID, NAME) DW_FORM_##NAME = ID,
#define HANDLE_DW_FORM(ID, NAME, VERSION, VENDOR) DW_FORM_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_FORM_lo_user = 0x1f00, ///< Not specified by DWARF.
};
enum LocationAtom {
#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID,
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) DW_OP_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_OP_lo_user = 0xe0,
DW_OP_hi_user = 0xff,
@ -113,7 +121,7 @@ enum LocationAtom {
};
enum TypeKind {
#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID,
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) DW_ATE_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_ATE_lo_user = 0x80,
DW_ATE_hi_user = 0xff
@ -164,7 +172,7 @@ enum DefaultedMemberAttribute {
};
enum SourceLanguage {
#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID,
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) DW_LANG_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_LANG_lo_user = 0x8000,
DW_LANG_hi_user = 0xffff
@ -406,6 +414,40 @@ unsigned getAttributeEncoding(StringRef EncodingString);
unsigned getMacinfo(StringRef MacinfoString);
/// @}
/// \defgroup DwarfConstantsVersioning Dwarf version for constants
///
/// For constants defined by DWARF, returns the DWARF version when the constant
/// was first defined. For vendor extensions, if there is a version-related
/// policy for when to emit it, returns a version number for that policy.
/// Otherwise returns 0.
///
/// @{
unsigned TagVersion(Tag T);
unsigned AttributeVersion(Attribute A);
unsigned FormVersion(Form F);
unsigned OperationVersion(LocationAtom O);
unsigned AttributeEncodingVersion(TypeKind E);
unsigned LanguageVersion(SourceLanguage L);
/// @}
/// \defgroup DwarfConstantsVendor Dwarf "vendor" for constants
///
/// These functions return an identifier describing "who" defined the constant,
/// either the DWARF standard itself or the vendor who defined the extension.
///
/// @{
unsigned TagVendor(Tag T);
unsigned AttributeVendor(Attribute A);
unsigned FormVendor(Form F);
unsigned OperationVendor(LocationAtom O);
unsigned AttributeEncodingVendor(TypeKind E);
unsigned LanguageVendor(SourceLanguage L);
/// @}
/// Tells whether the specified form is defined in the specified version,
/// or is an extension if extensions are allowed.
bool isValidFormForVersion(Form F, unsigned Version, bool ExtensionsOk = true);
/// \brief Returns the symbolic string representing Val when used as a value
/// for attribute Attr.
StringRef AttributeValueString(uint16_t Attr, unsigned Val);

View File

@ -31,6 +31,8 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
//===----------------------------------------------------------------------===//
// DIEAbbrevData Implementation
//===----------------------------------------------------------------------===//
@ -79,15 +81,22 @@ void DIEAbbrev::Emit(const AsmPrinter *AP) const {
dwarf::AttributeString(AttrData.getAttribute()).data());
// Emit form type.
#ifndef NDEBUG
// Could be an assertion, but this way we can see the failing form code
// easily, which helps track down where it came from.
if (!dwarf::isValidFormForVersion(AttrData.getForm(),
AP->getDwarfVersion())) {
DEBUG(dbgs() << "Invalid form " << format("0x%x", AttrData.getForm())
<< " for DWARF version " << AP->getDwarfVersion() << "\n");
llvm_unreachable("Invalid form for specified DWARF version");
}
#endif
AP->EmitULEB128(AttrData.getForm(),
dwarf::FormEncodingString(AttrData.getForm()).data());
// Emit value for DW_FORM_implicit_const.
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) {
assert(AP->getDwarfVersion() >= 5 &&
"DW_FORM_implicit_const is supported starting from DWARFv5");
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
AP->EmitSLEB128(AttrData.getValue());
}
}
// Mark end of abbreviation.

View File

@ -22,7 +22,7 @@ StringRef llvm::dwarf::TagString(unsigned Tag) {
switch (Tag) {
default:
return StringRef();
#define HANDLE_DW_TAG(ID, NAME) \
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) \
case DW_TAG_##NAME: \
return "DW_TAG_" #NAME;
#include "llvm/Support/Dwarf.def"
@ -31,11 +31,34 @@ StringRef llvm::dwarf::TagString(unsigned Tag) {
unsigned llvm::dwarf::getTag(StringRef TagString) {
return StringSwitch<unsigned>(TagString)
#define HANDLE_DW_TAG(ID, NAME) .Case("DW_TAG_" #NAME, DW_TAG_##NAME)
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) \
.Case("DW_TAG_" #NAME, DW_TAG_##NAME)
#include "llvm/Support/Dwarf.def"
.Default(DW_TAG_invalid);
}
unsigned llvm::dwarf::TagVersion(dwarf::Tag Tag) {
switch (Tag) {
default:
return 0;
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) \
case DW_TAG_##NAME: \
return VERSION;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::TagVendor(dwarf::Tag Tag) {
switch (Tag) {
default:
return 0;
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) \
case DW_TAG_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/Support/Dwarf.def"
}
}
StringRef llvm::dwarf::ChildrenString(unsigned Children) {
switch (Children) {
case DW_CHILDREN_no: return "DW_CHILDREN_no";
@ -48,29 +71,73 @@ StringRef llvm::dwarf::AttributeString(unsigned Attribute) {
switch (Attribute) {
default:
return StringRef();
#define HANDLE_DW_AT(ID, NAME) \
case DW_AT_##NAME: \
#define HANDLE_DW_AT(ID, NAME, VERSION, VENDOR) \
case DW_AT_##NAME: \
return "DW_AT_" #NAME;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::AttributeVersion(dwarf::Attribute Attribute) {
switch (Attribute) {
default:
return 0;
#define HANDLE_DW_AT(ID, NAME, VERSION, VENDOR) \
case DW_AT_##NAME: \
return VERSION;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::AttributeVendor(dwarf::Attribute Attribute) {
switch (Attribute) {
default:
return 0;
#define HANDLE_DW_AT(ID, NAME, VERSION, VENDOR) \
case DW_AT_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/Support/Dwarf.def"
}
}
StringRef llvm::dwarf::FormEncodingString(unsigned Encoding) {
switch (Encoding) {
default:
return StringRef();
#define HANDLE_DW_FORM(ID, NAME) \
case DW_FORM_##NAME: \
#define HANDLE_DW_FORM(ID, NAME, VERSION, VENDOR) \
case DW_FORM_##NAME: \
return "DW_FORM_" #NAME;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::FormVersion(dwarf::Form Form) {
switch (Form) {
default:
return 0;
#define HANDLE_DW_FORM(ID, NAME, VERSION, VENDOR) \
case DW_FORM_##NAME: \
return VERSION;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::FormVendor(dwarf::Form Form) {
switch (Form) {
default:
return 0;
#define HANDLE_DW_FORM(ID, NAME, VERSION, VENDOR) \
case DW_FORM_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/Support/Dwarf.def"
}
}
StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
switch (Encoding) {
default:
return StringRef();
#define HANDLE_DW_OP(ID, NAME) \
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) \
case DW_OP_##NAME: \
return "DW_OP_" #NAME;
#include "llvm/Support/Dwarf.def"
@ -81,17 +148,40 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
return StringSwitch<unsigned>(OperationEncodingString)
#define HANDLE_DW_OP(ID, NAME) .Case("DW_OP_" #NAME, DW_OP_##NAME)
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) \
.Case("DW_OP_" #NAME, DW_OP_##NAME)
#include "llvm/Support/Dwarf.def"
.Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
.Default(0);
}
unsigned llvm::dwarf::OperationVersion(dwarf::LocationAtom Op) {
switch (Op) {
default:
return 0;
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) \
case DW_OP_##NAME: \
return VERSION;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::OperationVendor(dwarf::LocationAtom Op) {
switch (Op) {
default:
return 0;
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) \
case DW_OP_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/Support/Dwarf.def"
}
}
StringRef llvm::dwarf::AttributeEncodingString(unsigned Encoding) {
switch (Encoding) {
default:
return StringRef();
#define HANDLE_DW_ATE(ID, NAME) \
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) \
case DW_ATE_##NAME: \
return "DW_ATE_" #NAME;
#include "llvm/Support/Dwarf.def"
@ -100,11 +190,34 @@ StringRef llvm::dwarf::AttributeEncodingString(unsigned Encoding) {
unsigned llvm::dwarf::getAttributeEncoding(StringRef EncodingString) {
return StringSwitch<unsigned>(EncodingString)
#define HANDLE_DW_ATE(ID, NAME) .Case("DW_ATE_" #NAME, DW_ATE_##NAME)
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) \
.Case("DW_ATE_" #NAME, DW_ATE_##NAME)
#include "llvm/Support/Dwarf.def"
.Default(0);
}
unsigned llvm::dwarf::AttributeEncodingVersion(dwarf::TypeKind ATE) {
switch (ATE) {
default:
return 0;
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) \
case DW_ATE_##NAME: \
return VERSION;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::AttributeEncodingVendor(dwarf::TypeKind ATE) {
switch (ATE) {
default:
return 0;
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) \
case DW_ATE_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/Support/Dwarf.def"
}
}
StringRef llvm::dwarf::DecimalSignString(unsigned Sign) {
switch (Sign) {
case DW_DS_unsigned: return "DW_DS_unsigned";
@ -169,7 +282,7 @@ StringRef llvm::dwarf::LanguageString(unsigned Language) {
switch (Language) {
default:
return StringRef();
#define HANDLE_DW_LANG(ID, NAME) \
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
case DW_LANG_##NAME: \
return "DW_LANG_" #NAME;
#include "llvm/Support/Dwarf.def"
@ -178,11 +291,34 @@ StringRef llvm::dwarf::LanguageString(unsigned Language) {
unsigned llvm::dwarf::getLanguage(StringRef LanguageString) {
return StringSwitch<unsigned>(LanguageString)
#define HANDLE_DW_LANG(ID, NAME) .Case("DW_LANG_" #NAME, DW_LANG_##NAME)
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
.Case("DW_LANG_" #NAME, DW_LANG_##NAME)
#include "llvm/Support/Dwarf.def"
.Default(0);
}
unsigned llvm::dwarf::LanguageVersion(dwarf::SourceLanguage Lang) {
switch (Lang) {
default:
return 0;
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
case DW_LANG_##NAME: \
return VERSION;
#include "llvm/Support/Dwarf.def"
}
}
unsigned llvm::dwarf::LanguageVendor(dwarf::SourceLanguage Lang) {
switch (Lang) {
default:
return 0;
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
case DW_LANG_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/Support/Dwarf.def"
}
}
StringRef llvm::dwarf::CaseString(unsigned Case) {
switch (Case) {
case DW_ID_case_sensitive: return "DW_ID_case_sensitive";
@ -394,3 +530,12 @@ StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) {
return StringRef();
}
bool llvm::dwarf::isValidFormForVersion(Form F, unsigned Version,
bool ExtensionsOk) {
if (FormVendor(F) == DWARF_VENDOR_DWARF) {
unsigned FV = FormVersion(F);
return FV > 0 && FV <= Version;
}
return ExtensionsOk;
}

View File

@ -1,70 +0,0 @@
; 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 <path-to-file>
;
; 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, dwarfAddressSpace: 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, dwarfAddressSpace: 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)

View File

@ -1,92 +0,0 @@
; RUN: llc -O0 -mtriple=amdgcn-amd-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 <path-to-file>
;
; global int GlobA;
; global int GlobB;
;
; kernel void kernel1(unsigned int ArgN, global int *ArgA, global int *ArgB) {
; ArgA[ArgN] += ArgB[ArgN];
; }
declare void @llvm.dbg.declare(metadata, metadata, metadata)
; CHECK-NOT: DW_AT_location [DW_FORM_block1] (<0x05> 03 00 00 00 00 )
@GlobA = common addrspace(1) global i32 0, align 4, !dbg !0
; CHECK-NOT: DW_AT_location [DW_FORM_block1] (<0x05> 03 00 00 00 00 )
@GlobB = common addrspace(1) global i32 0, align 4, !dbg !6
define amdgpu_kernel void @kernel1(
; CHECK-NOT: DW_AT_location [DW_FORM_block1] (<0x06> 91 04 10 01 16 18 )
i32 %ArgN,
; CHECK-NOT: DW_AT_location [DW_FORM_block1] (<0x06> 91 08 10 01 16 18 )
i32 addrspace(1)* %ArgA,
; CHECK-NOT: DW_AT_location [DW_FORM_block1] (<0x06> 91 10 10 01 16 18 )
i32 addrspace(1)* %ArgB) !dbg !13 {
entry:
%ArgN.addr = alloca i32, align 4
%ArgA.addr = alloca i32 addrspace(1)*, align 4
%ArgB.addr = alloca i32 addrspace(1)*, align 4
store i32 %ArgN, i32* %ArgN.addr, align 4
call void @llvm.dbg.declare(metadata i32* %ArgN.addr, metadata !22, metadata !23), !dbg !24
store i32 addrspace(1)* %ArgA, i32 addrspace(1)** %ArgA.addr, align 4
call void @llvm.dbg.declare(metadata i32 addrspace(1)** %ArgA.addr, metadata !25, metadata !23), !dbg !26
store i32 addrspace(1)* %ArgB, i32 addrspace(1)** %ArgB.addr, align 4
call void @llvm.dbg.declare(metadata i32 addrspace(1)** %ArgB.addr, metadata !27, metadata !23), !dbg !28
%0 = load i32 addrspace(1)*, i32 addrspace(1)** %ArgB.addr, align 4, !dbg !29
%1 = load i32, i32* %ArgN.addr, align 4, !dbg !30
%idxprom = zext i32 %1 to i64, !dbg !29
%arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %0, i64 %idxprom, !dbg !29
%2 = load i32, i32 addrspace(1)* %arrayidx, align 4, !dbg !29
%3 = load i32 addrspace(1)*, i32 addrspace(1)** %ArgA.addr, align 4, !dbg !31
%4 = load i32, i32* %ArgN.addr, align 4, !dbg !32
%idxprom1 = zext i32 %4 to i64, !dbg !31
%arrayidx2 = getelementptr inbounds i32, i32 addrspace(1)* %3, i64 %idxprom1, !dbg !31
%5 = load i32, i32 addrspace(1)* %arrayidx2, align 4, !dbg !33
%add = add nsw i32 %5, %2, !dbg !33
store i32 %add, i32 addrspace(1)* %arrayidx2, align 4, !dbg !33
ret void, !dbg !34
}
!llvm.dbg.cu = !{!2}
!opencl.ocl.version = !{!9}
!llvm.module.flags = !{!10, !11}
!llvm.ident = !{!12}
!0 = !DIGlobalVariableExpression(var: !1)
!1 = distinct !DIGlobalVariable(name: "GlobA", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 5.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
!3 = !DIFile(filename: "variable-locations-dwarf-v1.cl", directory: "/some/random/directory")
!4 = !{}
!5 = !{!0, !6}
!6 = !DIGlobalVariableExpression(var: !7)
!7 = distinct !DIGlobalVariable(name: "GlobB", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true)
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!9 = !{i32 2, i32 0}
!10 = !{i32 2, !"Dwarf Version", i32 1}
!11 = !{i32 2, !"Debug Info Version", i32 3}
!12 = !{!"clang version 5.0.0"}
!13 = distinct !DISubprogram(name: "kernel1", scope: !3, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4)
!14 = !DISubroutineType(types: !15)
!15 = !{null, !16, !17, !17}
!16 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
!18 = !{i32 0, i32 1, i32 1}
!19 = !{!"none", !"none", !"none"}
!20 = !{!"uint", !"int*", !"int*"}
!21 = !{!"", !"", !""}
!22 = !DILocalVariable(name: "ArgN", arg: 1, scope: !13, file: !3, line: 4, type: !16)
!23 = !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)
!24 = !DILocation(line: 4, column: 34, scope: !13)
!25 = !DILocalVariable(name: "ArgA", arg: 2, scope: !13, file: !3, line: 4, type: !17)
!26 = !DILocation(line: 4, column: 52, scope: !13)
!27 = !DILocalVariable(name: "ArgB", arg: 3, scope: !13, file: !3, line: 4, type: !17)
!28 = !DILocation(line: 4, column: 70, scope: !13)
!29 = !DILocation(line: 5, column: 17, scope: !13)
!30 = !DILocation(line: 5, column: 22, scope: !13)
!31 = !DILocation(line: 5, column: 3, scope: !13)
!32 = !DILocation(line: 5, column: 8, scope: !13)
!33 = !DILocation(line: 5, column: 14, scope: !13)
!34 = !DILocation(line: 6, column: 1, scope: !13)

View File

@ -522,7 +522,8 @@ public:
/// \brief Emit the abbreviation table \p Abbrevs to the
/// debug_abbrev section.
void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs);
void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
unsigned DwarfVersion);
/// \brief Emit the string table described by \p Pool.
void emitStrings(const NonRelocatableStringpool &Pool);
@ -690,8 +691,10 @@ void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit) {
/// \brief Emit the \p Abbrevs array as the shared abbreviation table
/// for the linked Dwarf file.
void DwarfStreamer::emitAbbrevs(
const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs) {
const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
unsigned DwarfVersion) {
MS->SwitchSection(MOFI->getDwarfAbbrevSection());
MC->setDwarfVersion(DwarfVersion);
Asm->emitDwarfAbbrevs(Abbrevs);
}
@ -1129,6 +1132,12 @@ private:
/// \brief Called at the end of a debug object link.
void endDebugObject();
/// Remembers the newest DWARF version we've seen in a unit.
void maybeUpdateMaxDwarfVersion(unsigned Version) {
if (MaxDwarfVersion < Version)
MaxDwarfVersion = Version;
}
/// Keeps track of relocations.
class RelocationManager {
struct ValidReloc {
@ -1430,6 +1439,7 @@ private:
std::unique_ptr<DwarfStreamer> Streamer;
uint64_t OutputDebugInfoSize;
unsigned UnitID; ///< A unique ID that identifies each compile unit.
unsigned MaxDwarfVersion = 0;
/// The units of the current debug map object.
std::vector<std::unique_ptr<CompileUnit>> Units;
@ -3435,9 +3445,11 @@ bool DwarfLinker::link(const DebugMap &Map) {
CUDie.dump(outs(), 0);
}
if (!registerModuleReference(CUDie, *CU, ModuleMap))
if (!registerModuleReference(CUDie, *CU, ModuleMap)) {
Units.push_back(llvm::make_unique<CompileUnit>(*CU, UnitID++,
!Options.NoODR, ""));
maybeUpdateMaxDwarfVersion(CU->getVersion());
}
}
// Now build the DIE parent links that we will use during the next phase.
@ -3471,7 +3483,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
// Emit everything that's global.
if (!Options.NoOutput) {
Streamer->emitAbbrevs(Abbreviations);
Streamer->emitAbbrevs(Abbreviations, MaxDwarfVersion);
Streamer->emitStrings(StringPool);
}

View File

@ -170,7 +170,8 @@ void TestAllForms() {
CUDie.addAttribute(Attr_DW_FORM_ref8, DW_FORM_ref8, Data8);
const auto Attr_DW_FORM_ref_sig8 = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_ref_sig8, DW_FORM_ref_sig8, Data8_2);
if (Version >= 4)
CUDie.addAttribute(Attr_DW_FORM_ref_sig8, DW_FORM_ref_sig8, Data8_2);
const auto Attr_DW_FORM_ref_udata = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_ref_udata, DW_FORM_ref_udata, UData[0]);
@ -185,7 +186,8 @@ void TestAllForms() {
CUDie.addAttribute(Attr_DW_FORM_flag_false, DW_FORM_flag, false);
const auto Attr_DW_FORM_flag_present = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_flag_present, DW_FORM_flag_present);
if (Version >= 4)
CUDie.addAttribute(Attr_DW_FORM_flag_present, DW_FORM_flag_present);
//----------------------------------------------------------------------
// Test SLEB128 based forms
@ -213,8 +215,9 @@ void TestAllForms() {
Dwarf32Values[0]);
const auto Attr_DW_FORM_sec_offset = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_sec_offset, DW_FORM_sec_offset,
Dwarf32Values[1]);
if (Version >= 4)
CUDie.addAttribute(Attr_DW_FORM_sec_offset, DW_FORM_sec_offset,
Dwarf32Values[1]);
//----------------------------------------------------------------------
// Add an address at the end to make sure we can decode this value
@ -307,7 +310,8 @@ void TestAllForms() {
EXPECT_EQ(Data2, toReference(DieDG.find(Attr_DW_FORM_ref2), 0));
EXPECT_EQ(Data4, toReference(DieDG.find(Attr_DW_FORM_ref4), 0));
EXPECT_EQ(Data8, toReference(DieDG.find(Attr_DW_FORM_ref8), 0));
EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0));
if (Version >= 4)
EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0));
EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0));
//----------------------------------------------------------------------
@ -315,7 +319,8 @@ void TestAllForms() {
//----------------------------------------------------------------------
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_true), 0));
EXPECT_EQ(0ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_false), 1));
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0));
if (Version >= 4)
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0));
//----------------------------------------------------------------------
// Test SLEB128 based forms
@ -334,8 +339,9 @@ void TestAllForms() {
//----------------------------------------------------------------------
EXPECT_EQ(Dwarf32Values[0],
toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0));
EXPECT_EQ(Dwarf32Values[1],
toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0));
if (Version >= 4)
EXPECT_EQ(Dwarf32Values[1],
toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0));
//----------------------------------------------------------------------
// Add an address at the end to make sure we can decode this value