r338353 - Improve support of PDB as an external layout source

2018-07-31 Thread Aleksandr Urakov via cfe-commits
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-namel

r345012 - [AST] Do not align virtual bases in `MicrosoftRecordLayoutBuilder` when

2018-10-23 Thread Aleksandr Urakov via cfe-commits
Author: aleksandr.urakov
Date: Tue Oct 23 01:23:22 2018
New Revision: 345012

URL: http://llvm.org/viewvc/llvm-project?rev=345012&view=rev
Log:
[AST] Do not align virtual bases in `MicrosoftRecordLayoutBuilder` when
  an external layout is used

Summary:
The patch removes alignment of virtual bases when an external layout is used.
We have two cases:
- the external layout source has an information about virtual bases offsets,
  so we just use them;
- the external source has no information about virtual bases offsets. In this
  case we can't predict where the base will be located. If we will align it but
  there will be something like `#pragma pack(push, 1)` really, then likely our
  layout will not fit into the real structure size, and then some asserts will
  hit. The asserts look reasonable, so I don't think that we need to remove
  them. May be it would be better instead don't align fields / bases etc.
  (so treat it always as `#pragma pack(push, 1)`) when an external layout source
  is used but no info about a field location is presented.

This one is related to D49871

Reviewers: rnk, rsmith, zturner, mstorsjo, majnemer

Reviewed By: rnk

Subscribers: cfe-commits

Tags: #clang

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

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

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=345012&r1=345011&r2=345012&view=diff
==
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Tue Oct 23 01:23:22 2018
@@ -2829,15 +2829,14 @@ void MicrosoftRecordLayoutBuilder::layou
 CharUnits BaseOffset;
 
 // Respect the external AST source base offset, if present.
-bool FoundBase = false;
 if (UseExternalLayout) {
-  FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
-  if (FoundBase)
-assert(BaseOffset >= Size && "base offset already allocated");
-}
-if (!FoundBase)
+  if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
+BaseOffset = Size;
+} else
   BaseOffset = Size.alignTo(Info.Alignment);
 
+assert(BaseOffset >= Size && "base offset already allocated");
+
 VBases.insert(std::make_pair(BaseDecl,
 ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
 Size = BaseOffset + BaseLayout.getNonVirtualSize();

Modified: 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=345012&r1=345011&r2=345012&view=diff
==
--- cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout 
(original)
+++ cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout Tue Oct 
23 01:23:22 2018
@@ -3,16 +3,26 @@
 Type: class B<0>
 
 Layout: 
 
 *** Dumping AST Record Layout
 Type: class B<1>
 
 Layout: 
 
 *** Dumping AST Record Layout
 Type: class C
 
 Layout: 
+
+*** Dumping AST Record Layout
+Type: class D
+
+Layout: 

Modified: 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=345012&r1=345011&r2=345012&view=diff
==
--- cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp Tue Oct 23 
01:23:22 2018
@@ -1,26 +1,40 @@
-// RUN: %clang_cc1 -w -fdump-record-layouts-simple 
-foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | 
FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -w -fdump-record-layouts-simple 
-foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | 
FileCheck %s
+
+//#pragma pack(push, 1)
 
 // CHECK: Type: class B<0>
+// CHECK:   Size:40
 // CHECK:   FieldOffsets: [0, 32]
 
 // CHECK: Type: class B<1>
+// CHECK:   Size:40
 // CHECK:   FieldOffsets: [0, 32]
 
-//#pragma pack(push, 1)
 template
 class B {
   int _b1;
   char _b2;
 };
-//#pragma pack(pop)
 
 // CHECK: Type: class C
+// CHECK:   Size:88
 // CHECK:   FieldOffsets: [80]
 
 class C : B<0>, B<1> {
   char _c;
 };
 
+// CHECK: Type: class D
+// CHECK:   Size:120
+// CHECK:   FieldOffsets: [32]
+
+class D : virtual B<0>, virtual B<1> {
+  char _d;
+};
+
+//#pragma pack(pop)
+
 void use_structs() {
   C cs[sizeof(C)];
+  D ds[sizeof(D)];
 }


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r356047 - [AST] Improve support of external layouts in `MicrosoftRecordLayoutBuilder`

2019-03-13 Thread Aleksandr Urakov via cfe-commits
Author: aleksandr.urakov
Date: Wed Mar 13 06:38:12 2019
New Revision: 356047

URL: http://llvm.org/viewvc/llvm-project?rev=356047&view=rev
Log:
[AST] Improve support of external layouts in `MicrosoftRecordLayoutBuilder`

Summary:
This patch fixes several small problems with external layouts support in
`MicrosoftRecordLayoutBuilder`:
- aligns properly the size of a struct that ends with a bit field. It was
  aligned on byte before, not on the size of the field, so the struct size was
  smaller than it should be;
- adjusts the struct size when injecting a vbptr in the case when there were no
  bases or fields allocated after the vbptr. Similarly, without the adjustment
  the struct was smaller than it should be;
- the same fix as above for the vfptr.
All these fixes affect the non-virtual size of a struct, so they are tested
through non-virtual inheritance.

Reviewers: rnk, zturner, rsmith

Reviewed By: rnk

Subscribers: jdoerfert, cfe-commits

Tags: #clang

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

Added:
cfe/trunk/test/CodeGenCXX/Inputs/override-layout-virtual-base.layout
cfe/trunk/test/CodeGenCXX/override-layout-virtual-base.cpp
Modified:
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/test/CodeGenCXX/Inputs/override-bit-field-layout.layout
cfe/trunk/test/CodeGenCXX/override-bit-field-layout.cpp
cfe/trunk/test/CodeGenCXX/override-layout.cpp

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=356047&r1=356046&r2=356047&view=diff
==
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Wed Mar 13 06:38:12 2019
@@ -2692,7 +2692,8 @@ void MicrosoftRecordLayoutBuilder::layou
 auto FieldBitOffset = External.getExternalFieldOffset(FD);
 placeFieldAtBitOffset(FieldBitOffset);
 auto NewSize = Context.toCharUnitsFromBits(
-llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth()));
+llvm::alignDown(FieldBitOffset, Context.toBits(Info.Alignment)) +
+Context.toBits(Info.Size));
 Size = std::max(Size, NewSize);
 Alignment = std::max(Alignment, Info.Alignment);
   } else if (IsUnion) {
@@ -2741,12 +2742,17 @@ void MicrosoftRecordLayoutBuilder::injec
   CharUnits InjectionSite = VBPtrOffset;
   // But before we do, make sure it's properly aligned.
   VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment);
