[llvm] 7669f3c - Recommit "[CodeView] Emit static data members as S_CONSTANTs."

Amy Huang via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 28 16:36:15 PDT 2020


Author: Amy Huang
Date: 2020-10-28T16:35:59-07:00
New Revision: 7669f3c0f69db78cdd3deef066abc99f60fc580d

URL: https://github.com/llvm/llvm-project/commit/7669f3c0f69db78cdd3deef066abc99f60fc580d
DIFF: https://github.com/llvm/llvm-project/commit/7669f3c0f69db78cdd3deef066abc99f60fc580d.diff

LOG: Recommit "[CodeView] Emit static data members as S_CONSTANTs."

We used to only emit static const data members in CodeView as
S_CONSTANTS when they were used; this patch makes it so they are always emitted.

This changes CodeViewDebug.cpp to find the static const members from the
class debug info instead of creating DIGlobalVariables in the IR
whenever a static const data member is used.

Bug: https://bugs.llvm.org/show_bug.cgi?id=47580

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

This reverts commit 504615353f31136dd6bf7a971b6c236fd70582be.

Added: 
    

Modified: 
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/test/CodeGenCXX/debug-info-static-member.cpp
    llvm/include/llvm/CodeGen/DebugHandlerBase.h
    llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
    llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
    llvm/test/DebugInfo/COFF/global-constants.ll
    llvm/test/DebugInfo/COFF/types-array-unsized.ll

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 1b1fbccaaa04..6f77aed526bc 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4736,13 +4736,10 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
     }
   }
 
-  llvm::DIScope *DContext = nullptr;
-
   // Do not emit separate definitions for function local consts.
   if (isa<FunctionDecl>(VD->getDeclContext()))
     return;
 
-  // Emit definition for static members in CodeView.
   VD = cast<ValueDecl>(VD->getCanonicalDecl());
   auto *VarD = dyn_cast<VarDecl>(VD);
   if (VarD && VarD->isStaticDataMember()) {
@@ -4755,15 +4752,9 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
     RetainedTypes.push_back(
         CGM.getContext().getRecordType(RD).getAsOpaquePtr());
 
-    if (!CGM.getCodeGenOpts().EmitCodeView)
-      return;
-
-    // Use the global scope for static members.
-    DContext = getContextDescriptor(
-        cast<Decl>(CGM.getContext().getTranslationUnitDecl()), TheCU);
-  } else {
-    DContext = getDeclContextDescriptor(VD);
+    return;
   }
+  llvm::DIScope *DContext = getDeclContextDescriptor(VD);
 
   auto &GV = DeclCache[VD];
   if (GV)

diff  --git a/clang/test/CodeGenCXX/debug-info-static-member.cpp b/clang/test/CodeGenCXX/debug-info-static-member.cpp
index 8ad86843f4e9..260a3afdd652 100644
--- a/clang/test/CodeGenCXX/debug-info-static-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-member.cpp
@@ -1,12 +1,12 @@
-// RUN: %clangxx -target x86_64-unknown-unknown -g %s -emit-llvm -S -o - | FileCheck %s
-// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++98 %s -emit-llvm -S -o - | FileCheck %s
-// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited %s -emit-llvm -o - | FileCheck --check-prefix MSVC %s
+// RUN: %clangxx -target x86_64-unknown-unknown -g %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,NOT-MS %s
+// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++98 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,NOT-MS %s
+// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,NOT-MS %s
+// RUN: %clangxx -target x86_64-windows-msvc -g %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK %s
 // PR14471
 
-// CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]]
-// CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]]
-// CHECK: @_ZN1C1cE = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]]
+// CHECK: @{{.*}}a{{.*}} = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]]
+// CHECK: @{{.*}}b{{.*}} = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]]
+// CHECK: @{{.*}}c{{.*}} = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]]
 
 enum X {
   Y
@@ -36,9 +36,8 @@ class C
 // CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]], expr: !DIExpression())
 // CHECK: [[AV]] = distinct !DIGlobalVariable(name: "a",
 // CHECK-SAME:                                declaration: ![[DECL_A:[0-9]+]])
-// MSVC: distinct !DIGlobalVariable(name: "a"
 //
-// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X")
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}})
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct"
 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var"
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>"
@@ -50,14 +49,13 @@ int C::a = 4;
 // CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]], expr: !DIExpression())
 // CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b",
 // CHECK-SAME:                                declaration: ![[DECL_B:[0-9]+]])
