zequanwu updated this revision to Diff 529757.
zequanwu added a comment.
Herald added subscribers: ChuanqiXu, mgrang.

Extend the output and reading of -fdump-record-layouts-simple.
Add a test case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152472/new/

https://reviews.llvm.org/D152472

Files:
  clang/include/clang/Frontend/LayoutOverrideSource.h
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/Frontend/LayoutOverrideSource.cpp
  clang/test/CodeGenCXX/Inputs/override-layout-ms.layout
  clang/test/CodeGenCXX/override-layout-ms.cpp

Index: clang/test/CodeGenCXX/override-layout-ms.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/override-layout-ms.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -w -triple=x86_64-pc-win32 -fms-compatibility -fdump-record-layouts -foverride-record-layout=%S/Inputs/override-layout-ms.layout %s | FileCheck  %s
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:          0 | struct E1 (empty)
+// CHECK:            | [sizeof=1, align=1,
+// CHECK:            |  nvsize=0, nvalign=1]
+// CHECK: *** Dumping AST Record Layout
+// CHECK:          0 | struct Mid
+// CHECK:          0 |   void * p
+// CHECK:            | [sizeof=8, align=8,
+// CHECK:            |  nvsize=8, nvalign=8]
+// CHECK: *** Dumping AST Record Layout
+// CHECK:          0 | struct E2 (empty)
+// CHECK:            | [sizeof=1, align=1,
+// CHECK:            |  nvsize=0, nvalign=1]
+// CHECK: *** Dumping AST Record Layout
+// CHECK:          0 | struct Combine
+// CHECK:          0 |   struct E1 (base) (empty)
+// CHECK:          0 |   struct Mid (base)
+// CHECK:          0 |     void * p
+// CHECK:          0 |   struct E2 (base) (empty)
+// CHECK:            | [sizeof=8, align=8,
+// CHECK:            |  nvsize=8, nvalign=8]
+
+
+struct E1 {};
+struct E2 {};
+struct Mid {void *p; };
+struct __declspec(empty_bases) Combine : E1, Mid, E2 {};
+Combine g;
+
Index: clang/test/CodeGenCXX/Inputs/override-layout-ms.layout
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/Inputs/override-layout-ms.layout
@@ -0,0 +1,39 @@
+*** Dumping AST Record Layout
+Type: struct E1
+
+Layout: <ASTRecordLayout
+  Size:8
+  Alignment:8
+  BaseOffsets: []>
+  VBaseOffsets: []>
+  FieldOffsets: []>
+
+*** Dumping AST Record Layout
+Type: struct Mid
+
+Layout: <ASTRecordLayout
+  Size:64
+  Alignment:64
+  BaseOffsets: []>
+  VBaseOffsets: []>
+  FieldOffsets: [0]>
+
+*** Dumping AST Record Layout
+Type: struct E2
+
+Layout: <ASTRecordLayout
+  Size:8
+  Alignment:8
+  BaseOffsets: []>
+  VBaseOffsets: []>
+  FieldOffsets: []>
+
+*** Dumping AST Record Layout
+Type: struct Combine
+
+Layout: <ASTRecordLayout
+  Size:64
+  Alignment:64
+  BaseOffsets: [0, 0, 0]>
+  VBaseOffsets: []>
+  FieldOffsets: []>
Index: clang/lib/Frontend/LayoutOverrideSource.cpp
===================================================================
--- clang/lib/Frontend/LayoutOverrideSource.cpp
+++ clang/lib/Frontend/LayoutOverrideSource.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 #include "clang/Frontend/LayoutOverrideSource.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/Basic/CharInfo.h"
 #include "llvm/Support/raw_ostream.h"
 #include <fstream>
@@ -26,6 +27,20 @@
   return S.substr(0, Offset).str();
 }
 
+/// Parse an unsigned integer and move S to the next non-digit character.
+static bool parseUnsigned(StringRef &S, unsigned long long &ULL) {
+  if (S.empty() || !isDigit(S[0]))
+    return false;
+  unsigned Idx = 1;
+  while (Idx < S.size() && isDigit(S[Idx]))
+    ++Idx;
+  unsigned long long Offset = 0;
+  (void)S.substr(0, Idx).getAsInteger(10, Offset);
+  S = S.substr(Idx);
+  ULL = Offset;
+  return true;
+}
+
 LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
   std::ifstream Input(Filename.str().c_str());
   if (!Input.is_open())