+  // Determine where the first field should be laid out after the vbptr.
+  CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
   // Shift everything after the vbptr down, unless we're using an external
   // layout.
-  if (UseExternalLayout)
+  if (UseExternalLayout) {
+// It is possible that there were no fields or bases located after vbptr,
+// so the size was not adjusted before.
+if (Size < FieldStart)
+  Size = FieldStart;
 return;
-  // Determine where the first field should be laid out after the vbptr.
-  CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
+  }
   // Make sure that the amount we push the fields back by is a multiple of the
   // alignment.
   CharUnits Offset = (FieldStart - InjectionSite)
@@ -2771,8 +2777,14 @@ void MicrosoftRecordLayoutBuilder::injec
   if (HasVBPtr)
 VBPtrOffset += Offset;
 
-  if (UseExternalLayout)
+  if (UseExternalLayout) {
+// The class may have no bases or fields, but still have a vfptr
+// (e.g. it's an interface class). The size was not correctly set before
+// in this case.
+if (FieldOffsets.empty() && Bases.empty())
+  Size += Offset;
 return;
+  }
 
   Size += Offset;
 

Modified: cfe/trunk/test/CodeGenCXX/Inputs/override-bit-field-layout.layout
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/Inputs/override-bit-field-layout.layout?rev=356047&r1=356046&r2=356047&view=diff
==
--- cfe/trunk/test/CodeGenCXX/Inputs/override-bit-field-layout.layout (original)
+++ cfe/trunk/test/CodeGenCXX/Inputs/override-bit-field-layout.layout Wed Mar 
13 06:38:12 2019
@@ -14,3 +14,11 @@ Layout: 
+
+*** Dumping AST Record Layout
+Type: struct S3
+
+Layout: 

Added: cfe/trunk/test/CodeGenCXX/Inputs/override-layout-virtual-base.layout
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/Inputs/override-layout-virtual-base.layout?rev=356047&view=auto
==
--- cfe/trunk/test/CodeGenCXX/Inputs/override-layout-virtual-base.layout (added)
+++ cfe/trunk/test/CodeGenCXX/Inputs/override-layout-virtual-base.layout Wed 
Mar 13 06:38:12 2019
@@ -0,0 +1,8 @@
+
+*** Dumping AST Record Layout
+Type: struct S2
+
+Layout: 

Modified: cfe/trunk/test/CodeGenCXX/override-bit-field-layout.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/override-b