-// MSVC: distinct !DIGlobalVariable(name: "b"
 // CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b"
 // CHECK-NOT:                                 size:
 // CHECK-NOT:                                 align:
 // CHECK-NOT:                                 offset:
 // CHECK-SAME:                                flags: DIFlagProtected | DIFlagStaticMember)
 //
-// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C")
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}})
 //
 // CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a"
 // CHECK-NOT:                                 size:
@@ -98,7 +96,6 @@ int C::a = 4;
 int C::b = 2;
 // CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]], expr: !DIExpression())
 // CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]])
-// MSVC: distinct !DIGlobalVariable(name: "c"
 int C::c = 1;
 
 int main()
@@ -122,14 +119,6 @@ int ref() {
   return anon_static_decl_struct::anon_static_decl_var;
 }
 
-// In MSVC, static data members should be emitted as global variables when used.
-// MSVC: !DIGlobalVariableExpression(var: [[ANON_STATIC_DECL:![0-9]+]],
-// MSVC-SAME: !DIExpression(DW_OP_constu, 117, DW_OP_stack_value)
-// MSVC: [[ANON_STATIC_DECL]] = distinct !DIGlobalVariable(name: "anon_static_decl_var"
-// MSVC: !DIGlobalVariableExpression(var: [[STATIC_DECL_TEMPL:![0-9]+]]
-// MSVC-SAME: !DIExpression(DW_OP_constu, 7, DW_OP_stack_value)
-// MSVC: [[STATIC_DECL_TEMPL]] = distinct !DIGlobalVariable(name: "static_decl_templ_var"
-
 template<typename T>
 struct static_decl_templ {
   static const int static_decl_templ_var = 7;
@@ -151,9 +140,11 @@ struct V {
   virtual ~V(); // cause the definition of 'V' to be omitted by no-standalone-debug optimization
   static const int const_va = 42;
 };
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
-// CHECK-SAME:           line: [[@LINE-3]]
-// CHECK-SAME:           extraData: i32 42
+
+// const_va is not emitted for MS targets.
+// NOT-MS: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
+// NOT-MS-SAME:           line: [[@LINE-5]]
+// NOT-MS-SAME:           extraData: i32 42
 const int V::const_va;
 
 namespace x {

diff  --git a/llvm/include/llvm/CodeGen/DebugHandlerBase.h b/llvm/include/llvm/CodeGen/DebugHandlerBase.h
index b488979f458c..0de88b8867a1 100644
--- a/llvm/include/llvm/CodeGen/DebugHandlerBase.h
+++ b/llvm/include/llvm/CodeGen/DebugHandlerBase.h
@@ -133,6 +133,9 @@ class DebugHandlerBase : public AsmPrinterHandler {
   /// If this type is derived from a base type then return base type size.
   static uint64_t getBaseTypeSize(const DIType *Ty);
 
+  /// Return true if type encoding is unsigned.
+  static bool isUnsignedDIType(const DIType *Ty);
+
   const InstructionOrdering &getInstOrdering() const { return InstOrdering; }
 };
 

diff  --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 98fccf009338..125fea76b841 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -588,13 +588,18 @@ void CodeViewDebug::endModule() {
     if (!P.first->isDeclarationForLinker())
       emitDebugInfoForFunction(P.first, *P.second);
 
-  // Emit global variable debug information.
-  setCurrentSubprogram(nullptr);
-  emitDebugInfoForGlobals();
+  // Get types used by globals without emitting anything.
+  // This is meant to collect all static const data members so they can be
+  // emitted as globals.
+  collectDebugInfoForGlobals();
 
   // Emit retained types.
   emitDebugInfoForRetainedTypes();
 
+  // Emit global variable debug information.
+  setCurrentSubprogram(nullptr);
+  emitDebugInfoForGlobals();
+
   // Switch back to the generic .debug$S section after potentially processing
   // comdat symbol sections.
   switchToDebugSectionForSymbol(nullptr);
@@ -2143,6 +2148,12 @@ void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
                                       const DIDerivedType *DDTy) {
   if (!DDTy->getName().empty()) {
     Info.Members.push_back({DDTy, 0});
+
+    // Collect static const data members.
+    if ((DDTy->getFlags() & DINode::FlagStaticMember) ==
+        DINode::FlagStaticMember)
+      StaticConstMembers.push_back(DDTy);
+
     return;
   }
 
@@ -3045,15 +3056,32 @@ void CodeViewDebug::collectGlobalVariableInfo() {
   }
 }
 
+void CodeViewDebug::collectDebugInfoForGlobals() {
+  for (const CVGlobalVariable &CVGV : GlobalVariables) {
+    const DIGlobalVariable *DIGV = CVGV.DIGV;
+    const DIScope *Scope = DIGV->getScope();
+    getCompleteTypeIndex(DIGV->getType());
+    getFullyQualifiedName(Scope, DIGV->getName());
+  }
+
+  for (const CVGlobalVariable &CVGV : ComdatVariables) {
+    const DIGlobalVariable *DIGV = CVGV.DIGV;
+    const DIScope *Scope = DIGV->getScope();
+    getCompleteTypeIndex(DIGV->getType());
+    getFullyQualifiedName(Scope, DIGV->getName());
+  }
+}
+
 void CodeViewDebug::emitDebugInfoForGlobals() {
   // First, emit all globals that are not in a comdat in a single symbol
   // substream. MSVC doesn't like it if the substream is empty, so only open
   // it if we have at least one global to emit.
   switchToDebugSectionForSymbol(nullptr);
-  if (!GlobalVariables.empty()) {
+  if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
     OS.AddComment("Symbol subsection for globals");
     MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
     emitGlobalVariableList(GlobalVariables);
+    emitStaticConstMemberList();
     endCVSubsection(EndLabel);
   }
 
@@ -3092,6 +3120,42 @@ void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) {
   }
 }
 
+void CodeViewDebug::emitStaticConstMemberList() {
+  for (const DIDerivedType *DTy : StaticConstMembers) {
+    const DIScope *Scope = DTy->getScope();
+
+    APSInt Value;
+    if (const ConstantInt *CI =
+            dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
+      Value = APSInt(CI->getValue(),
+                     DebugHandlerBase::isUnsignedDIType(DTy->getBaseType()));
+    else if (const ConstantFP *CFP =
+                 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
+      Value = APSInt(CFP->getValueAPF().bitcastToAPInt(), true);
+    else
+      continue;
+
+    std::string QualifiedName = getFullyQualifiedName(Scope, DTy->getName());
+
+    MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
+    OS.AddComment("Type");
+    OS.emitInt32(getTypeIndex(DTy->getBaseType()).getIndex());
+    OS.AddComment("Value");
+
+    // Encoded integers shouldn't need more than 10 bytes.
+    uint8_t Data[10];
+    BinaryStreamWriter Writer(Data, llvm::support::endianness::little);
+    CodeViewRecordIO IO(Writer);
+    cantFail(IO.mapEncodedInteger(Value));
+    StringRef SRef((char *)Data, Writer.getOffset());
+    OS.emitBinaryData(SRef);
+
+    OS.AddComment("Name");
+    emitNullTerminatedSymbolName(OS, QualifiedName);
+    endSymbolRecord(SConstantEnd);
+  }
+}
+
 void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
   const DIGlobalVariable *DIGV = CVGV.DIGV;
 

diff  --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 82f0293874d0..0e4fd534ea07 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -203,6 +203,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
   // Array of non-COMDAT global variables.
   SmallVector<CVGlobalVariable, 1> GlobalVariables;
 
+  /// List of static const data members to be emitted as S_CONSTANTs.
+  SmallVector<const DIDerivedType *, 4> StaticConstMembers;
+
   /// The set of comdat .debug$S sections that we've seen so far. Each section
   /// must start with a magic version number that must only be emitted once.
   /// This set tracks which sections we've already opened.
@@ -313,9 +316,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
   void emitDebugInfoForUDTs(
       const std::vector<std::pair<std::string, const DIType *>> &UDTs);
 
+  void collectDebugInfoForGlobals();
   void emitDebugInfoForGlobals();
   void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals);
   void emitDebugInfoForGlobal(const CVGlobalVariable &CVGV);
+  void emitStaticConstMemberList();
 
   /// Opens a subsection of the given kind in a .debug$S codeview section.
   /// Returns an end label for use with endCVSubsection when the subsection is

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 826c5078ed50..9d963a3f5872 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -158,6 +158,54 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
   return getBaseTypeSize(BaseType);
 }
 
+bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
+  if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
+    // FIXME: Enums without a fixed underlying type have unknown signedness
+    // here, leading to incorrectly emitted constants.
+    if (CTy->getTag() == dwarf::DW_TAG_enumeration_type)
+      return false;
+
+    // (Pieces of) aggregate types that get hacked apart by SROA may be
+    // represented by a constant. Encode them as unsigned bytes.
+    return true;
+  }
+
+  if (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
+    dwarf::Tag T = (dwarf::Tag)Ty->getTag();
+    // Encode pointer constants as unsigned bytes. This is used at least for
+    // null pointer constant emission.
+    // FIXME: reference and rvalue_reference /probably/ shouldn't be allowed
+    // here, but accept them for now due to a bug in SROA producing bogus
+    // dbg.values.
+    if (T == dwarf::DW_TAG_pointer_type ||
+        T == dwarf::DW_TAG_ptr_to_member_type ||
+        T == dwarf::DW_TAG_reference_type ||
+        T == dwarf::DW_TAG_rvalue_reference_type)
+      return true;
+    assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
+           T == dwarf::DW_TAG_volatile_type ||
+           T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type);
+    assert(DTy->getBaseType() && "Expected valid base type");
+    return isUnsignedDIType(DTy->getBaseType());
+  }
+
+  auto *BTy = cast<DIBasicType>(Ty);
+  unsigned Encoding = BTy->getEncoding();
+  assert((Encoding == dwarf::DW_ATE_unsigned ||
+          Encoding == dwarf::DW_ATE_unsigned_char ||
+          Encoding == dwarf::DW_ATE_signed ||
+          Encoding == dwarf::DW_ATE_signed_char ||
+          Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||
+          Encoding == dwarf::DW_ATE_boolean ||
+          (Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
+           Ty->getName() == "decltype(nullptr)")) &&
+         "Unsupported encoding");
+  return Encoding == dwarf::DW_ATE_unsigned ||
+         Encoding == dwarf::DW_ATE_unsigned_char ||
+         Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||
+         Ty->getTag() == dwarf::DW_TAG_unspecified_type;
+}
+
 static bool hasDebugInfo(const MachineModuleInfo *MMI,
                          const MachineFunction *MF) {
   if (!MMI->hasDebugInfo())

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index cf0d30e5a1c7..6208b5f2777f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -434,55 +434,6 @@ void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {
   addSourceLine(Die, Ty->getLine(), Ty->getFile());
 }
 
-/// Return true if type encoding is unsigned.
-static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) {
-  if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
-    // FIXME: Enums without a fixed underlying type have unknown signedness
-    // here, leading to incorrectly emitted constants.
-    if (CTy->getTag() == dwarf::DW_TAG_enumeration_type)
-      return false;
-
-    // (Pieces of) aggregate types that get hacked apart by SROA may be
-    // represented by a constant. Encode them as unsigned bytes.
-    return true;
-  }
-
-  if (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
-    dwarf::Tag T = (dwarf::Tag)Ty->getTag();
-    // Encode pointer constants as unsigned bytes. This is used at least for
-    // null pointer constant emission.
-    // FIXME: reference and rvalue_reference /probably/ shouldn't be allowed
-    // here, but accept them for now due to a bug in SROA producing bogus
-    // dbg.values.
-    if (T == dwarf::DW_TAG_pointer_type ||
-        T == dwarf::DW_TAG_ptr_to_member_type ||
-        T == dwarf::DW_TAG_reference_type ||
-        T == dwarf::DW_TAG_rvalue_reference_type)
-      return true;
-    assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
-           T == dwarf::DW_TAG_volatile_type ||
-           T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type);
-    assert(DTy->getBaseType() && "Expected valid base type");
-    return isUnsignedDIType(DD, DTy->getBaseType());
-  }
-
-  auto *BTy = cast<DIBasicType>(Ty);
-  unsigned Encoding = BTy->getEncoding();
-  assert((Encoding == dwarf::DW_ATE_unsigned ||
-          Encoding == dwarf::DW_ATE_unsigned_char ||
-          Encoding == dwarf::DW_ATE_signed ||
-          Encoding == dwarf::DW_ATE_signed_char ||
-          Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||
-          Encoding == dwarf::DW_ATE_boolean ||
-          (Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
-           Ty->getName() == "decltype(nullptr)")) &&
-         "Unsupported encoding");
-  return Encoding == dwarf::DW_ATE_unsigned ||
-         Encoding == dwarf::DW_ATE_unsigned_char ||
-         Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||
-         Ty->getTag() == dwarf::DW_TAG_unspecified_type;
-}
-
 void DwarfUnit::addConstantFPValue(DIE &Die, const MachineOperand &MO) {
   assert(MO.isFPImm() && "Invalid machine operand!");
   DIEBlock *Block = new (DIEValueAllocator) DIEBlock;
@@ -519,11 +470,11 @@ void DwarfUnit::addConstantValue(DIE &Die, const MachineOperand &MO,
                                  const DIType *Ty) {
   assert(MO.isImm() && "Invalid machine operand!");
 
-  addConstantValue(Die, isUnsignedDIType(DD, Ty), MO.getImm());
+  addConstantValue(Die, DD->isUnsignedDIType(Ty), MO.getImm());
 }
 
 void DwarfUnit::addConstantValue(DIE &Die, uint64_t Val, const DIType *Ty) {
-  addConstantValue(Die, isUnsignedDIType(DD, Ty), Val);
+  addConstantValue(Die, DD->isUnsignedDIType(Ty), Val);
 }
 
 void DwarfUnit::addConstantValue(DIE &Die, bool Unsigned, uint64_t Val) {
@@ -534,7 +485,7 @@ void DwarfUnit::addConstantValue(DIE &Die, bool Unsigned, uint64_t Val) {
 }
 
 void DwarfUnit::addConstantValue(DIE &Die, const APInt &Val, const DIType *Ty) {
-  addConstantValue(Die, Val, isUnsignedDIType(DD, Ty));
+  addConstantValue(Die, Val, DD->isUnsignedDIType(Ty));
 }
 
 void DwarfUnit::addConstantValue(DIE &Die, const APInt &Val, bool Unsigned) {
@@ -936,7 +887,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
           DIE &Variant = createAndAddDIE(dwarf::DW_TAG_variant, Buffer);
           if (const ConstantInt *CI =
               dyn_cast_or_null<ConstantInt>(DDTy->getDiscriminantValue())) {
-            if (isUnsignedDIType(DD, Discriminator->getBaseType()))
+            if (DD->isUnsignedDIType(Discriminator->getBaseType()))
               addUInt(Variant, dwarf::DW_AT_discr_value, None, CI->getZExtValue());
             else
               addSInt(Variant, dwarf::DW_AT_discr_value, None, CI->getSExtValue());
@@ -1543,7 +1494,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
 
 void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
   const DIType *DTy = CTy->getBaseType();
-  bool IsUnsigned = DTy && isUnsignedDIType(DD, DTy);
+  bool IsUnsigned = DTy && DD->isUnsignedDIType(DTy);
   if (DTy) {
     if (DD->getDwarfVersion() >= 3)
       addType(Buffer, DTy);

diff  --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
index 49761b9dce88..c272985cf2d4 100644
--- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -273,7 +273,6 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value,
 
 void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value,
                                                 const Twine &Comment) {
-  assert(Value < 0 && "Encoded integer is not signed!");
   if (Value >= std::numeric_limits<int8_t>::min()) {
     Streamer->emitIntValue(LF_CHAR, 2);
     emitComment(Comment);
@@ -322,7 +321,6 @@ void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value,
 }
 
 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
-  assert(Value < 0 && "Encoded integer is not signed!");
   if (Value >= std::numeric_limits<int8_t>::min()) {
     if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
       return EC;

diff  --git a/llvm/test/DebugInfo/COFF/global-constants.ll b/llvm/test/DebugInfo/COFF/global-constants.ll
index f930df48be10..8276932925ac 100644
--- a/llvm/test/DebugInfo/COFF/global-constants.ll
+++ b/llvm/test/DebugInfo/COFF/global-constants.ll
@@ -7,6 +7,9 @@
 ; }
 ; struct S {
 ;   static const int TestConst2 = -10;
+;   // Unused static consts should still be emitted.
+;   static const int TestConst3 = 3;
+;   static constexpr int TestConst 4 = 4;
 ;   enum { SEnum = 42 };
 ; };
 ; enum TestEnum : int {
@@ -34,14 +37,6 @@
 
 ; ASM:	      .short	4359                    # Record kind: S_CONSTANT
 ; ASM-NEXT:	  .long	4101                    # Type
-; ASM-NEXT:	  .byte	0x0a, 0x80, 0xf6, 0xff  # Value
-; ASM-NEXT:	  .byte	0xff, 0xff, 0xff, 0xff
-; ASM-NEXT:	  .byte	0xff, 0xff
-; ASM-NEXT:	  .asciz	"S::TestConst2"         # Name
-; ASM-NEXT:	  .p2align	2
-
-; ASM:	      .short	4359                    # Record kind: S_CONSTANT
-; ASM-NEXT:	  .long	4110                    # Type
 ; ASM-NEXT:	  .byte	0x0a, 0x80, 0x40, 0x61  # Value
 ; ASM-NEXT:	  .byte	0x07, 0x80, 0xff, 0xff
 ; ASM-NEXT:	  .byte	0xff, 0xff
@@ -49,6 +44,12 @@
 ; ASM-NEXT:	  .p2align	2
 ; ASM-NOT:    .asciz "S::SEnum"             # Name
 
+; ASM:	      .short	4359                    # Record kind: S_CONSTANT
+; ASM-NEXT:	  .long	4105                    # Type
+; ASM-NEXT:	  .byte	0x00, 0x80, 0xf6        # Value
+; ASM-NEXT:	  .asciz	"S::TestConst2"         # Name
+; ASM-NEXT:	  .p2align	2
+
 ; OBJ:        CodeViewDebugInfo [
 ; OBJ:          Section: .debug$S
 ; OBJ:          Magic: 0x4
@@ -62,17 +63,17 @@
 ; OBJ-NEXT:       }
 ; OBJ-NEXT:       ConstantSym {
 ; OBJ-NEXT:         Kind: S_CONSTANT (0x1107)
-; OBJ-NEXT:         Type: const int (0x1005)
-; OBJ-NEXT:         Value: 18446744073709551606
-; OBJ-NEXT:         Name: S::TestConst2
-; OBJ-NEXT:       }
-; OBJ-NEXT:       ConstantSym {
-; OBJ-NEXT:         Kind: S_CONSTANT (0x1107)
-; OBJ-NEXT:         Type: TestEnum (0x100E)
+; OBJ-NEXT:         Type: TestEnum (0x1005)
 ; OBJ-NEXT:         Value: 18446744071562551616
 ; OBJ-NEXT:         Name: ENUM_B
 ; OBJ-NEXT:       }
 ; OBJ-NOT:          Name: S::SEnum
+; OBJ-NEXT:       ConstantSym {
+; OBJ-NEXT:         Kind: S_CONSTANT (0x1107)
+; OBJ-NEXT:         Type: const int (0x1009)
+; OBJ-NEXT:         Value: -10
+; OBJ-NEXT:         Name: S::TestConst2
+; OBJ-NEXT:       }
 
 ; ModuleID = 'a.cpp'
 source_filename = "a.cpp"
@@ -98,43 +99,43 @@ attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-
 !llvm.module.flags = !{!26, !27, !28, !29}
 !llvm.ident = !{!30}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 202f144bffd0be254a829924195e1b8ebabcbb79)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !15, globals: !16, nameTableKind: None)
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git 34cd06a9b3bddaa7a989c606bbf1327ee651711c)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !17, globals: !18, nameTableKind: None)
 !1 = !DIFile(filename: "a.cpp", directory: "F:\\llvm-project\\__test", checksumkind: CSK_MD5, checksum: "a1dbf3aabea9e8f9d1be48f60287942f")
-!2 = !{!3, !11}
-!3 = !DICompositeType(tag: DW_TAG_enumeration_type, scope: !4, file: !1, line: 6, baseType: !8, size: 32, elements: !9, identifier: ".?AW4<unnamed-enum-SEnum>@S@@")
+!2 = !{!3, !13}
+!3 = !DICompositeType(tag: DW_TAG_enumeration_type, scope: !4, file: !1, line: 8, baseType: !8, size: 32, elements: !11, identifier: ".?AW4<unnamed-enum-SEnum>@S@@")
 !4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !1, line: 4, size: 8, flags: DIFlagTypePassByValue, elements: !5, identifier: ".?AUS@@")
-!5 = !{!6, !3}
+!5 = !{!6, !9, !10, !3}
 !6 = !DIDerivedType(tag: DW_TAG_member, name: "TestConst2", scope: !4, file: !1, line: 5, baseType: !7, flags: DIFlagStaticMember, extraData: i32 -10)
 !7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8)
 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!9 = !{!10}
