Index: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1394,6 +1394,35 @@ // FIXME: Make an LF_UDT_SRC_LINE record. } +/// If this type is derived from a base type then return base type size. +static uint64_t getBaseTypeSize(const DIDerivedType *Ty) { + unsigned Tag = Ty->getTag(); + + if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && + Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_restrict_type) + return Ty->getSizeInBits(); + + DIType *BaseType = Ty->getBaseType().resolve(); + + // If this type is not derived from any type or the type is a declaration then + // take conservative approach. + if (!BaseType || BaseType->isForwardDecl()) + return Ty->getSizeInBits(); + + // If this is a derived type, go ahead and get the base type, unless it's a + // reference then it's just the size of the field. Pointer types have no need + // of this since they're a different type of qualification on the type. + if (BaseType->getTag() == dwarf::DW_TAG_reference_type || + BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type) + return Ty->getSizeInBits(); + + if (DIDerivedType *DT = dyn_cast(BaseType)) + return getBaseTypeSize(DT); + + return BaseType->getSizeInBits(); +} + std::tuple CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { // Manually count members. MSVC appears to count everything that generates a @@ -1417,10 +1446,23 @@ continue; } + uint64_t Size = Member->getSizeInBits(); + uint64_t FieldSize = getBaseTypeSize(Member); uint64_t OffsetInBytes = MemberInfo.BaseOffset; - // FIXME: Handle bitfield type memeber. - OffsetInBytes += Member->getOffsetInBits() / 8; + if (Size != FieldSize) { + uint64_t Offset = Member->getOffsetInBits(); + uint64_t AlignMask = ~(Member->getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + uint64_t FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + + MemberBaseType = TypeTable.writeBitField( + BitFieldRecord(MemberBaseType, (uint8_t)Size, (uint8_t)Offset)); + OffsetInBytes += FieldOffset / 8; + } else + // This is not a bitfield. + OffsetInBytes += Member->getOffsetInBits() / 8; Fields.writeDataMember( DataMemberRecord(translateAccessFlags(Ty->getTag(), Member->getFlags()), Index: test/DebugInfo/COFF/types-bitfield.ll =================================================================== --- test/DebugInfo/COFF/types-bitfield.ll +++ test/DebugInfo/COFF/types-bitfield.ll @@ -0,0 +1,125 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; C++ source to regenerate: +; $ cat t.cpp +; +; struct A { +; int x : 1; +; int y : 4; +; int z : 3; +; char w : 7; +; }; +; +; A a; + + +; CHECK: CodeViewTypes [ +; CHECK: Section: .debug$T (5) +; CHECK: Magic: 0x4 +; CHECK: Struct (0x1000) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 0 +; CHECK: Properties [ (0x280) +; CHECK: ForwardReference (0x80) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: 0x0 +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 0 +; CHECK: Name: A +; CHECK: LinkageName: .?AUA@@ +; CHECK: } +; CHECK: BitField (0x1001) { +; CHECK: TypeLeafKind: LF_BITFIELD (0x1205) +; CHECK: Type: int (0x74) +; CHECK: BitSize: 1 +; CHECK: BitOffset: 0 +; CHECK: } +; CHECK: BitField (0x1002) { +; CHECK: TypeLeafKind: LF_BITFIELD (0x1205) +; CHECK: Type: int (0x74) +; CHECK: BitSize: 4 +; CHECK: BitOffset: 1 +; CHECK: } +; CHECK: BitField (0x1003) { +; CHECK: TypeLeafKind: LF_BITFIELD (0x1205) +; CHECK: Type: int (0x74) +; CHECK: BitSize: 3 +; CHECK: BitOffset: 5 +; CHECK: } +; CHECK: BitField (0x1004) { +; CHECK: TypeLeafKind: LF_BITFIELD (0x1205) +; CHECK: Type: char (0x70) +; CHECK: BitSize: 7 +; CHECK: BitOffset: 0 +; CHECK: } +; CHECK: UnknownLeaf (0x1005) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: 0x1001 +; CHECK: FieldOffset: 0x0 +; CHECK: Name: x +; CHECK: } +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: 0x1002 +; CHECK: FieldOffset: 0x0 +; CHECK: Name: y +; CHECK: } +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: 0x1003 +; CHECK: FieldOffset: 0x0 +; CHECK: Name: z +; CHECK: } +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: 0x1004 +; CHECK: FieldOffset: 0x4 +; CHECK: Name: w +; CHECK: } +; CHECK: } +; CHECK: Struct (0x1006) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 4 +; CHECK: Properties [ (0x200) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: w (0x1005) +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 8 +; CHECK: Name: A +; CHECK: LinkageName: .?AUA@@ +; CHECK: } +; CHECK: ] + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc" + +%struct.A = type { i32, i8 } + +@"\01?a@@3UA@@A" = global %struct.A zeroinitializer, align 4 + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!13, !14} +!llvm.ident = !{!15} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 273084)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3) +!1 = !DIFile(filename: "t.cpp", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = distinct !DIGlobalVariable(name: "a", linkageName: "\01?a@@3UA@@A", scope: !0, file: !1, line: 8, type: !5, isLocal: false, isDefinition: true, variable: %struct.A* @"\01?a@@3UA@@A") +!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 1, size: 64, align: 32, elements: !6, identifier: ".?AUA@@") +!6 = !{!7, !9, !10, !11} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !5, file: !1, line: 2, baseType: !8, size: 1, align: 32) +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!9 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !5, file: !1, line: 3, baseType: !8, size: 4, align: 32, offset: 1) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !5, file: !1, line: 4, baseType: !8, size: 3, align: 32, offset: 5) +!11 = !DIDerivedType(tag: DW_TAG_member, name: "w", scope: !5, file: !1, line: 5, baseType: !12, size: 7, align: 8, offset: 32) +!12 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +!13 = !{i32 2, !"CodeView", i32 1} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{!"clang version 3.9.0 (trunk 273084)"}