diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 1b1fbccaaa048..6f77aed526bc4 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(VD->getDeclContext())) return; - // Emit definition for static members in CodeView. VD = cast(VD->getCanonicalDecl()); auto *VarD = dyn_cast(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(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 8ad86843f4e9e..260a3afdd6524 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" @@ -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 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 b488979f458cd..0de88b8867a14 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 98fccf0093389..125fea76b8418 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 Globals) { } } +void CodeViewDebug::emitStaticConstMemberList() { + for (const DIDerivedType *DTy : StaticConstMembers) { + const DIScope *Scope = DTy->getScope(); + + APSInt Value; + if (const ConstantInt *CI = + dyn_cast_or_null(DTy->getConstant())) + Value = APSInt(CI->getValue(), + DebugHandlerBase::isUnsignedDIType(DTy->getBaseType())); + else if (const ConstantFP *CFP = + dyn_cast_or_null(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 82f0293874d04..0e4fd534ea07d 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 GlobalVariables; + /// List of static const data members to be emitted as S_CONSTANTs. + SmallVector 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> &UDTs); + void collectDebugInfoForGlobals(); void emitDebugInfoForGlobals(); void emitGlobalVariableList(ArrayRef 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 826c5078ed506..9d963a3f5872f 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(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(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(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 cf0d30e5a1c7f..6208b5f2777fb 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(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(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(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(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 49761b9dce88e..c272985cf2d49 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -273,7 +273,6 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector &Value, void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, const Twine &Comment) { - assert(Value < 0 && "Encoded integer is not signed!"); if (Value >= std::numeric_limits::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::min()) { if (auto EC = Writer->writeInteger(LF_CHAR)) return EC; diff --git a/llvm/test/DebugInfo/COFF/global-constants.ll b/llvm/test/DebugInfo/COFF/global-constants.ll index f930df48be106..8276932925ac4 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@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@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 8bfb0c08ee392..bae5707c76e05 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)