1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[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

llvm-svn: 274200
This commit is contained in:
David Majnemer 2016-06-30 03:00:20 +00:00
parent 461b4dc08b
commit 12b9df8e32
6 changed files with 272 additions and 11 deletions

View File

@ -194,6 +194,22 @@ namespace llvm {
uint64_t OffsetInBits, unsigned Flags,
DIType *Ty);
/// Create debugging information entry for a bit field member.
/// \param Scope Member scope.
/// \param Name Member name.
/// \param File File where this member is defined.
/// \param LineNo Line number.
/// \param SizeInBits Member size.
/// \param AlignInBits Member alignment.
/// \param OffsetInBits Member offset.
/// \param StorageOffsetInBits Member storage offset.
/// \param Flags Flags to encode member attribute.
/// \param Ty Parent type.
DIDerivedType *createBitFieldMemberType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
uint64_t StorageOffsetInBits, unsigned Flags, DIType *Ty);
/// Create debugging information entry for a
/// C++ static data member.
/// \param Scope Member scope.

View File

@ -37,5 +37,6 @@ HANDLE_DI_FLAG((1 << 16), SingleInheritance)
HANDLE_DI_FLAG((2 << 16), MultipleInheritance)
HANDLE_DI_FLAG((3 << 16), VirtualInheritance)
HANDLE_DI_FLAG((1 << 18), IntroducedVirtual)
HANDLE_DI_FLAG((1 << 19), BitField)
#undef HANDLE_DI_FLAG

View File

@ -581,6 +581,7 @@ public:
return getFlags() & FlagObjcClassComplete;
}
bool isVector() const { return getFlags() & FlagVector; }
bool isBitField() const { return getFlags() & FlagBitField; }
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
@ -740,6 +741,12 @@ public:
DIObjCProperty *getObjCProperty() const {
return dyn_cast_or_null<DIObjCProperty>(getExtraData());
}
Constant *getStorageOffsetInBits() const {
assert(getTag() == dwarf::DW_TAG_member && isBitField());
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
return C->getValue();
return nullptr;
}
Constant *getConstant() const {
assert(getTag() == dwarf::DW_TAG_member && isStaticMember());
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))

View File

@ -20,6 +20,7 @@
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/IR/Constants.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbol.h"
@ -1500,23 +1501,32 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {
const DIDerivedType *Member = MemberInfo.MemberTypeNode;
TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
StringRef MemberName = Member->getName();
MemberAccess Access =
translateAccessFlags(Ty->getTag(), Member->getFlags());
if (Member->isStaticMember()) {
Fields.writeStaticDataMember(StaticDataMemberRecord(
translateAccessFlags(Ty->getTag(), Member->getFlags()),
MemberBaseType, Member->getName()));
Fields.writeStaticDataMember(
StaticDataMemberRecord(Access, MemberBaseType, MemberName));
MemberCount++;
continue;
}
uint64_t OffsetInBytes = MemberInfo.BaseOffset;
// FIXME: Handle bitfield type memeber.
OffsetInBytes += Member->getOffsetInBits() / 8;
Fields.writeDataMember(
DataMemberRecord(translateAccessFlags(Ty->getTag(), Member->getFlags()),
MemberBaseType, OffsetInBytes, Member->getName()));
// Data member.
uint64_t MemberOffsetInBits = Member->getOffsetInBits();
if (Member->isBitField()) {
uint64_t StartBitOffset = MemberOffsetInBits;
if (const auto *CI =
dyn_cast_or_null<ConstantInt>(Member->getStorageOffsetInBits())) {
MemberOffsetInBits = CI->getZExtValue();
}
StartBitOffset -= MemberOffsetInBits;
MemberBaseType = TypeTable.writeBitField(BitFieldRecord(
MemberBaseType, Member->getSizeInBits(), StartBitOffset));
}
uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
Fields.writeDataMember(DataMemberRecord(Access, MemberBaseType,
MemberOffsetInBytes, MemberName));
MemberCount++;
}

View File

