llvm.org GIT mirror llvm / 18b9b9a
[CodeView] Implement support for bitfields in LLVM CodeView need to know the offset of the storage allocation for a bitfield. Encode this via the "extraData" field in DIDerivedType and introduced a new flag, DIFlagBitField, to indicate whether or not a member is a bitfield. This fixes PR28162. Differential Revision: http://reviews.llvm.org/D21782 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274200 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 4 years ago
6 changed file(s) with 272 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
193193 uint64_t OffsetInBits, unsigned Flags,
194194 DIType *Ty);
195195
196 /// Create debugging information entry for a bit field member.
197 /// \param Scope Member scope.
198 /// \param Name Member name.
199 /// \param File File where this member is defined.
200 /// \param LineNo Line number.
201 /// \param SizeInBits Member size.
202 /// \param AlignInBits Member alignment.
203 /// \param OffsetInBits Member offset.
204 /// \param StorageOffsetInBits Member storage offset.
205 /// \param Flags Flags to encode member attribute.
206 /// \param Ty Parent type.
207 DIDerivedType *createBitFieldMemberType(
208 DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
209 uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
210 uint64_t StorageOffsetInBits, unsigned Flags, DIType *Ty);
211
196212 /// Create debugging information entry for a
197213 /// C++ static data member.
198214 /// \param Scope Member scope.
3636 HANDLE_DI_FLAG((2 << 16), MultipleInheritance)
3737 HANDLE_DI_FLAG((3 << 16), VirtualInheritance)
3838 HANDLE_DI_FLAG((1 << 18), IntroducedVirtual)
39 HANDLE_DI_FLAG((1 << 19), BitField)
3940
4041 #undef HANDLE_DI_FLAG
580580 return getFlags() & FlagObjcClassComplete;
581581 }
582582 bool isVector() const { return getFlags() & FlagVector; }
583 bool isBitField() const { return getFlags() & FlagBitField; }
583584 bool isStaticMember() const { return getFlags() & FlagStaticMember; }
584585 bool isLValueReference() const { return getFlags() & FlagLValueReference; }
585586 bool isRValueReference() const { return getFlags() & FlagRValueReference; }
738739 }
739740 DIObjCProperty *getObjCProperty() const {
740741 return dyn_cast_or_null(getExtraData());
742 }
743 Constant *getStorageOffsetInBits() const {
744 assert(getTag() == dwarf::DW_TAG_member && isBitField());
745 if (auto *C = cast_or_null(getExtraData()))
746 return C->getValue();
747 return nullptr;
741748 }
742749 Constant *getConstant() const {
743750 assert(getTag() == dwarf::DW_TAG_member && isStaticMember());
1919 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
2020 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
2121 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
22 #include "llvm/IR/Constants.h"
2223 #include "llvm/MC/MCExpr.h"
2324 #include "llvm/MC/MCSectionCOFF.h"
2425 #include "llvm/MC/MCSymbol.h"
14991500 for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {
15001501 const DIDerivedType *Member = MemberInfo.MemberTypeNode;
15011502 TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
1503 StringRef MemberName = Member->getName();
1504 MemberAccess Access =
1505 translateAccessFlags(Ty->getTag(), Member->getFlags());
15021506
15031507 if (Member->isStaticMember()) {
1504 Fields.writeStaticDataMember(StaticDataMemberRecord(
1505 translateAccessFlags(Ty->getTag(), Member->getFlags()),
1506 MemberBaseType, Member->getName()));
1508 Fields.writeStaticDataMember(
1509 StaticDataMemberRecord(Access, MemberBaseType, MemberName));
15071510 MemberCount++;
15081511 continue;
15091512 }
15101513
1511 uint64_t OffsetInBytes = MemberInfo.BaseOffset;
1512
1513 // FIXME: Handle bitfield type memeber.
1514 OffsetInBytes += Member->getOffsetInBits() / 8;
1515
1516 Fields.writeDataMember(
1517 DataMemberRecord(translateAccessFlags(Ty->getTag(), Member->getFlags()),
1518 MemberBaseType, OffsetInBytes, Member->getName()));
1514 // Data member.
1515 uint64_t MemberOffsetInBits = Member->getOffsetInBits();
1516 if (Member->isBitField()) {
1517 uint64_t StartBitOffset = MemberOffsetInBits;
1518 if (const auto *CI =
1519 dyn_cast_or_null(Member->getStorageOffsetInBits())) {
1520 MemberOffsetInBits = CI->getZExtValue();
1521 }
1522 StartBitOffset -= MemberOffsetInBits;
1523 MemberBaseType = TypeTable.writeBitField(BitFieldRecord(
1524 MemberBaseType, Member->getSizeInBits(), StartBitOffset));
1525 }
1526 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
1527 Fields.writeDataMember(DataMemberRecord(Access, MemberBaseType,
1528 MemberOffsetInBytes, MemberName));
15191529 MemberCount++;
15201530 }
15211531
305305 if (C)
306306 return ConstantAsMetadata::get(C);
307307 return nullptr;
308 }
309
310 DIDerivedType *DIBuilder::createBitFieldMemberType(
311 DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
312 uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
313 uint64_t StorageOffsetInBits, unsigned Flags, DIType *Ty) {
314 Flags |= DINode::FlagBitField;
315 return DIDerivedType::get(
316 VMContext, dwarf::DW_TAG_member, Name, File, LineNumber,
317 getNonCompileUnitScope(Scope), Ty, SizeInBits, AlignInBits, OffsetInBits,
318 Flags, ConstantAsMetadata::get(ConstantInt::get(
319 IntegerType::get(VMContext, 64), StorageOffsetInBits)));
308320 }
309321
310322 DIDerivedType *DIBuilder::createStaticMemberType(DIScope *Scope, StringRef Name,
0 ; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
1
2 ; C++ source to regenerate:
3 ; $ cat t.cpp
4 ; #pragma pack(1)
5 ; struct S0 {
6 ; char : 8;
7 ; short : 8;
8 ; short x : 8;
9 ; } s0;
10 ;
11 ; #pragma pack(1)
12 ; struct S1 {
13 ; char x1[2];
14 ; char x2;
15 ; int y : 23;
16 ; int z : 23;
17 ; int w : 2;
18 ; struct { char c; short s; } v;
19 ; short u : 3;
20 ; } s1;
21 ;
22 ; #pragma pack(1)
23 ; struct S2 {
24 ; char : 0;
25 ; int y : 1;
26 ; } s2;
27 ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
28
29 ; CHECK: CodeViewTypes [
30 ; CHECK: BitField ([[S0_x:.*]]) {
31 ; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
32 ; CHECK: Type: short (0x11)
33 ; CHECK: BitSize: 8
34 ; CHECK: BitOffset: 8
35 ; CHECK: }
36 ; CHECK: FieldList ([[S0_fl:.*]]) {
37 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
38 ; CHECK: DataMember {
39 ; CHECK: Type: [[S0_x:.*]]
40 ; CHECK: FieldOffset: 0x1
41 ; CHECK: Name: x
42 ; CHECK: }
43 ; CHECK: }
44 ; CHECK: Struct ({{.*}}) {
45 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
46 ; CHECK: MemberCount: 1
47 ; CHECK: Properties [ (0x0)
48 ; CHECK: ]
49 ; CHECK: FieldList: ([[S0_fl]])
50 ; CHECK: SizeOf: 3
51 ; CHECK: Name: S0
52 ; CHECK: }
53 ; CHECK: BitField ([[S1_y_z:.*]]) {
54 ; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
55 ; CHECK: Type: int (0x74)
56 ; CHECK: BitSize: 23
57 ; CHECK: BitOffset: 0
58 ; CHECK: }
59 ; CHECK: BitField ([[S1_w:.*]]) {
60 ; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
61 ; CHECK: Type: int (0x74)
62 ; CHECK: BitSize: 2
63 ; CHECK: BitOffset: 23
64 ; CHECK: }
65 ; CHECK: BitField ([[S1_u:.*]]) {
66 ; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
67 ; CHECK: Type: short (0x11)
68 ; CHECK: BitSize: 3
69 ; CHECK: BitOffset: 0
70 ; CHECK: }
71 ; CHECK: FieldList ([[S1_fl:.*]]) {
72 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
73 ; CHECK: DataMember {
74 ; CHECK: FieldOffset: 0x0
75 ; CHECK: Name: x1
76 ; CHECK: }
77 ; CHECK: DataMember {
78 ; CHECK: Type: char (0x70)
79 ; CHECK: FieldOffset: 0x2
80 ; CHECK: Name: x2
81 ; CHECK: }
82 ; CHECK: DataMember {
83 ; CHECK: Type: [[S1_y_z]]
84 ; CHECK: FieldOffset: 0x3
85 ; CHECK: Name: y
86 ; CHECK: }
87 ; CHECK: DataMember {
88 ; CHECK: Type: [[S1_y_z]]
89 ; CHECK: FieldOffset: 0x7
90 ; CHECK: Name: z
91 ; CHECK: }
92 ; CHECK: DataMember {
93 ; CHECK: Type: [[S1_w]]
94 ; CHECK: FieldOffset: 0x7
95 ; CHECK: Name: w
96 ; CHECK: }
97 ; CHECK: DataMember {
98 ; CHECK: FieldOffset: 0xB
99 ; CHECK: Name: v
100 ; CHECK: }
101 ; CHECK: DataMember {
102 ; CHECK: Type: [[S1_u]]
103 ; CHECK: FieldOffset: 0xE
104 ; CHECK: Name: u
105 ; CHECK: }
106 ; CHECK: }
107 ; CHECK: Struct ({{.*}}) {
108 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
109 ; CHECK: MemberCount: 7
110 ; CHECK: Properties [ (0x0)
111 ; CHECK: ]
112 ; CHECK: FieldList: ([[S1_fl]])
113 ; CHECK: SizeOf: 16
114 ; CHECK: Name: S1
115 ; CHECK: }
116 ; CHECK: FieldList ([[anon_fl:.*]]) {
117 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
118 ; CHECK: DataMember {
119 ; CHECK: Type: char (0x70)
120 ; CHECK: FieldOffset: 0x0
121 ; CHECK: Name: c
122 ; CHECK: }
123 ; CHECK: DataMember {
124 ; CHECK: Type: short (0x11)
125 ; CHECK: FieldOffset: 0x1
126 ; CHECK: Name: s
127 ; CHECK: }
128 ; CHECK: }
129 ; CHECK: Struct ({{.*}}) {
130 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
131 ; CHECK: MemberCount: 2
132 ; CHECK: Properties [ (0x0)
133 ; CHECK: ]
134 ; CHECK: FieldList: ([[anon_fl]])
135 ; CHECK: SizeOf: 3
136 ; CHECK: Name: S1::
137 ; CHECK: }
138 ; CHECK: BitField ([[S2_y:.*]]) {
139 ; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
140 ; CHECK: Type: int (0x74)
141 ; CHECK: BitSize: 1
142 ; CHECK: BitOffset: 0
143 ; CHECK: }
144 ; CHECK: FieldList ([[S2_fl:.*]]) {
145 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
146 ; CHECK: DataMember {
147 ; CHECK: Type: [[S2_y]]
148 ; CHECK: FieldOffset: 0x0
149 ; CHECK: Name: y
150 ; CHECK: }
151 ; CHECK: }
152 ; CHECK: Struct ({{.*}}) {
153 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
154 ; CHECK: MemberCount: 1
155 ; CHECK: Properties [ (0x0)
156 ; CHECK: ]
157 ; CHECK: FieldList: ([[S2_fl]])
158 ; CHECK: SizeOf: 4
159 ; CHECK: Name: S2
160 ; CHECK: }
161
162 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
163 target triple = "x86_64-pc-windows-msvc18.0.0"
164
165 %struct.S0 = type <{ i8, i16 }>
166 %struct.S1 = type <{ [2 x i8], i8, i32, i32, %struct.anon, i16 }>
167 %struct.anon = type <{ i8, i16 }>
168 %struct.S2 = type { i32 }
169
170 @s0 = common global %struct.S0 zeroinitializer, align 1
171 @s1 = common global %struct.S1 zeroinitializer, align 1
172 @s2 = common global %struct.S2 zeroinitializer, align 1
173
174 !llvm.dbg.cu = !{!0}
175 !llvm.module.flags = !{!33, !34, !35}
176 !llvm.ident = !{!36}
177
178 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 273812) (llvm/trunk 273843)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
179 !1 = !DIFile(filename: "-", directory: "/usr/local/google/home/majnemer/llvm/src")
180 !2 = !{}
181 !3 = !{!4, !10, !29}
182 !4 = distinct !DIGlobalVariable(name: "s0", scope: !0, file: !5, line: 7, type: !6, isLocal: false, isDefinition: true, variable: %struct.S0* @s0)
183 !5 = !DIFile(filename: "", directory: "/usr/local/google/home/majnemer/llvm/src")
184 !6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S0", file: !5, line: 3, size: 24, align: 8, elements: !7)
185 !7 = !{!8}
186 !8 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !6, file: !5, line: 6, baseType: !9, size: 8, align: 16, offset: 16, flags: DIFlagBitField, extraData: i64 8)
187 !9 = !DIBasicType(name: "short", size: 16, align: 16, encoding: DW_ATE_signed)
188 !10 = distinct !DIGlobalVariable(name: "s1", scope: !0, file: !5, line: 18, type: !11, isLocal: false, isDefinition: true, variable: %struct.S1* @s1)
189 !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S1", file: !5, line: 10, size: 128, align: 8, elements: !12)
190 !12 = !{!13, !18, !19, !21, !22, !23, !28}
191 !13 = !DIDerivedType(tag: DW_TAG_member, name: "x1", scope: !11, file: !5, line: 11, baseType: !14, size: 16, align: 8)
192 !14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 16, align: 8, elements: !16)
193 !15 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
194 !16 = !{!17}
195 !17 = !DISubrange(count: 2)
196 !18 = !DIDerivedType(tag: DW_TAG_member, name: "x2", scope: !11, file: !5, line: 12, baseType: !15, size: 8, align: 8, offset: 16)
197 !19 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !5, line: 13, baseType: !20, size: 23, align: 32, offset: 24, flags: DIFlagBitField, extraData: i64 24)
198 !20 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
199 !21 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !11, file: !5, line: 14, baseType: !20, size: 23, align: 32, offset: 56, flags: DIFlagBitField, extraData: i64 56)
200 !22 = !DIDerivedType(tag: DW_TAG_member, name: "w", scope: !11, file: !5, line: 15, baseType: !20, size: 2, align: 32, offset: 79, flags: DIFlagBitField, extraData: i64 56)
201 !23 = !DIDerivedType(tag: DW_TAG_member, name: "v", scope: !11, file: !5, line: 16, baseType: !24, size: 24, align: 8, offset: 88)
202 !24 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !11, file: !5, line: 16, size: 24, align: 8, elements: !25)
203 !25 = !{!26, !27}
204 !26 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !24, file: !5, line: 16, baseType: !15, size: 8, align: 8)
205 !27 = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: !24, file: !5, line: 16, baseType: !9, size: 16, align: 16, offset: 8)
206 !28 = !DIDerivedType(tag: DW_TAG_member, name: "u", scope: !11, file: !5, line: 17, baseType: !9, size: 3, align: 16, offset: 112, flags: DIFlagBitField, extraData: i64 112)
207 !29 = distinct !DIGlobalVariable(name: "s2", scope: !0, file: !5, line: 24, type: !30, isLocal: false, isDefinition: true, variable: %struct.S2* @s2)
208 !30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S2", file: !5, line: 21, size: 32, align: 8, elements: !31)
209 !31 = !{!32}
210 !32 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !30, file: !5, line: 23, baseType: !20, size: 1, align: 32, flags: DIFlagBitField, extraData: i64 0)
211 !33 = !{i32 2, !"CodeView", i32 1}
212 !34 = !{i32 2, !"Debug Info Version", i32 3}
213 !35 = !{i32 1, !"PIC Level", i32 2}
214 !36 = !{!"clang version 3.9.0 (trunk 273812) (llvm/trunk 273843)"}