Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -99,6 +99,11 @@ bool UseReferenceType = false; }; + struct CVGlobalVariable { + const DIGlobalVariable *DIGV; + const GlobalVariable *GV; + }; + struct InlineSite { SmallVector InlinedLocals; SmallVector ChildSites; @@ -112,6 +117,7 @@ // Combines information from DILexicalBlock and LexicalScope. struct LexicalBlock { SmallVector Locals; + SmallVector Globals; SmallVector Children; const MCSymbol *Begin; const MCSymbol *End; @@ -134,6 +140,7 @@ SmallVector ChildSites; SmallVector Locals; + SmallVector Globals; std::unordered_map LexicalBlocks; @@ -183,6 +190,17 @@ // and LexicalBlocks. DenseMap> ScopeVariables; + // Map to separate global variables according to the lexical scope they + // belong in. A null local scope represents the global scope. + typedef SmallVector GlobalVariableList; + DenseMap > ScopeGlobals; + + // Array of global variables which need to be emitted into a COMDAT section. + SmallVector ComdatVariables; + + // Array of non-COMDAT global variables. + SmallVector GlobalVariables; + /// 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. @@ -288,13 +306,13 @@ void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI); - void emitDebugInfoForGlobals(); - void emitDebugInfoForRetainedTypes(); void emitDebugInfoForUDTs(ArrayRef> UDTs); + void emitDebugInfoForGlobals(); + void emitGlobalVariableList(ArrayRef Globals); void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, const GlobalVariable *GV, MCSymbol *GVSym); @@ -310,6 +328,7 @@ using InlinedEntity = DbgValueHistoryMap::InlinedEntity; + void collectGlobalVariableInfo(); void collectVariableInfo(const DISubprogram *SP); void collectVariableInfoFromMFTable(DenseSet &Processed); @@ -318,10 +337,12 @@ // scopes, and populate it with local variables. void collectLexicalBlockInfo(SmallVectorImpl &Scopes, SmallVectorImpl &Blocks, - SmallVectorImpl &Locals); + SmallVectorImpl &Locals, + SmallVectorImpl &Globals); void collectLexicalBlockInfo(LexicalScope &Scope, SmallVectorImpl &ParentBlocks, - SmallVectorImpl &ParentLocals); + SmallVectorImpl &ParentLocals, + SmallVectorImpl &ParentGlobals); /// Records information about a local variable in the appropriate scope. In /// particular, locals from inlined code live inside the inlining site. Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -123,6 +123,8 @@ TheCPU = mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch()); + collectGlobalVariableInfo(); + // Check if we should emit type record hashes. ConstantInt *GH = mdconst::extract_or_null( MMI->getModule()->getModuleFlag("CodeViewGHash")); @@ -1082,6 +1084,7 @@ OS.EmitLabel(FrameProcEnd); emitLocalVariableList(FI, FI.Locals); + emitGlobalVariableList(FI.Globals); emitLexicalBlockList(FI.ChildBlocks, FI); // Emit inlined call site information. Only emit functions inlined directly @@ -2099,6 +2102,7 @@ GlobalUDTs.clear(); TypeIndices.clear(); CompleteTypeIndices.clear(); + ScopeGlobals.clear(); } void CodeViewDebug::collectMemberInfo(ClassInfo &Info, @@ -2716,6 +2720,7 @@ // Emit variables local to this lexical block. emitLocalVariableList(FI, Block.Locals); + emitGlobalVariableList(Block.Globals); // Emit lexical blocks contained within this block. emitLexicalBlockList(Block.Children, FI); @@ -2732,9 +2737,10 @@ void CodeViewDebug::collectLexicalBlockInfo( SmallVectorImpl &Scopes, SmallVectorImpl &Blocks, - SmallVectorImpl &Locals) { + SmallVectorImpl &Locals, + SmallVectorImpl &Globals) { for (LexicalScope *Scope : Scopes) - collectLexicalBlockInfo(*Scope, Blocks, Locals); + collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals); } /// Populate the lexical blocks and local variable lists of the parent with @@ -2742,45 +2748,58 @@ void CodeViewDebug::collectLexicalBlockInfo( LexicalScope &Scope, SmallVectorImpl &ParentBlocks, - SmallVectorImpl &ParentLocals) { + SmallVectorImpl &ParentLocals, + SmallVectorImpl &ParentGlobals) { if (Scope.isAbstractScope()) return; - auto LocalsIter = ScopeVariables.find(&Scope); - if (LocalsIter == ScopeVariables.end()) { - // This scope does not contain variables and can be eliminated. - collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals); - return; - } - SmallVectorImpl &Locals = LocalsIter->second; - + // Gather information about the lexical scope including local variables, + // global variables, and address ranges. + bool IgnoreScope = false; + auto LI = ScopeVariables.find(&Scope); + SmallVectorImpl *Locals = + LI != ScopeVariables.end() ? &LI->second : nullptr; + auto GI = ScopeGlobals.find(Scope.getScopeNode()); + SmallVectorImpl *Globals = + GI != ScopeGlobals.end() ? GI->second.get() : nullptr; const DILexicalBlock *DILB = dyn_cast(Scope.getScopeNode()); - if (!DILB) { - // This scope is not a lexical block and can be eliminated, but keep any - // local variables it contains. - ParentLocals.append(Locals.begin(), Locals.end()); - collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals); - return; - } - const SmallVectorImpl &Ranges = Scope.getRanges(); - if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) { - // This lexical block scope has too many address ranges to represent in the - // current CodeView format or does not have a valid address range. - // Eliminate this lexical scope and promote any locals it contains to the - // parent scope. - // - // For lexical scopes with multiple address ranges you may be tempted to - // construct a single range covering every instruction where the block is - // live and everything in between. Unfortunately, Visual Studio only - // displays variables from the first matching lexical block scope. If the - // first lexical block contains exception handling code or cold code which - // is moved to the bottom of the routine creating a single range covering - // nearly the entire routine, then it will hide all other lexical blocks - // and the variables they contain. - // - ParentLocals.append(Locals.begin(), Locals.end()); - collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals); + + // Ignore lexical scopes which do not contain variables. + if (!Locals && !Globals) + IgnoreScope = true; + + // Ignore lexical scopes which are not lexical blocks. + if (!DILB) + IgnoreScope = true; + + // Ignore scopes which have too many address ranges to represent in the + // current CodeView format or do not have a valid address range. + // + // For lexical scopes with multiple address ranges you may be tempted to + // construct a single range covering every instruction where the block is + // live and everything in between. Unfortunately, Visual Studio only + // displays variables from the first matching lexical block scope. If the + // first lexical block contains exception handling code or cold code which + // is moved to the bottom of the routine creating a single range covering + // nearly the entire routine, then it will hide all other lexical blocks + // and the variables they contain. + if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) + IgnoreScope = true; + + if (IgnoreScope) { + // This scope can be safely ignored and eliminating it will reduce the + // size of the debug information. Be sure to collect any variable and scope + // information from the this scope or any of its children and collapse them + // into the parent scope. + if (Locals) + ParentLocals.append(Locals->begin(), Locals->end()); + if (Globals) + ParentGlobals.append(Globals->begin(), Globals->end()); + collectLexicalBlockInfo(Scope.getChildren(), + ParentBlocks, + ParentLocals, + ParentGlobals); return; } @@ -2791,8 +2810,8 @@ if (!BlockInsertion.second) return; - // Create a lexical block containing the local variables and collect the - // the lexical block information for the children. + // Create a lexical block containing the variables and collect the the + // lexical block information for the children. const InsnRange &Range = Ranges.front(); assert(Range.first && Range.second); LexicalBlock &Block = BlockInsertion.first->second; @@ -2801,9 +2820,15 @@ assert(Block.Begin && "missing label for scope begin"); assert(Block.End && "missing label for scope end"); Block.Name = DILB->getName(); - Block.Locals = std::move(Locals); + if (Locals) + Block.Locals = std::move(*Locals); + if (Globals) + Block.Globals = std::move(*Globals); ParentBlocks.push_back(&Block); - collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals); + collectLexicalBlockInfo(Scope.getChildren(), + Block.Children, + Block.Locals, + Block.Globals); } void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) { @@ -2815,7 +2840,10 @@ // Build the lexical block structure to emit for this routine. if (LexicalScope *CFS = LScopes.getCurrentFunctionScope()) - collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals); + collectLexicalBlockInfo(*CFS, + CurFn->ChildBlocks, + CurFn->Locals, + CurFn->Globals); // Clear the scope and variable information from the map which will not be // valid after we have finished processing this routine. This also prepares @@ -2905,7 +2933,7 @@ } } -void CodeViewDebug::emitDebugInfoForGlobals() { +void CodeViewDebug::collectGlobalVariableInfo() { DenseMap GlobalMap; for (const GlobalVariable &GV : MMI->getModule()->globals()) { @@ -2918,42 +2946,59 @@ NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); for (const MDNode *Node : CUs->operands()) { const auto *CU = cast(Node); - - // 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); - MCSymbol *EndLabel = nullptr; for (const auto *GVE : CU->getGlobalVariables()) { - if (const auto *GV = GlobalMap.lookup(GVE)) - if (!GV->hasComdat() && !GV->isDeclarationForLinker()) { - if (!EndLabel) { - OS.AddComment("Symbol subsection for globals"); - EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); - } - // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. - emitDebugInfoForGlobal(GVE->getVariable(), GV, Asm->getSymbol(GV)); + const auto *GV = GlobalMap.lookup(GVE); + if (!GV || GV->isDeclarationForLinker()) + continue; + const DIGlobalVariable *DIGV = GVE->getVariable(); + DIScope *Scope = DIGV->getScope(); + SmallVector *VariableList; + if (Scope && isa(Scope)) { + // Locate a global variable list for this scope, creating one if + // necessary. + auto I = ScopeGlobals.find(Scope); + if (I == ScopeGlobals.end()) { + bool inserted; + std::tie(I, inserted) = ScopeGlobals.insert( + {Scope, llvm::make_unique()}); + assert(inserted && "Expected insert because the key didn't exist."); } + VariableList = I->second.get(); + } else if (GV->hasComdat()) + // Emit this global variable into a COMDAT section. + VariableList = &ComdatVariables; + else + // Emit this globla variable in a single global symbol section. + VariableList = &GlobalVariables; + CVGlobalVariable CVGV = {DIGV, GV}; + VariableList->emplace_back(std::move(CVGV)); } - if (EndLabel) - endCVSubsection(EndLabel); + } +} - // Second, emit each global that is in a comdat into its own .debug$S - // section along with its own symbol substream. - for (const auto *GVE : CU->getGlobalVariables()) { - if (const auto *GV = GlobalMap.lookup(GVE)) { - if (GV->hasComdat()) { - MCSymbol *GVSym = Asm->getSymbol(GV); - OS.AddComment("Symbol subsection for " + - Twine(GlobalValue::dropLLVMManglingEscape(GV->getName()))); - switchToDebugSectionForSymbol(GVSym); - EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); - // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. - emitDebugInfoForGlobal(GVE->getVariable(), GV, GVSym); - endCVSubsection(EndLabel); - } - } - } +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()) { + OS.AddComment("Symbol subsection for globals"); + MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); + emitGlobalVariableList(GlobalVariables); + endCVSubsection(EndLabel); + } + + // Second, emit each global that is in a comdat into its own .debug$S + // section along with its own symbol substream. + for (const CVGlobalVariable &CVGV : ComdatVariables) { + MCSymbol *GVSym = Asm->getSymbol(CVGV.GV); + OS.AddComment("Symbol subsection for " + + Twine(GlobalValue::dropLLVMManglingEscape(CVGV.GV->getName()))); + switchToDebugSectionForSymbol(GVSym); + MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); + // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. + emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym); + endCVSubsection(EndLabel); } } @@ -2969,6 +3014,15 @@ } } +// Emit each global variable in the specified array. +void CodeViewDebug::emitGlobalVariableList(ArrayRef Globals) { + for (const CVGlobalVariable &CVGV : Globals) { + MCSymbol *GVSym = Asm->getSymbol(CVGV.GV); + // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. + emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym); + } +} + void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, const GlobalVariable *GV, MCSymbol *GVSym) { Index: llvm/test/DebugInfo/COFF/global_visibility.ll =================================================================== --- llvm/test/DebugInfo/COFF/global_visibility.ll +++ llvm/test/DebugInfo/COFF/global_visibility.ll @@ -0,0 +1,279 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s +; +; This test verifies global variables are emitted within the correct scope. +; +; -- global_visibility.cpp ---------------------------------------------------- +; 1 +; 2 int global_int = 0; +; 3 +; 4 template struct A { +; 5 static T comdat_int; +; 6 static T set(T value) { T r = comdat_int; comdat_int = value; return r; }; +; 7 }; +; 8 +; 9 template T A::comdat_int = 42; +; 10 +; 11 void foo() { +; 12 static int local_int = 1; +; 13 { +; 14 static int nested_int = 2; +; 15 local_int = nested_int; +; 16 } +; 17 local_int = A::set(42); +; 18 } +; 19 +; 20 void bar() { +; 21 static int local_int = 3; +; 22 { +; 23 static int nested_int = 4; +; 24 local_int = nested_int; +; 25 } +; 26 local_int = A::set(42); +; 27 } +; 28 +; ----------------------------------------------------------------------------- +; +; $ clang -S -emit-llvm -g -gcodeview global_visibility.cpp +; +; NOTE: The scope for both DIGlobalVariable's named "nested_int" should refer +; to the appropriate DILexicalBlock, not a DISubprogram. +; + +; CHECK: CodeViewDebugInfo [ +; CHECK: Section: .debug$S (9) + +; CHECK: Subsection [ +; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: SubSectionSize: 0x99 +; CHECK: GlobalProcIdSym { +; CHECK: Kind: S_GPROC32_ID (0x1147) +; CHECK: DisplayName: foo +; CHECK: LinkageName: ?foo@@YAXXZ +; CHECK: } +; CHECK: DataSym { +; CHECK: Kind: S_LDATA32 (0x110C) +; CHECK: DisplayName: local_int +; CHECK: LinkageName: ?local_int@?1??foo@@YAXXZ@4HA +; CHECK: } +; CHECK: BlockSym { +; CHECK: Kind: S_BLOCK32 (0x1103) +; CHECK: } +; CHECK: DataSym { +; CHECK: Kind: S_LDATA32 (0x110C) +; CHECK: DisplayName: nested_int +; CHECK: LinkageName: ?nested_int@?1??foo@@YAXXZ@4HA +; CHECK: } +; CHECK: ScopeEndSym { +; CHECK: Kind: S_END (0x6) +; CHECK: } +; CHECK: ProcEnd { +; CHECK: Kind: S_PROC_ID_END (0x114F) +; CHECK: } +; CHECK: ] +; CHECK: Subsection [ +; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: SubSectionSize: 0x99 +; CHECK: GlobalProcIdSym { +; CHECK: Kind: S_GPROC32_ID (0x1147) +; CHECK: DisplayName: bar +; CHECK: LinkageName: ?bar@@YAXXZ +; CHECK: } +; CHECK: DataSym { +; CHECK: Kind: S_LDATA32 (0x110C) +; CHECK: DisplayName: local_int +; CHECK: LinkageName: ?local_int@?1??bar@@YAXXZ@4HA +; CHECK: } +; CHECK: BlockSym { +; CHECK: Kind: S_BLOCK32 (0x1103) +; CHECK: } +; CHECK: DataSym { +; CHECK: Kind: S_LDATA32 (0x110C) +; CHECK: DisplayName: nested_int +; CHECK: LinkageName: ?nested_int@?1??bar@@YAXXZ@4HA +; CHECK: } +; CHECK: ScopeEndSym { +; CHECK: Kind: S_END (0x6) +; CHECK: } +; CHECK: ProcEnd { +; CHECK: Kind: S_PROC_ID_END (0x114F) +; CHECK: } +; CHECK: ] +; CHECK: Subsection [ +; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: SubSectionSize: 0x19 +; CHECK: GlobalData { +; CHECK: Kind: S_GDATA32 (0x110D) +; CHECK: DisplayName: global_int +; CHECK: LinkageName: ?global_int@@3HA +; CHECK: } +; CHECK: ] +; CHECK: ] +; CHECK: CodeViewDebugInfo [ +; CHECK: Section: .debug$S (16) +; CHECK: Subsection [ +; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: GlobalData { +; CHECK: Kind: S_GDATA32 (0x110D) +; CHECK: DisplayName: comdat_int +; CHECK: LinkageName: ?comdat_int@?$A@H@@2HA +; CHECK: } +; CHECK: ] +; CHECK: ] +; CHECK: CodeViewDebugInfo [ +; CHECK: Section: .debug$S (17) +; CHECK: Subsection [ +; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: GlobalData { +; CHECK: Kind: S_GDATA32 (0x110D) +; CHECK: DisplayName: comdat_int +; CHECK: LinkageName: ?comdat_int@?$A@I@@2IA +; CHECK: } +; CHECK: ] +; CHECK: ] +; + +; ModuleID = 'global_visibility.cpp' +source_filename = "global_visibility.cpp" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.15.26730" + +$"?set@?$A@H@@SAHH@Z" = comdat any + +$"?set@?$A@I@@SAII@Z" = comdat any + +$"?comdat_int@?$A@H@@2HA" = comdat any + +$"?comdat_int@?$A@I@@2IA" = comdat any + +@"?global_int@@3HA" = dso_local global i32 0, align 4, !dbg !0 +@"?local_int@?1??foo@@YAXXZ@4HA" = internal global i32 1, align 4, !dbg !6 +@"?nested_int@?1??foo@@YAXXZ@4HA" = internal global i32 2, align 4, !dbg !12 +@"?local_int@?1??bar@@YAXXZ@4HA" = internal global i32 3, align 4, !dbg !14 +@"?nested_int@?1??bar@@YAXXZ@4HA" = internal global i32 4, align 4, !dbg !17 +@"?comdat_int@?$A@H@@2HA" = linkonce_odr dso_local global i32 42, comdat, align 4, !dbg !19 +@"?comdat_int@?$A@I@@2IA" = linkonce_odr dso_local global i32 42, comdat, align 4, !dbg !29 + +; Function Attrs: noinline optnone uwtable +define dso_local void @"?foo@@YAXXZ"() #0 !dbg !8 { +entry: + %0 = load i32, i32* @"?nested_int@?1??foo@@YAXXZ@4HA", align 4, !dbg !45 + store i32 %0, i32* @"?local_int@?1??foo@@YAXXZ@4HA", align 4, !dbg !45 + %call = call i32 @"?set@?$A@H@@SAHH@Z"(i32 42), !dbg !47 + store i32 %call, i32* @"?local_int@?1??foo@@YAXXZ@4HA", align 4, !dbg !47 + ret void, !dbg !48 +} + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr dso_local i32 @"?set@?$A@H@@SAHH@Z"(i32 %value) #1 comdat align 2 !dbg !49 { +entry: + %value.addr = alloca i32, align 4 + %r = alloca i32, align 4 + store i32 %value, i32* %value.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %value.addr, metadata !50, metadata !DIExpression()), !dbg !51 + call void @llvm.dbg.declare(metadata i32* %r, metadata !52, metadata !DIExpression()), !dbg !51 + %0 = load i32, i32* @"?comdat_int@?$A@H@@2HA", align 4, !dbg !51 + store i32 %0, i32* %r, align 4, !dbg !51 + %1 = load i32, i32* %value.addr, align 4, !dbg !51 + store i32 %1, i32* @"?comdat_int@?$A@H@@2HA", align 4, !dbg !51 + %2 = load i32, i32* %r, align 4, !dbg !51 + ret i32 %2, !dbg !51 +} + +; Function Attrs: noinline optnone uwtable +define dso_local void @"?bar@@YAXXZ"() #0 !dbg !16 { +entry: + %0 = load i32, i32* @"?nested_int@?1??bar@@YAXXZ@4HA", align 4, !dbg !53 + store i32 %0, i32* @"?local_int@?1??bar@@YAXXZ@4HA", align 4, !dbg !53 + %call = call i32 @"?set@?$A@I@@SAII@Z"(i32 42), !dbg !55 + store i32 %call, i32* @"?local_int@?1??bar@@YAXXZ@4HA", align 4, !dbg !55 + ret void, !dbg !56 +} + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr dso_local i32 @"?set@?$A@I@@SAII@Z"(i32 %value) #1 comdat align 2 !dbg !57 { +entry: + %value.addr = alloca i32, align 4 + %r = alloca i32, align 4 + store i32 %value, i32* %value.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %value.addr, metadata !58, metadata !DIExpression()), !dbg !59 + call void @llvm.dbg.declare(metadata i32* %r, metadata !60, metadata !DIExpression()), !dbg !59 + %0 = load i32, i32* @"?comdat_int@?$A@I@@2IA", align 4, !dbg !59 + store i32 %0, i32* %r, align 4, !dbg !59 + %1 = load i32, i32* %value.addr, align 4, !dbg !59 + store i32 %1, i32* @"?comdat_int@?$A@I@@2IA", align 4, !dbg !59 + %2 = load i32, i32* %r, align 4, !dbg !59 + ret i32 %2, !dbg !59 +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 + +attributes #0 = { noinline optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone speculatable } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!40, !41, !42, !43} +!llvm.ident = !{!44} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "global_int", linkageName: "?global_int@@3HA", scope: !2, file: !3, line: 2, type: !11, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 8.0.0 (trunk)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "global_visibility.cpp", directory: "C:\5Cpath\5Cto\5Cdirectory", checksumkind: CSK_MD5, checksum: "f59b9e5de12391471b1a61888cb68a3e") +!4 = !{} +!5 = !{!0, !6, !12, !14, !17, !19, !29} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "local_int", scope: !8, file: !3, line: 12, type: !11, isLocal: true, isDefinition: true) +!8 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAXXZ", scope: !3, file: !3, line: 11, type: !9, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression()) +!13 = distinct !DIGlobalVariable(name: "nested_int", scope: !46, file: !3, line: 14, type: !11, isLocal: true, isDefinition: true) +!14 = !DIGlobalVariableExpression(var: !15, expr: !DIExpression()) +!15 = distinct !DIGlobalVariable(name: "local_int", scope: !16, file: !3, line: 21, type: !11, isLocal: true, isDefinition: true) +!16 = distinct !DISubprogram(name: "bar", linkageName: "?bar@@YAXXZ", scope: !3, file: !3, line: 20, type: !9, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4) +!17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) +!18 = distinct !DIGlobalVariable(name: "nested_int", scope: !54, file: !3, line: 23, type: !11, isLocal: true, isDefinition: true) +!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression()) +!20 = distinct !DIGlobalVariable(name: "comdat_int", linkageName: "?comdat_int@?$A@H@@2HA", scope: !2, file: !3, line: 9, type: !11, isLocal: false, isDefinition: true, declaration: !21) +!21 = !DIDerivedType(tag: DW_TAG_member, name: "comdat_int", scope: !22, file: !3, line: 5, baseType: !11, flags: DIFlagStaticMember) +!22 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 4, size: 8, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !23, templateParams: !27, identifier: ".?AU?$A@H@@") +!23 = !{!21, !24} +!24 = !DISubprogram(name: "set", linkageName: "?set@?$A@H@@SAHH@Z", scope: !22, file: !3, line: 6, type: !25, scopeLine: 6, flags: DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!25 = !DISubroutineType(types: !26) +!26 = !{!11, !11} +!27 = !{!28} +!28 = !DITemplateTypeParameter(name: "T", type: !11) +!29 = !DIGlobalVariableExpression(var: !30, expr: !DIExpression()) +!30 = distinct !DIGlobalVariable(name: "comdat_int", linkageName: "?comdat_int@?$A@I@@2IA", scope: !2, file: !3, line: 9, type: !31, isLocal: false, isDefinition: true, declaration: !32) +!31 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!32 = !DIDerivedType(tag: DW_TAG_member, name: "comdat_int", scope: !33, file: !3, line: 5, baseType: !31, flags: DIFlagStaticMember) +!33 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 4, size: 8, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !34, templateParams: !38, identifier: ".?AU?$A@I@@") +!34 = !{!32, !35} +!35 = !DISubprogram(name: "set", linkageName: "?set@?$A@I@@SAII@Z", scope: !33, file: !3, line: 6, type: !36, scopeLine: 6, flags: DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!36 = !DISubroutineType(types: !37) +!37 = !{!31, !31} +!38 = !{!39} +!39 = !DITemplateTypeParameter(name: "T", type: !31) +!40 = !{i32 2, !"CodeView", i32 1} +!41 = !{i32 2, !"Debug Info Version", i32 3} +!42 = !{i32 1, !"wchar_size", i32 2} +!43 = !{i32 7, !"PIC Level", i32 2} +!44 = !{!"clang version 8.0.0 (trunk)"} +!45 = !DILocation(line: 15, scope: !46) +!46 = distinct !DILexicalBlock(scope: !8, file: !3, line: 13) +!47 = !DILocation(line: 17, scope: !8) +!48 = !DILocation(line: 18, scope: !8) +!49 = distinct !DISubprogram(name: "set", linkageName: "?set@?$A@H@@SAHH@Z", scope: !22, file: !3, line: 6, type: !25, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !24, retainedNodes: !4) +!50 = !DILocalVariable(name: "value", arg: 1, scope: !49, file: !3, line: 6, type: !11) +!51 = !DILocation(line: 6, scope: !49) +!52 = !DILocalVariable(name: "r", scope: !49, file: !3, line: 6, type: !11) +!53 = !DILocation(line: 24, scope: !54) +!54 = distinct !DILexicalBlock(scope: !16, file: !3, line: 22) +!55 = !DILocation(line: 26, scope: !16) +!56 = !DILocation(line: 27, scope: !16) +!57 = distinct !DISubprogram(name: "set", linkageName: "?set@?$A@I@@SAII@Z", scope: !33, file: !3, line: 6, type: !36, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !35, retainedNodes: !4) +!58 = !DILocalVariable(name: "value", arg: 1, scope: !57, file: !3, line: 6, type: !31) +!59 = !DILocation(line: 6, scope: !57) +!60 = !DILocalVariable(name: "r", scope: !57, file: !3, line: 6, type: !31) Index: llvm/test/DebugInfo/COFF/type-quals.ll =================================================================== --- llvm/test/DebugInfo/COFF/type-quals.ll +++ llvm/test/DebugInfo/COFF/type-quals.ll @@ -209,28 +209,42 @@ ; CHECK: FunctionType: void (int& __restrict) (0x1011) ; CHECK: Name: g ; CHECK: } -; CHECK: ArgList (0x1013) { +; CHECK: Modifier (0x1013) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: char (0x70) +; CHECK: Modifiers [ (0x1) +; CHECK: Const (0x1) +; CHECK: ] +; CHECK: } +; CHECK: Array (0x1014) { +; CHECK: TypeLeafKind: LF_ARRAY (0x1503) +; CHECK: ElementType: const char (0x1013) +; CHECK: IndexType: unsigned __int64 (0x23) +; CHECK: SizeOf: 4 +; CHECK: Name: +; CHECK: } +; CHECK: ArgList (0x1015) { ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) ; CHECK: NumArgs: 0 ; CHECK: Arguments [ ; CHECK: ] ; CHECK: } -; CHECK: Procedure (0x1014) { +; CHECK: Procedure (0x1016) { ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) ; CHECK: ReturnType: void (0x3) ; CHECK: CallingConvention: NearC (0x0) ; CHECK: FunctionOptions [ (0x0) ; CHECK: ] ; CHECK: NumParameters: 0 -; CHECK: ArgListType: () (0x1013) +; CHECK: ArgListType: () (0x1015) ; CHECK: } -; CHECK: FuncId (0x1015) { +; CHECK: FuncId (0x1017) { ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) ; CHECK: ParentScope: 0x0 -; CHECK: FunctionType: void () (0x1014) +; CHECK: FunctionType: void () (0x1016) ; CHECK: Name: h ; CHECK: } -; CHECK: Struct (0x1016) { +; CHECK: Struct (0x1018) { ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) ; CHECK: MemberCount: 0 ; CHECK: Properties [ (0x180) @@ -243,9 +257,9 @@ ; CHECK: SizeOf: 0 ; CHECK: Name: h::Foo ; CHECK: } -; CHECK: Pointer (0x1017) { +; CHECK: Pointer (0x1019) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: h::Foo (0x1016) +; CHECK: PointeeType: h::Foo (0x1018) ; CHECK: PtrType: Near64 (0xC) ; CHECK: PtrMode: Pointer (0x0) ; CHECK: IsFlat: 0 @@ -255,26 +269,26 @@ ; CHECK: IsRestrict: 0 ; CHECK: SizeOf: 8 ; CHECK: } -; CHECK: ArgList (0x1018) { +; CHECK: ArgList (0x101A) { ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) ; CHECK: NumArgs: 1 ; CHECK: Arguments [ ; CHECK: ArgType: int (0x74) ; CHECK: ] ; CHECK: } -; CHECK: MemberFunction (0x1019) { +; CHECK: MemberFunction (0x101B) { ; CHECK: TypeLeafKind: LF_MFUNCTION (0x1009) ; CHECK: ReturnType: int (0x74) -; CHECK: ClassType: h::Foo (0x1016) -; CHECK: ThisType: h::Foo* const (0x1017) +; CHECK: ClassType: h::Foo (0x1018) +; CHECK: ThisType: h::Foo* const (0x1019) ; CHECK: CallingConvention: NearC (0x0) ; CHECK: FunctionOptions [ (0x0) ; CHECK: ] ; CHECK: NumParameters: 1 -; CHECK: ArgListType: (int) (0x1018) +; CHECK: ArgListType: (int) (0x101A) ; CHECK: ThisAdjustment: 0 ; CHECK: } -; CHECK: FieldList (0x101A) { +; CHECK: FieldList (0x101C) { ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) ; CHECK: DataMember { ; CHECK: TypeLeafKind: LF_MEMBER (0x150D) @@ -286,24 +300,24 @@ ; CHECK: OneMethod { ; CHECK: TypeLeafKind: LF_ONEMETHOD (0x1511) ; CHECK: AccessSpecifier: Public (0x3) -; CHECK: Type: int h::Foo::(int) (0x1019) +; CHECK: Type: int h::Foo::(int) (0x101B) ; CHECK: Name: func ; CHECK: } ; CHECK: } -; CHECK: Struct (0x101B) { +; CHECK: Struct (0x101D) { ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) ; CHECK: MemberCount: 2 ; CHECK: Properties [ (0x100) ; CHECK: Scoped (0x100) ; CHECK: ] -; CHECK: FieldList: (0x101A) +; CHECK: FieldList: (0x101C) ; CHECK: DerivedFrom: 0x0 ; CHECK: VShape: 0x0 ; CHECK: SizeOf: 4 ; CHECK: Name: h::Foo ; CHECK: } -; CHECK: Pointer (0x101D) { +; CHECK: Pointer (0x101F) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) ; CHECK: PointeeType: int (0x74) ; CHECK: PtrType: Near64 (0xC) @@ -314,12 +328,12 @@ ; CHECK: IsUnaligned: 0 ; CHECK: IsRestrict: 1 ; CHECK: SizeOf: 4 -; CHECK: ClassType: h::Foo (0x1016) +; CHECK: ClassType: h::Foo (0x1018) ; CHECK: Representation: SingleInheritanceData (0x1) ; CHECK: } -; CHECK: Pointer (0x101E) { +; CHECK: Pointer (0x1020) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: int h::Foo::(int) (0x1019) +; CHECK: PointeeType: int h::Foo::(int) (0x101B) ; CHECK: PtrType: Near64 (0xC) ; CHECK: PtrMode: PointerToMemberFunction (0x3) ; CHECK: IsFlat: 0 @@ -328,18 +342,18 @@ ; CHECK: IsUnaligned: 0 ; CHECK: IsRestrict: 0 ; CHECK: SizeOf: 8 -; CHECK: ClassType: h::Foo (0x1016) +; CHECK: ClassType: h::Foo (0x1018) ; CHECK: Representation: SingleInheritanceFunction (0x5) ; CHECK: } -; CHECK: MemberFuncId (0x101F) { +; CHECK: MemberFuncId (0x1021) { ; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) -; CHECK: ClassType: h::Foo (0x1016) -; CHECK: FunctionType: int h::Foo::(int) (0x1019) +; CHECK: ClassType: h::Foo (0x1018) +; CHECK: FunctionType: int h::Foo::(int) (0x101B) ; CHECK: Name: func ; CHECK: } -; CHECK: Pointer (0x1020) { +; CHECK: Pointer (0x1022) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: h::Foo (0x1016) +; CHECK: PointeeType: h::Foo (0x1018) ; CHECK: PtrType: Near64 (0xC) ; CHECK: PtrMode: Pointer (0x0) ; CHECK: IsFlat: 0 @@ -349,20 +363,6 @@ ; CHECK: IsRestrict: 0 ; CHECK: SizeOf: 8 ; CHECK: } -; CHECK: Modifier (0x1021) { -; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) -; CHECK: ModifiedType: char (0x70) -; CHECK: Modifiers [ (0x1) -; CHECK: Const (0x1) -; CHECK: ] -; CHECK: } -; CHECK: Array (0x1022) { -; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: const char (0x1021) -; CHECK: IndexType: unsigned __int64 (0x23) -; CHECK: SizeOf: 4 -; CHECK: Name: -; CHECK: } ; CHECK: ] ; CHECK-LABEL: CodeViewDebugInfo [