@ -308,6 +308,18 @@ static ConstantAsMetadata *getConstantOrNull(Constant *C) {
return nullptr;
}
DIDerivedType *DIBuilder::createBitFieldMemberType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
uint64_t StorageOffsetInBits, unsigned Flags, DIType *Ty) {
Flags |= DINode::FlagBitField;
return DIDerivedType::get(
VMContext, dwarf::DW_TAG_member, Name, File, LineNumber,
getNonCompileUnitScope(Scope), Ty, SizeInBits, AlignInBits, OffsetInBits,
Flags, ConstantAsMetadata::get(ConstantInt::get(
IntegerType::get(VMContext, 64), StorageOffsetInBits)));
}
DIDerivedType *DIBuilder::createStaticMemberType(DIScope *Scope, StringRef Name,
DIFile *File,
unsigned LineNumber,

View File

@ -0,0 +1,215 @@
; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
; C++ source to regenerate:
; $ cat t.cpp
; #pragma pack(1)
; struct S0 {
; char : 8;
; short : 8;
; short x : 8;
; } s0;
;
; #pragma pack(1)
; struct S1 {
; char x1[2];
; char x2;
; int y : 23;
; int z : 23;
; int w : 2;
; struct { char c; short s; } v;
; short u : 3;
; } s1;
;
; #pragma pack(1)
; struct S2 {
; char : 0;
; int y : 1;
; } s2;
; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
; CHECK: CodeViewTypes [
; CHECK: BitField ([[S0_x:.*]]) {
; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
; CHECK: Type: short (0x11)
; CHECK: BitSize: 8
; CHECK: BitOffset: 8
; CHECK: }
; CHECK: FieldList ([[S0_fl:.*]]) {
; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK: DataMember {
; CHECK: Type: [[S0_x:.*]]
; CHECK: FieldOffset: 0x1
; CHECK: Name: x
; CHECK: }
; CHECK: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 1
; CHECK: Properties [ (0x0)
; CHECK: ]
; CHECK: FieldList: <field list> ([[S0_fl]])
; CHECK: SizeOf: 3
; CHECK: Name: S0
; CHECK: }
; CHECK: BitField ([[S1_y_z:.*]]) {
; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
; CHECK: Type: int (0x74)
; CHECK: BitSize: 23
; CHECK: BitOffset: 0
; CHECK: }
; CHECK: BitField ([[S1_w:.*]]) {
; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
; CHECK: Type: int (0x74)
; CHECK: BitSize: 2
; CHECK: BitOffset: 23
; CHECK: }
; CHECK: BitField ([[S1_u:.*]]) {
; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
; CHECK: Type: short (0x11)
; CHECK: BitSize: 3
; CHECK: BitOffset: 0
; CHECK: }
; CHECK: FieldList ([[S1_fl:.*]]) {
; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK: DataMember {
; CHECK: FieldOffset: 0x0
; CHECK: Name: x1
; CHECK: }
; CHECK: DataMember {
; CHECK: Type: char (0x70)
; CHECK: FieldOffset: 0x2
; CHECK: Name: x2
; CHECK: }
; CHECK: DataMember {
; CHECK: Type: [[S1_y_z]]
; CHECK: FieldOffset: 0x3
; CHECK: Name: y
; CHECK: }
; CHECK: DataMember {
; CHECK: Type: [[S1_y_z]]
; CHECK: FieldOffset: 0x7
; CHECK: Name: z
; CHECK: }
; CHECK: DataMember {
; CHECK: Type: [[S1_w]]
; CHECK: FieldOffset: 0x7
; CHECK: Name: w
; CHECK: }
; CHECK: DataMember {
; CHECK: FieldOffset: 0xB
; CHECK: Name: v
; CHECK: }
; CHECK: DataMember {
; CHECK: Type: [[S1_u]]
; CHECK: FieldOffset: 0xE
; CHECK: Name: u
; CHECK: }
; CHECK: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 7
; CHECK: Properties [ (0x0)
; CHECK: ]
; CHECK: FieldList: <field list> ([[S1_fl]])
; CHECK: SizeOf: 16
; CHECK: Name: S1
; CHECK: }
; CHECK: FieldList ([[anon_fl:.*]]) {
; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK: DataMember {
; CHECK: Type: char (0x70)
; CHECK: FieldOffset: 0x0
; CHECK: Name: c
; CHECK: }
; CHECK: DataMember {
; CHECK: Type: short (0x11)
; CHECK: FieldOffset: 0x1
; CHECK: Name: s
; CHECK: }
; CHECK: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 2
; CHECK: Properties [ (0x0)
; CHECK: ]
; CHECK: FieldList: <field list> ([[anon_fl]])
; CHECK: SizeOf: 3
; CHECK: Name: S1::
; CHECK: }
; CHECK: BitField ([[S2_y:.*]]) {
; CHECK: TypeLeafKind: LF_BITFIELD (0x1205)
; CHECK: Type: int (0x74)
; CHECK: BitSize: 1
; CHECK: BitOffset: 0
; CHECK: }
; CHECK: FieldList ([[S2_fl:.*]]) {
; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK: DataMember {
; CHECK: Type: [[S2_y]]
; CHECK: FieldOffset: 0x0
; CHECK: Name: y
; CHECK: }
; CHECK: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 1
; CHECK: Properties [ (0x0)
; CHECK: ]
; CHECK: FieldList: <field list> ([[S2_fl]])
; CHECK: SizeOf: 4
; CHECK: Name: S2
; CHECK: }
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "x86_64-pc-windows-msvc18.0.0"
%struct.S0 = type <{ i8, i16 }>
%struct.S1 = type <{ [2 x i8], i8, i32, i32, %struct.anon, i16 }>
%struct.anon = type <{ i8, i16 }>
%struct.S2 = type { i32 }
@s0 = common global %struct.S0 zeroinitializer, align 1
@s1 = common global %struct.S1 zeroinitializer, align 1
@s2 = common global %struct.S2 zeroinitializer, align 1
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!33, !34, !35}
!llvm.ident = !{!36}
!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)
!1 = !DIFile(filename: "-", directory: "/usr/local/google/home/majnemer/llvm/src")
!2 = !{}
!3 = !{!4, !10, !29}
!4 = distinct !DIGlobalVariable(name: "s0", scope: !0, file: !5, line: 7, type: !6, isLocal: false, isDefinition: true, variable: %struct.S0* @s0)
!5 = !DIFile(filename: "<stdin>", directory: "/usr/local/google/home/majnemer/llvm/src")
!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S0", file: !5, line: 3, size: 24, align: 8, elements: !7)
!7 = !{!8}
!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)
!9 = !DIBasicType(name: "short", size: 16, align: 16, encoding: DW_ATE_signed)
!10 = distinct !DIGlobalVariable(name: "s1", scope: !0, file: !5, line: 18, type: !11, isLocal: false, isDefinition: true, variable: %struct.S1* @s1)
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S1", file: !5, line: 10, size: 128, align: 8, elements: !12)
!12 = !{!13, !18, !19, !21, !22, !23, !28}
!13 = !DIDerivedType(tag: DW_TAG_member, name: "x1", scope: !11, file: !5, line: 11, baseType: !14, size: 16, align: 8)
!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 16, align: 8, elements: !16)
!15 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
!16 = !{!17}
!17 = !DISubrange(count: 2)
!18 = !DIDerivedType(tag: DW_TAG_member, name: "x2", scope: !11, file: !5, line: 12, baseType: !15, size: 8, align: 8, offset: 16)
!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)
!20 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!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)
!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)
!23 = !DIDerivedType(tag: DW_TAG_member, name: "v", scope: !11, file: !5, line: 16, baseType: !24, size: 24, align: 8, offset: 88)
!24 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !11, file: !5, line: 16, size: 24, align: 8, elements: !25)
!25 = !{!26, !27}
!26 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !24, file: !5, line: 16, baseType: !15, size: 8, align: 8)
!27 = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: !24, file: !5, line: 16, baseType: !9, size: 16, align: 16, offset: 8)
!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)
!29 = distinct !DIGlobalVariable(name: "s2", scope: !0, file: !5, line: 24, type: !30, isLocal: false, isDefinition: true, variable: %struct.S2* @s2)
!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S2", file: !5, line: 21, size: 32, align: 8, elements: !31)
!31 = !{!32}
!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)
!33 = !{i32 2, !"CodeView", i32 1}
!34 = !{i32 2, !"Debug Info Version", i32 3}
!35 = !{i32 1, !"PIC Level", i32 2}
!36 = !{!"clang version 3.9.0 (trunk 273812) (llvm/trunk 273843)"}