-!10 = !DIEnumerator(name: "SEnum", value: 42)
-!11 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "TestEnum", file: !1, line: 8, baseType: !8, size: 32, elements: !12, identifier: ".?AW4TestEnum@@")
-!12 = !{!13, !14}
-!13 = !DIEnumerator(name: "ENUM_A", value: 2147000000)
-!14 = !DIEnumerator(name: "ENUM_B", value: -2147000000)
-!15 = !{!4}
-!16 = !{!17, !22, !24}
-!17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression(DW_OP_constu, 1078523331, DW_OP_stack_value))
-!18 = distinct !DIGlobalVariable(name: "TestConst1", scope: !19, file: !1, line: 2, type: !20, isLocal: true, isDefinition: true)
-!19 = !DINamespace(name: "Test1", scope: null)
-!20 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !21)
-!21 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
-!22 = !DIGlobalVariableExpression(var: !23, expr: !DIExpression(DW_OP_constu, 18446744073709551606, DW_OP_stack_value))
-!23 = distinct !DIGlobalVariable(name: "TestConst2", scope: !0, file: !1, line: 5, type: !7, isLocal: true, isDefinition: true, declaration: !6)
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "TestConst3", scope: !4, file: !1, line: 6, baseType: !7, flags: DIFlagStaticMember, extraData: i32 3)
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "TestConst4", scope: !4, file: !1, line: 7, baseType: !7, flags: DIFlagStaticMember, extraData: i32 4)
+!11 = !{!12}
+!12 = !DIEnumerator(name: "SEnum", value: 42)
+!13 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "TestEnum", file: !1, line: 10, baseType: !8, size: 32, elements: !14, identifier: ".?AW4TestEnum@@")
+!14 = !{!15, !16}
+!15 = !DIEnumerator(name: "ENUM_A", value: 2147000000)
+!16 = !DIEnumerator(name: "ENUM_B", value: -2147000000)
+!17 = !{!4}
+!18 = !{!19, !24}
+!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression(DW_OP_constu, 1078523331, DW_OP_stack_value))
+!20 = distinct !DIGlobalVariable(name: "TestConst1", scope: !21, file: !1, line: 2, type: !22, isLocal: true, isDefinition: true)
+!21 = !DINamespace(name: "Test1", scope: null)
+!22 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !23)
+!23 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
 !24 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression(DW_OP_constu, 18446744071562551616, DW_OP_stack_value))
