[llvm] [ThinLTO] Fix assembly dumping of vtable type ids (PR #73997)

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 30 14:25:34 PST 2023


https://github.com/teresajohnson created https://github.com/llvm/llvm-project/pull/73997

With RTTI, a C++ class type info will get two entries in the summary
index: a gv and a typeidCompatibleVTable, both sharing the same GUID.
Ensure we use different namespaces to generate the entry slot numbers
for these two different summary entries.


>From 4b8acafd1e06231821c7a724ca8f6566292fc945 Mon Sep 17 00:00:00 2001
From: Teresa Johnson <tejohnson at google.com>
Date: Thu, 30 Nov 2023 13:31:04 -0800
Subject: [PATCH] [ThinLTO] Fix assembly dumping of vtable type ids

With RTTI, a C++ class type info will get two entries in the summary
index: a gv and a typeidCompatibleVTable, both sharing the same GUID.
Ensure we use different namespaces to generate the entry slot numbers
for these two different summary entries.
---
 llvm/lib/IR/AsmWriter.cpp                     | 31 +++++++++++++++---
 .../test/Assembler/thinlto-vtable-summary2.ll | 32 +++++++++++++++++++
 2 files changed, 59 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Assembler/thinlto-vtable-summary2.ll

diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 601b636f306adeb..fabc79adbd33ddc 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -736,6 +736,11 @@ class SlotTracker : public AbstractSlotTrackerStorage {
   StringMap<unsigned> TypeIdMap;
   unsigned TypeIdNext = 0;
 
+  /// TypeIdCompatibleVtableMap - The slot map for type compatible vtable ids
+  /// used in the summary index.
+  StringMap<unsigned> TypeIdCompatibleVtableMap;
+  unsigned TypeIdCompatibleVtableNext = 0;
+
 public:
   /// Construct from a module.
   ///
@@ -779,6 +784,7 @@ class SlotTracker : public AbstractSlotTrackerStorage {
   int getModulePathSlot(StringRef Path);
   int getGUIDSlot(GlobalValue::GUID GUID);
   int getTypeIdSlot(StringRef Id);
+  int getTypeIdCompatibleVtableSlot(StringRef Id);
 
   /// If you'd like to deal with a function instead of just a module, use
   /// this method to get its data into the SlotTracker.
@@ -834,6 +840,7 @@ class SlotTracker : public AbstractSlotTrackerStorage {
   inline void CreateModulePathSlot(StringRef Path);
   void CreateGUIDSlot(GlobalValue::GUID GUID);
   void CreateTypeIdSlot(StringRef Id);
+  void CreateTypeIdCompatibleVtableSlot(StringRef Id);
 
   /// Add all of the module level global variables (and their initializers)
   /// and function declarations, but not the contents of those functions.
@@ -1095,11 +1102,13 @@ int SlotTracker::processIndex() {
   for (auto &GlobalList : *TheIndex)
     CreateGUIDSlot(GlobalList.first);
 
+  // Start numbering the TypeIdCompatibleVtables after the GUIDs.
+  TypeIdCompatibleVtableNext = GUIDNext;
   for (auto &TId : TheIndex->typeIdCompatibleVtableMap())
-    CreateGUIDSlot(GlobalValue::getGUID(TId.first));
+    CreateTypeIdCompatibleVtableSlot(TId.first);
 
-  // Start numbering the TypeIds after the GUIDs.
-  TypeIdNext = GUIDNext;
+  // Start numbering the TypeIds after the TypeIdCompatibleVtables.
+  TypeIdNext = TypeIdCompatibleVtableNext;
   for (const auto &TID : TheIndex->typeIds())
     CreateTypeIdSlot(TID.second.first);
 
@@ -1232,6 +1241,15 @@ int SlotTracker::getTypeIdSlot(StringRef Id) {
   return I == TypeIdMap.end() ? -1 : (int)I->second;
 }
 
+int SlotTracker::getTypeIdCompatibleVtableSlot(StringRef Id) {
+  // Check for uninitialized state and do lazy initialization.
+  initializeIndexIfNeeded();
+
+  // Find the TypeIdCompatibleVtable string in the map
+  auto I = TypeIdCompatibleVtableMap.find(Id);
+  return I == TypeIdCompatibleVtableMap.end() ? -1 : (int)I->second;
+}
+
 /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
 void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
   assert(V && "Can't insert a null Value into SlotTracker!");
@@ -1307,6 +1325,11 @@ void SlotTracker::CreateTypeIdSlot(StringRef Id) {
   TypeIdMap[Id] = TypeIdNext++;
 }
 
+/// Create a new slot for the specified Id
+void SlotTracker::CreateTypeIdCompatibleVtableSlot(StringRef Id) {
+  TypeIdCompatibleVtableMap[Id] = TypeIdCompatibleVtableNext++;
+}
+
 namespace {
 /// Common instances used by most of the printer functions.
 struct AsmWriterContext {
@@ -2955,7 +2978,7 @@ void AssemblyWriter::printModuleSummaryIndex() {
   // Print the TypeIdCompatibleVtableMap entries.
   for (auto &TId : TheIndex->typeIdCompatibleVtableMap()) {
     auto GUID = GlobalValue::getGUID(TId.first);
-    Out << "^" << Machine.getGUIDSlot(GUID)
+    Out << "^" << Machine.getTypeIdCompatibleVtableSlot(TId.first)
         << " = typeidCompatibleVTable: (name: \"" << TId.first << "\"";
     printTypeIdCompatibleVtableSummary(TId.second);
     Out << ") ; guid = " << GUID << "\n";
diff --git a/llvm/test/Assembler/thinlto-vtable-summary2.ll b/llvm/test/Assembler/thinlto-vtable-summary2.ll
new file mode 100644
index 000000000000000..862b7abfcd3c348
--- /dev/null
+++ b/llvm/test/Assembler/thinlto-vtable-summary2.ll
@@ -0,0 +1,32 @@
+;; Test to ensure that the summary is correctly printed when there is both a
+;; global variable summary and a vtable typeid summary entry for the same
+;; symbol.
+
+; RUN: opt %s -S -module-summary | FileCheck %s
+;; Make sure it round trips correctly.
+; RUN: opt %s -S -module-summary -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s
+
+;; These summary entries should get numbered differently.
+; CHECK: ^2 = gv: (name: "_ZTS1A"
+; CHECK: ^6 = typeidCompatibleVTable: (name: "_ZTS1A"
+
+; ModuleID = 'thinlto-vtable-summary2.cc'
+source_filename = "thinlto-vtable-summary2.cc"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at _ZTV1A = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A3fooEv] }, align 8, !type !0, !type !1
+ at _ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
+ at _ZTS1A = dso_local constant [3 x i8] c"1A\00", align 1
+ at _ZTI1A = dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, align 8
+
+define dso_local noundef i32 @_ZN1A3fooEv(ptr noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr align 2 {
+entry:
+  %this.addr = alloca ptr, align 8
+  store ptr %this, ptr %this.addr, align 8
+  %this1 = load ptr, ptr %this.addr, align 8
+  ret i32 1
+}
+
+!0 = !{i64 16, !"_ZTS1A"}
+!1 = !{i64 16, !"_ZTSM1AFivE.virtual"}



More information about the llvm-commits mailing list