Recommit "[CodeView] Emit static data members as S_CONSTANTs."
authorAmy Huang <akhuang@google.com>
Tue, 27 Oct 2020 18:35:57 +0000 (11:35 -0700)
committerAmy Huang <akhuang@google.com>
Wed, 28 Oct 2020 23:35:59 +0000 (16:35 -0700)
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.

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

index 1b1fbccaaa0481eaf0e1879c465aabdc999544e7..6f77aed526bc4ab19453e43eead1b9c2d67af207 100644 (file)
@@ -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)
index 8ad86843f4e9e7a88575da17883ef48670a48a08..260a3afdd6524f349e02be3128f2e50d267ca1c5 100644 (file)
@@ -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 @@ public:
 // 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 {
index b488979f458cdbd5c18da2a0f8319997f01ca2b5..0de88b8867a14d6e74a3421d91e451409103b6d7 100644 (file)
@@ -133,6 +133,9 @@ public:
   /// 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; }
 };
 
index 98fccf0093389a1e35d3fffe8f0d04e452c99f4c..125fea76b84182e45e83e15c914dbb7ac996e7fd 100644 (file)
@@ -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;
 
index 82f0293874d047c55d0cbb439e19bcada3644909..0e4fd534ea07d0db6c166c48e66db1473054a088 100644 (file)
@@ -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
index 826c5078ed506d2d79ea93e7a40866fc068f1ae4..9d963a3f5872f8058b76c86f0935c14341b66739 100644 (file)
@@ -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())
index cf0d30e5a1c7faea02d431dbb6402d6f0d9bafa5..6208b5f2777fb43c6f5b017fa5a3dca9e8a00071 100644 (file)
@@ -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);
index 49761b9dce88e7619111dc307c5ea21d527db946..c272985cf2d49ed08897367e0c690ddba1a78ad7 100644 (file)
@@ -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;
index f930df48be1067bc9acfc6268bf01a848d105bfd..8276932925ac45fed47e3293939d10fedd4b9e5f 100644 (file)
@@ -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 {
 
 ; 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
 ; 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
 ; 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)
index 8bfb0c08ee392dd777e4c8aacf4a3ac620c44f9d..bae5707c76e052e83f13374d071f7b87d19d461d 100644 (file)
 ; 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)
 ; 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)