-!25 = distinct !DIGlobalVariable(name: "ENUM_B", scope: !0, file: !1, line: 10, type: !11, isLocal: true, isDefinition: true)
+!25 = distinct !DIGlobalVariable(name: "ENUM_B", scope: !0, file: !1, line: 12, type: !13, isLocal: true, isDefinition: true)
 !26 = !{i32 2, !"CodeView", i32 1}
 !27 = !{i32 2, !"Debug Info Version", i32 3}
 !28 = !{i32 1, !"wchar_size", i32 2}
 !29 = !{i32 7, !"PIC Level", i32 2}
-!30 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git 202f144bffd0be254a829924195e1b8ebabcbb79)"}
-!31 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAXXZ", scope: !1, file: !1, line: 13, type: !32, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !34)
+!30 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 34cd06a9b3bddaa7a989c606bbf1327ee651711c)"}
+!31 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAXXZ", scope: !1, file: !1, line: 15, type: !32, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !34)
 !32 = !DISubroutineType(types: !33)
 !33 = !{null}
 !34 = !{}
-!35 = !DILocation(line: 14, scope: !31)
-!36 = !DILocation(line: 15, scope: !31)
-!37 = !DILocation(line: 16, scope: !31)
-!38 = !DILocation(line: 17, scope: !31)
-!39 = !DILocation(line: 18, scope: !31)
+!35 = !DILocation(line: 16, scope: !31)
+!36 = !DILocation(line: 17, scope: !31)
+!37 = !DILocation(line: 18, scope: !31)
+!38 = !DILocation(line: 19, scope: !31)
+!39 = !DILocation(line: 20, scope: !31)

