Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit bfdde98

Browse files
committed
Debug Info: Support DW_AT_calling_convention on composite types.
This implements the DWARF 5 feature described at http://www.dwarfstd.org/ShowIssue.php?issue=141215.1 This allows a consumer to understand whether a composite data type is trivially copyable and thus should be passed by value instead of by reference. The canonical example is being able to distinguish the following two types: // S is not trivially copyable because of the explicit destructor. struct S { ~S() {} }; // T is a POD type. struct T { ~T() = default; }; This patch adds two new (DI)flags to LLVM metadata: TypePassByValue and TypePassByReference. <rdar://problem/36034922> Differential Revision: https://reviews.llvm.org/D41743 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321844 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 60d5d5c commit bfdde98

File tree

7 files changed

+91
-3
lines changed

7 files changed

+91
-3
lines changed

include/llvm-c/DebugInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ typedef enum {
5252
LLVMDIFlagBitField = 1 << 19,
5353
LLVMDIFlagNoReturn = 1 << 20,
5454
LLVMDIFlagMainSubprogram = 1 << 21,
55+
LLVMDIFlagTypePassByValue = 1 << 22,
56+
LLVMDIFlagTypePassByReference = 1 << 23,
5557
LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5),
5658
LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected |
5759
LLVMDIFlagPublic,

include/llvm/IR/DebugInfoFlags.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ HANDLE_DI_FLAG((1 << 18), IntroducedVirtual)
4343
HANDLE_DI_FLAG((1 << 19), BitField)
4444
HANDLE_DI_FLAG((1 << 20), NoReturn)
4545
HANDLE_DI_FLAG((1 << 21), MainSubprogram)
46+
HANDLE_DI_FLAG((1 << 22), TypePassByValue)
47+
HANDLE_DI_FLAG((1 << 23), TypePassByReference)
4648

4749
// To avoid needing a dedicated value for IndirectVirtualBase, we use
4850
// the bitwise or of Virtual and FwdDecl, which does not otherwise
@@ -52,7 +54,7 @@ HANDLE_DI_FLAG((1 << 2) | (1 << 5), IndirectVirtualBase)
5254
#ifdef DI_FLAG_LARGEST_NEEDED
5355
// intended to be used with ADT/BitmaskEnum.h
5456
// NOTE: always must be equal to largest flag, check this when adding new flag
55-
HANDLE_DI_FLAG((1 << 21), Largest)
57+
HANDLE_DI_FLAG((1 << 23), Largest)
5658
#undef DI_FLAG_LARGEST_NEEDED
5759
#endif
5860

include/llvm/IR/DebugInfoMetadata.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,10 @@ class DIType : public DIScope {
633633
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
634634
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
635635
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
636+
bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; }
637+
bool isTypePassByReference() const {
638+
return getFlags() & FlagTypePassByReference;
639+
}
636640

637641
static bool classof(const Metadata *MD) {
638642
switch (MD->getMetadataID()) {

lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,15 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
975975
Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type)
976976
addTemplateParams(Buffer, CTy->getTemplateParams());
977977

978+
// Add the type's non-standard calling convention.
979+
uint8_t CC = 0;
980+
if (CTy->isTypePassByValue())
981+
CC = dwarf::DW_CC_pass_by_value;
982+
else if (CTy->isTypePassByReference())
983+
CC = dwarf::DW_CC_pass_by_reference;
984+
if (CC)
985+
addUInt(Buffer, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1,
986+
CC);
978987
break;
979988
}
980989
default:

lib/IR/Verifier.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,12 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
905905
}
906906
}
907907

908+
/// Detect mutually exclusive flags.
908909
static bool hasConflictingReferenceFlags(unsigned Flags) {
909-
return (Flags & DINode::FlagLValueReference) &&
910-
(Flags & DINode::FlagRValueReference);
910+
return ((Flags & DINode::FlagLValueReference) &&
911+
(Flags & DINode::FlagRValueReference)) ||
912+
((Flags & DINode::FlagTypePassByValue) &&
913+
(Flags & DINode::FlagTypePassByReference));
911914
}
912915

913916
void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-info - | FileCheck %s
2+
;
3+
; // S is not trivially copyable.
4+
; struct S {
5+
; ~S() {}
6+
; };
7+
;
8+
; // T is a POD.
9+
; struct T {
10+
; ~T() = default;
11+
; };
12+
;
13+
; S s;
14+
; T t;
15+
;
16+
; CHECK: DW_TAG_structure_type
17+
; CHECK-NEXT: DW_AT_calling_convention (DW_CC_pass_by_reference)
18+
; CHECK-NEXT: DW_AT_name ("S")
19+
;
20+
; CHECK: DW_TAG_structure_type
21+
; CHECK-NEXT: DW_AT_calling_convention (DW_CC_pass_by_value)
22+
; CHECK-NEXT: DW_AT_name ("T")
23+
24+
source_filename = "pass.cpp"
25+
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
26+
target triple = "x86_64-apple-macosx10.13.0"
27+
28+
%struct.S = type { i8 }
29+
%struct.T = type { i8 }
30+
31+
@s = global %struct.S zeroinitializer, align 1, !dbg !0
32+
@__dso_handle = external hidden global i8
33+
@t = global %struct.T zeroinitializer, align 1, !dbg !6
34+
35+
!llvm.dbg.cu = !{!2}
36+
!llvm.module.flags = !{!20, !21, !22, !23}
37+
!llvm.ident = !{!24}
38+
39+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
40+
!1 = distinct !DIGlobalVariable(name: "s", scope: !2, file: !3, line: 9, type: !14, isLocal: false, isDefinition: true)
41+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (trunk 321763) (llvm/trunk 321758)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
42+
!3 = !DIFile(filename: "pass.cpp", directory: "/")
43+
!4 = !{}
44+
!5 = !{!0, !6}
45+
!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
46+
!7 = distinct !DIGlobalVariable(name: "t", scope: !2, file: !3, line: 10, type: !8, isLocal: false, isDefinition: true)
47+
!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "T", file: !3, line: 5, size: 8, elements: !9, identifier: "_ZTS1T", flags: DIFlagTypePassByValue)
48+
!9 = !{!10}
49+
!10 = !DISubprogram(name: "~T", scope: !8, file: !3, line: 6, type: !11, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false)
50+
!11 = !DISubroutineType(types: !12)
51+
!12 = !{null, !13}
52+
!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
53+
!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 1, size: 8, elements: !15, identifier: "_ZTS1S", flags: DIFlagTypePassByReference)
54+
!15 = !{!16}
55+
!16 = !DISubprogram(name: "~S", scope: !14, file: !3, line: 2, type: !17, isLocal: false, isDefinition: false, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false)
56+
!17 = !DISubroutineType(types: !18)
57+
!18 = !{null, !19}
58+
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
59+
!20 = !{i32 2, !"Dwarf Version", i32 4}
60+
!21 = !{i32 2, !"Debug Info Version", i32 3}
61+
!22 = !{i32 1, !"wchar_size", i32 4}
62+
!23 = !{i32 7, !"PIC Level", i32 2}
63+
!24 = !{!"clang version 7.0.0 (trunk 321763) (llvm/trunk 321758)"}

test/Verifier/cc-flags.ll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
; RUN: not opt -S < %s 2>&1 | FileCheck %s
2+
3+
!named = !{!0}
4+
!0 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", size: 1, flags: DIFlagTypePassByReference | DIFlagTypePassByValue)
5+
; CHECK: invalid reference flags

0 commit comments

Comments
 (0)