r338353 - Improve support of PDB as an external layout source

Aleksandr Urakov via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 31 01:27:06 PDT 2018


Author: aleksandr.urakov
Date: Tue Jul 31 01:27:06 2018
New Revision: 338353

URL: http://llvm.org/viewvc/llvm-project?rev=338353&view=rev
Log:
Improve support of PDB as an external layout source

Summary:
This patch improves support of PDB as an external layout source
in the next cases:

- Multiple non-virtual inheritance from packed base classes. When using
  external layout, there's no need to align `NonVirtualSize` of a base class.
  It may cause an overlapping when the next base classes will be layouted
  (but there is a slightly different case in the test because I can't find
  a way to specify a base offset);
- Support of nameless structs and unions. There is no info about nameless child
  structs and unions in Microsoft cl-emitted PDBs. Instead all its fields
  are just treated as outer structure's (union's) fields. This also causes
  a fields overlapping, and makes it possible for unions to have fields located
  at a non-zero offset.

Reviewers: rsmith, zturner, rnk, mstorsjo, majnemer

Reviewed By: rnk

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D49871

Added:
    cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout
    cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout
    cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp
    cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp
Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=338353&r1=338352&r2=338353&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Tue Jul 31 01:27:06 2018
@@ -2452,7 +2452,9 @@ void MicrosoftRecordLayoutBuilder::cxxLa
   auto RoundingAlignment = Alignment;
   if (!MaxFieldAlignment.isZero())
     RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
-  NonVirtualSize = Size = Size.alignTo(RoundingAlignment);
+  if (!UseExternalLayout)
+    Size = Size.alignTo(RoundingAlignment);
+  NonVirtualSize = Size;
   RequiredAlignment = std::max(
       RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
   layoutVirtualBases(RD);
@@ -2653,21 +2655,16 @@ void MicrosoftRecordLayoutBuilder::layou
   LastFieldIsNonZeroWidthBitfield = false;
   ElementInfo Info = getAdjustedElementInfo(FD);
   Alignment = std::max(Alignment, Info.Alignment);
-  if (IsUnion) {
-    placeFieldAtOffset(CharUnits::Zero());
-    Size = std::max(Size, Info.Size);
-  } else {
-    CharUnits FieldOffset;
-    if (UseExternalLayout) {
-      FieldOffset =
-          Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
-      assert(FieldOffset >= Size && "field offset already allocated");
-    } else {
-      FieldOffset = Size.alignTo(Info.Alignment);
-    }
-    placeFieldAtOffset(FieldOffset);
-    Size = FieldOffset + Info.Size;
-  }
+  CharUnits FieldOffset;
+  if (UseExternalLayout)
+    FieldOffset =
+        Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
+  else if (IsUnion)
+    FieldOffset = CharUnits::Zero();
+  else
+    FieldOffset = Size.alignTo(Info.Alignment);
+  placeFieldAtOffset(FieldOffset);
+  Size = std::max(Size, FieldOffset + Info.Size);
 }
 
 void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
@@ -2692,18 +2689,17 @@ void MicrosoftRecordLayoutBuilder::layou
   }
   LastFieldIsNonZeroWidthBitfield = true;
   CurrentBitfieldSize = Info.Size;
-  if (IsUnion) {
-    placeFieldAtOffset(CharUnits::Zero());
-    Size = std::max(Size, Info.Size);
-    // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
-  } else if (UseExternalLayout) {
+  if (UseExternalLayout) {
     auto FieldBitOffset = External.getExternalFieldOffset(FD);
     placeFieldAtBitOffset(FieldBitOffset);
     auto NewSize = Context.toCharUnitsFromBits(
         llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth()));
-    assert(NewSize >= Size && "bit field offset already allocated");
-    Size = NewSize;
+    Size = std::max(Size, NewSize);
     Alignment = std::max(Alignment, Info.Alignment);
+  } else if (IsUnion) {
+    placeFieldAtOffset(CharUnits::Zero());
+    Size = std::max(Size, Info.Size);
+    // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
   } else {
     // Allocate a new block of memory and place the bitfield in it.
     CharUnits FieldOffset = Size.alignTo(Info.Alignment);

Added: cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout?rev=338353&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout (added)
+++ cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout Tue Jul 31 01:27:06 2018
@@ -0,0 +1,16 @@
+
+*** Dumping AST Record Layout
+Type: struct S
+
+Layout: <ASTRecordLayout
+  Size:64
+  Alignment:32
+  FieldOffsets: [0, 32, 32]>
+
+*** Dumping AST Record Layout
+Type: union U
+
+Layout: <ASTRecordLayout
+  Size:96
+  Alignment:32
+  FieldOffsets: [0, 0, 32, 64, 68, 73]>

Added: cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout?rev=338353&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout (added)
+++ cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout Tue Jul 31 01:27:06 2018
@@ -0,0 +1,18 @@
+
+*** Dumping AST Record Layout
+Type: class B<0>
+
+Layout: <ASTRecordLayout
+  FieldOffsets: [0, 32]>
+
+*** Dumping AST Record Layout
+Type: class B<1>
+
+Layout: <ASTRecordLayout
+  FieldOffsets: [0, 32]>
+
+*** Dumping AST Record Layout
+Type: class C
+
+Layout: <ASTRecordLayout
+  FieldOffsets: [80]>

Added: cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp?rev=338353&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp Tue Jul 31 01:27:06 2018
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-nameless-struct-union.layout %s | FileCheck %s
+
+// CHECK: Type: struct S
+// CHECK:   Size:64
+// CHECK:   Alignment:32
+// CHECK:   FieldOffsets: [0, 32, 32]
+struct S {
+  short _s;
+//union {
+    int _su0;
+    char _su1;
+//};
+};
+
+// CHECK: Type: union U
+// CHECK:   Size:96
+// CHECK:   Alignment:32
+// CHECK:   FieldOffsets: [0, 0, 32, 64, 68, 73]
+union U {
+  short _u;
+//struct {
+    char _us0;
+    int _us1;
+    unsigned _us20 : 4;
+    unsigned _us21 : 5;
+    unsigned _us22 : 6;
+//};
+};
+
+void use_structs() {
+  S ss[sizeof(S)];
+  U us[sizeof(U)];
+}

Added: cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp?rev=338353&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp Tue Jul 31 01:27:06 2018
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | FileCheck %s
+
+// CHECK: Type: class B<0>
+// CHECK:   FieldOffsets: [0, 32]
+
+// CHECK: Type: class B<1>
+// CHECK:   FieldOffsets: [0, 32]
+
+//#pragma pack(push, 1)
+template<int I>
+class B {
+  int _b1;
+  char _b2;
+};
+//#pragma pack(pop)
+
+// CHECK: Type: class C
+// CHECK:   FieldOffsets: [80]
+
+class C : B<0>, B<1> {
+  char _c;
+};
+
+void use_structs() {
+  C cs[sizeof(C)];
+}




More information about the cfe-commits mailing list