diff  --git a/llvm/test/DebugInfo/COFF/types-array-unsized.ll b/llvm/test/DebugInfo/COFF/types-array-unsized.ll
index 8bfb0c08ee39..bae5707c76e0 100644
--- a/llvm/test/DebugInfo/COFF/types-array-unsized.ll
+++ b/llvm/test/DebugInfo/COFF/types-array-unsized.ll
@@ -12,14 +12,22 @@
 ; Foo f; // FIXME: only needed to force emit 'Foo'
 
 ; CHECK:      CodeViewTypes [
+; CHECK:        Array ([[ARRAY_COMPLETE:0x.*]]) {
+; CHECK-NEXT:     TypeLeafKind: LF_ARRAY (0x1503)
+; CHECK-NEXT:     ElementType: const char ({{.*}})
+; CHECK-NEXT:     IndexType: unsigned __int64 (0x23)
+; CHECK-NEXT:     SizeOf: 5
+; CHECK-NEXT:     Name:
+; CHECK-NEXT:   }
+; CHECK:      ]
 ; CHECK:        Array ([[ARRAY_FWD:0x.*]]) {
 ; CHECK-NEXT:     TypeLeafKind: LF_ARRAY (0x1503)
 ; CHECK-NEXT:     ElementType: const char ({{.*}})
 ; CHECK-NEXT:     IndexType: unsigned __int64 (0x23)
 ; CHECK-NEXT:     SizeOf: 0
-; CHECK-NEXT:     Name: 
+; CHECK-NEXT:     Name:
 ; CHECK-NEXT:   }
-; CHECK:        FieldList (0x1003) {
+; CHECK:        FieldList (0x1004) {
 ; CHECK-NEXT:     TypeLeafKind: LF_FIELDLIST (0x1203)
 ; CHECK-NEXT:     StaticDataMember {
 ; CHECK-NEXT:       TypeLeafKind: LF_STMEMBER (0x150E)
@@ -28,14 +36,6 @@
 ; CHECK-NEXT:       Name: str
 ; CHECK-NEXT:     }
 ; CHECK-NEXT:   }
-; CHECK:        Array ([[ARRAY_COMPLETE:0x.*]]) {
-; CHECK-NEXT:     TypeLeafKind: LF_ARRAY (0x1503)
-; CHECK-NEXT:     ElementType: const char ({{.*}})
-; CHECK-NEXT:     IndexType: unsigned __int64 (0x23)
-; CHECK-NEXT:     SizeOf: 5
-; CHECK-NEXT:     Name: 
-; CHECK-NEXT:   }
-; CHECK:      ]
 
 ; CHECK:          GlobalData {
 ; CHECK-NEXT:       Kind: S_GDATA32 (0x110D)


        


More information about the llvm-commits mailing list