@@ -80,8 +95,8 @@
       LineStr = LineStr.substr(Pos + strlen(" Size:"));
 
       unsigned long long Size = 0;
-      (void)LineStr.getAsInteger(10, Size);
-      CurrentLayout.Size = Size;
+      if (parseUnsigned(LineStr, Size))
+        CurrentLayout.Size = Size;
       continue;
     }
 
@@ -92,12 +107,13 @@
       LineStr = LineStr.substr(Pos + strlen("Alignment:"));
 
       unsigned long long Alignment = 0;
-      (void)LineStr.getAsInteger(10, Alignment);
-      CurrentLayout.Align = Alignment;
+      if (parseUnsigned(LineStr, Alignment))
+        CurrentLayout.Align = Alignment;
       continue;
     }
 
-    // Check for the size/alignment of the type.
+    // Check for the size/alignment of the type. The number follows "size=" or
+    // "align=" indicates number of bytes.
     Pos = LineStr.find("sizeof=");
     if (Pos != StringRef::npos) {
       /* Skip past the sizeof= prefix. */
@@ -105,8 +121,8 @@
 
       // Parse size.
       unsigned long long Size = 0;
-      (void)LineStr.getAsInteger(10, Size);
-      CurrentLayout.Size = Size;
+      if (parseUnsigned(LineStr, Size))
+        CurrentLayout.Size = Size * 8;
 
       Pos = LineStr.find("align=");
       if (Pos != StringRef::npos) {
@@ -115,8 +131,8 @@
 
         // Parse alignment.
         unsigned long long Alignment = 0;
-        (void)LineStr.getAsInteger(10, Alignment);
-        CurrentLayout.Align = Alignment;
+        if (parseUnsigned(LineStr, Alignment))
+          CurrentLayout.Align = Alignment * 8;
       }
 
       continue;
@@ -124,25 +140,50 @@
 
     // Check for the field offsets of the type.
     Pos = LineStr.find("FieldOffsets: [");
-    if (Pos == StringRef::npos)
-      continue;
+    if (Pos != StringRef::npos) {
+      LineStr = LineStr.substr(Pos + strlen("FieldOffsets: ["));
+      while (!LineStr.empty() && isDigit(LineStr[0])) {
+        unsigned long long Offset = 0;
+        if (parseUnsigned(LineStr, Offset))
+          CurrentLayout.FieldOffsets.push_back(Offset);
+
+        // Skip over this offset, the following comma, and any spaces.
+        LineStr = LineStr.substr(1);
+        while (!LineStr.empty() && isWhitespace(LineStr[0]))
+          LineStr = LineStr.substr(1);
+      }
+    }
 
-    LineStr = LineStr.substr(Pos + strlen("FieldOffsets: ["));
-    while (!LineStr.empty() && isDigit(LineStr[0])) {
-      // Parse this offset.
-      unsigned Idx = 1;
-      while (Idx < LineStr.size() && isDigit(LineStr[Idx]))
-        ++Idx;
+    // Check for the base offsets.
+    Pos = LineStr.find("BaseOffsets: [");
+    if (Pos != StringRef::npos) {
+      LineStr = LineStr.substr(Pos + strlen("BaseOffsets: ["));
+      while (!LineStr.empty() && isDigit(LineStr[0])) {
+        unsigned long long Offset = 0;
+        if (parseUnsigned(LineStr, Offset))
+          CurrentLayout.BaseOffsets.push_back(CharUnits::fromQuantity(Offset));
 
-      unsigned long long Offset = 0;
-      (void)LineStr.substr(0, Idx).getAsInteger(10, Offset);
+        // Skip over this offset, the following comma, and any spaces.
+        LineStr = LineStr.substr(1);
+        while (!LineStr.empty() && isWhitespace(LineStr[0]))
+          LineStr = LineStr.substr(1);
+      }
+    }
 
-      CurrentLayout.FieldOffsets.push_back(Offset);
+    // Check for the virtual base offsets.
+    Pos = LineStr.find("VBaseOffsets: [");
+    if (Pos != StringRef::npos) {
+      LineStr = LineStr.substr(Pos + strlen("VBaseOffsets: ["));
+      while (!LineStr.empty() && isDigit(LineStr[0])) {
+        unsigned long long Offset = 0;
+        if (parseUnsigned(LineStr, Offset))
+          CurrentLayout.VBaseOffsets.push_back(CharUnits::fromQuantity(Offset));
 
-      // Skip over this offset, the following comma, and any spaces.
-      LineStr = LineStr.substr(Idx + 1);
-      while (!LineStr.empty() && isWhitespace(LineStr[0]))
+        // Skip over this offset, the following comma, and any spaces.
         LineStr = LineStr.substr(1);
+        while (!LineStr.empty() && isWhitespace(LineStr[0]))
+          LineStr = LineStr.substr(1);
+      }
     }
   }
 
@@ -182,6 +223,24 @@
   if (NumFields != Known->second.FieldOffsets.size())
     return false;
 
+  // Provide base offsets.
+  if (const auto *RD = dyn_cast<CXXRecordDecl>(Record)) {
+    unsigned NumNB = 0;
+    unsigned NumVB = 0;
+    for (const auto &I : RD->bases()) {
+      const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
+      if (I.isVirtual()) {
+        if (NumVB >= Known->second.VBaseOffsets.size())
+          continue;
+        VirtualBaseOffsets[Base] = Known->second.VBaseOffsets[NumVB++];
+      } else {
+        if (NumNB >= Known->second.BaseOffsets.size())
+          continue;
+        BaseOffsets[Base] = Known->second.BaseOffsets[NumNB++];
+      }
+    }
+  }
+
   Size = Known->second.Size;
   Alignment = Known->second.Align;
   return true;
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2926,8 +2926,7 @@
   bool FoundBase = false;
   if (UseExternalLayout) {
     FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
-    if (FoundBase) {
-      assert(BaseOffset >= Size && "base offset already allocated");
+    if (BaseOffset > Size) {
       Size = BaseOffset;
     }
   }
@@ -3723,6 +3722,32 @@
   if (Target->defaultsToAIXPowerAlignment())
     OS << "  PreferredAlignment:" << toBits(Info.getPreferredAlignment())
        << "\n";
+  if (Info.CXXInfo) {
+    SmallVector<uint64_t, 4> Bases;
+    for (auto Base: Info.CXXInfo->BaseOffsets) {
+      Bases.push_back(Base.second.getQuantity());
+    }
+    llvm::sort(Bases);
+    OS << "  BaseOffsets: [";
+    for (unsigned i = 0, e = Bases.size(); i != e; ++i) {
+      if (i)
+        OS << ", ";
+      OS << Bases[i];
+    }
+    OS << "]>\n";
+    SmallVector<uint64_t, 4> VBases;
+    for (auto VBase: Info.CXXInfo->VBaseOffsets) {
+      VBases.push_back(VBase.second.VBaseOffset.getQuantity());
+    }
+    llvm::sort(VBases);
+    OS << "  VBaseOffsets: [";
+    for (unsigned i = 0, e = VBases.size(); i != e; ++i) {
+      if (i)
+        OS << ", ";
+      OS << VBases[i];
+    }
+    OS << "]>\n";
+  }
   OS << "  FieldOffsets: [";
   for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
     if (i)
Index: clang/include/clang/Frontend/LayoutOverrideSource.h
===================================================================
--- clang/include/clang/Frontend/LayoutOverrideSource.h
+++ clang/include/clang/Frontend/LayoutOverrideSource.h
@@ -30,6 +30,12 @@
       /// The alignment of the record.
       uint64_t Align;
 
+      /// The offsets of non-virtual base classes in the record.
+      SmallVector<CharUnits, 8> BaseOffsets;
+
+      /// The offsets of virtual base classes in the record.
+      SmallVector<CharUnits, 8> VBaseOffsets;
+
       /// The offsets of the fields, in source order.
       SmallVector<uint64_t, 8> FieldOffsets;
     };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to