[llvm] r349777 - [CodeView] Emit global variables within lexical scopes to limit visibility

Brock Wyma via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 20 09:33:45 PST 2018


Author: bwyma
Date: Thu Dec 20 09:33:45 2018
New Revision: 349777

URL: http://llvm.org/viewvc/llvm-project?rev=349777&view=rev
Log:

[CodeView] Emit global variables within lexical scopes to limit visibility

Emit static locals within the correct lexical scope so variables with the same
name will not confuse the debugger into getting the wrong value.

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


Added:
    llvm/trunk/test/DebugInfo/COFF/global_visibility.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
    llvm/trunk/test/DebugInfo/COFF/type-quals.ll

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=349777&r1=349776&r2=349777&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Thu Dec 20 09:33:45 2018
@@ -124,6 +124,8 @@ CodeViewDebug::CodeViewDebug(AsmPrinter
   TheCPU =
       mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch());
 
+  collectGlobalVariableInfo();
+
   // Check if we should emit type record hashes.
   ConstantInt *GH = mdconst::extract_or_null<ConstantInt>(
       MMI->getModule()->getModuleFlag("CodeViewGHash"));
@@ -1038,6 +1040,7 @@ void CodeViewDebug::emitDebugInfoForFunc
     endSymbolRecord(FrameProcEnd);
 
     emitLocalVariableList(FI, FI.Locals);
+    emitGlobalVariableList(FI.Globals);
     emitLexicalBlockList(FI.ChildBlocks, FI);
 
     // Emit inlined call site information. Only emit functions inlined directly
@@ -2046,6 +2049,7 @@ void CodeViewDebug::clear() {
   GlobalUDTs.clear();
   TypeIndices.clear();
   CompleteTypeIndices.clear();
+  ScopeGlobals.clear();
 }
 
 void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
@@ -2648,6 +2652,7 @@ void CodeViewDebug::emitLexicalBlock(con
 
   // 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);
@@ -2661,9 +2666,10 @@ void CodeViewDebug::emitLexicalBlock(con
 void CodeViewDebug::collectLexicalBlockInfo(
         SmallVectorImpl<LexicalScope *> &Scopes,
         SmallVectorImpl<LexicalBlock *> &Blocks,
-        SmallVectorImpl<LocalVariable> &Locals) {
+        SmallVectorImpl<LocalVariable> &Locals,
+        SmallVectorImpl<CVGlobalVariable> &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
@@ -2671,45 +2677,58 @@ void CodeViewDebug::collectLexicalBlockI
 void CodeViewDebug::collectLexicalBlockInfo(
     LexicalScope &Scope,
     SmallVectorImpl<LexicalBlock *> &ParentBlocks,
-    SmallVectorImpl<LocalVariable> &ParentLocals) {
+    SmallVectorImpl<LocalVariable> &ParentLocals,
+    SmallVectorImpl<CVGlobalVariable> &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<LocalVariable> &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<LocalVariable> *Locals =
+      LI != ScopeVariables.end() ? &LI->second : nullptr;
+  auto GI = ScopeGlobals.find(Scope.getScopeNode());
+  SmallVectorImpl<CVGlobalVariable> *Globals =
+      GI != ScopeGlobals.end() ? GI->second.get() : nullptr;
   const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(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<InsnRange> &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;
   }
 
@@ -2720,8 +2739,8 @@ void CodeViewDebug::collectLexicalBlockI
   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;
@@ -2730,9 +2749,15 @@ void CodeViewDebug::collectLexicalBlockI
   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) {
@@ -2744,7 +2769,10 @@ void CodeViewDebug::endFunctionImpl(cons
 
   // 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
@@ -2861,7 +2889,7 @@ void CodeViewDebug::emitDebugInfoForUDTs
   }
 }
 
-void CodeViewDebug::emitDebugInfoForGlobals() {
+void CodeViewDebug::collectGlobalVariableInfo() {
   DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
       GlobalMap;
   for (const GlobalVariable &GV : MMI->getModule()->globals()) {
@@ -2874,42 +2902,56 @@ void CodeViewDebug::emitDebugInfoForGlob
   NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
   for (const MDNode *Node : CUs->operands()) {
     const auto *CU = cast<DICompileUnit>(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<CVGlobalVariable, 1> *VariableList;
+      if (Scope && isa<DILocalScope>(Scope)) {
+        // Locate a global variable list for this scope, creating one if
+        // necessary.
+        auto Insertion = ScopeGlobals.insert(
+            {Scope, std::unique_ptr<GlobalVariableList>()});
+        if (Insertion.second)
+          Insertion.first->second = llvm::make_unique<GlobalVariableList>();
+        VariableList = Insertion.first->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);
   }
 }
 
@@ -2925,6 +2967,15 @@ void CodeViewDebug::emitDebugInfoForReta
   }
 }
 
+// Emit each global variable in the specified array.
+void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> 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) {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=349777&r1=349776&r2=349777&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Thu Dec 20 09:33:45 2018
@@ -99,6 +99,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
     bool UseReferenceType = false;
   };
 
+  struct CVGlobalVariable {
+    const DIGlobalVariable *DIGV;
+    const GlobalVariable *GV;
+  };
+
   struct InlineSite {
     SmallVector<LocalVariable, 1> InlinedLocals;
     SmallVector<const DILocation *, 1> ChildSites;
@@ -112,6 +117,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   // Combines information from DILexicalBlock and LexicalScope.
   struct LexicalBlock {
     SmallVector<LocalVariable, 1> Locals;
+    SmallVector<CVGlobalVariable, 1> Globals;
     SmallVector<LexicalBlock *, 1> Children;
     const MCSymbol *Begin;
     const MCSymbol *End;
@@ -134,6 +140,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
     SmallVector<const DILocation *, 1> ChildSites;
 
     SmallVector<LocalVariable, 1> Locals;
+    SmallVector<CVGlobalVariable, 1> Globals;
 
     std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks;
 
@@ -183,6 +190,17 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   // and LexicalBlocks.
   DenseMap<const LexicalScope *, SmallVector<LocalVariable, 1>> ScopeVariables;
 
+  // Map to separate global variables according to the lexical scope they
+  // belong in. A null local scope represents the global scope.
+  typedef SmallVector<CVGlobalVariable, 1> GlobalVariableList;
+  DenseMap<const DIScope*, std::unique_ptr<GlobalVariableList> > ScopeGlobals;
+
+  // Array of global variables which  need to be emitted into a COMDAT section.
+  SmallVector<CVGlobalVariable, 1> ComdatVariables;
+
+  // Array of non-COMDAT global variables.
+  SmallVector<CVGlobalVariable, 1> 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 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
 
   void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
 
-  void emitDebugInfoForGlobals();
-
   void emitDebugInfoForRetainedTypes();
 
   void
   emitDebugInfoForUDTs(ArrayRef<std::pair<std::string, const DIType *>> UDTs);
 
+  void emitDebugInfoForGlobals();
+  void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals);
   void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
                               const GlobalVariable *GV, MCSymbol *GVSym);
 
@@ -319,6 +337,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
 
   using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
 
+  void collectGlobalVariableInfo();
   void collectVariableInfo(const DISubprogram *SP);
 
   void collectVariableInfoFromMFTable(DenseSet<InlinedEntity> &Processed);
@@ -327,10 +346,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   // scopes, and populate it with local variables.
   void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes,
                                SmallVectorImpl<LexicalBlock *> &Blocks,
-                               SmallVectorImpl<LocalVariable> &Locals);
+                               SmallVectorImpl<LocalVariable> &Locals,
+                               SmallVectorImpl<CVGlobalVariable> &Globals);
   void collectLexicalBlockInfo(LexicalScope &Scope,
                                SmallVectorImpl<LexicalBlock *> &ParentBlocks,
-                               SmallVectorImpl<LocalVariable> &ParentLocals);
+                               SmallVectorImpl<LocalVariable> &ParentLocals,
+                               SmallVectorImpl<CVGlobalVariable> &ParentGlobals);
 
   /// Records information about a local variable in the appropriate scope. In
   /// particular, locals from inlined code live inside the inlining site.

Added: llvm/trunk/test/DebugInfo/COFF/global_visibility.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/global_visibility.ll?rev=349777&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/global_visibility.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/global_visibility.ll Thu Dec 20 09:33:45 2018
@@ -0,0 +1,276 @@
+; 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 <typename T> 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 <typename T> T A<T>::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<int>::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<unsigned>::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:     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 at 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 at 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:     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 at 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 at 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:     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 at 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 at 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 at H@@SAHH at Z" = comdat any
+
+$"?set@?$A at I@@SAII at Z" = comdat any
+
+$"?comdat_int@?$A at H@@2HA" = comdat any
+
+$"?comdat_int@?$A at I@@2IA" = comdat any
+
+@"?global_int@@3HA" = dso_local global i32 0, align 4, !dbg !0
+@"?local_int@?1??foo@@YAXXZ at 4HA" = internal global i32 1, align 4, !dbg !6
+@"?nested_int@?1??foo@@YAXXZ at 4HA" = internal global i32 2, align 4, !dbg !12
+@"?local_int@?1??bar@@YAXXZ at 4HA" = internal global i32 3, align 4, !dbg !14
+@"?nested_int@?1??bar@@YAXXZ at 4HA" = internal global i32 4, align 4, !dbg !17
+@"?comdat_int@?$A at H@@2HA" = linkonce_odr dso_local global i32 42, comdat, align 4, !dbg !19
+@"?comdat_int@?$A at 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 at 4HA", align 4, !dbg !45
+  store i32 %0, i32* @"?local_int@?1??foo@@YAXXZ at 4HA", align 4, !dbg !45
+  %call = call i32 @"?set@?$A at H@@SAHH at Z"(i32 42), !dbg !47
+  store i32 %call, i32* @"?local_int@?1??foo@@YAXXZ at 4HA", align 4, !dbg !47
+  ret void, !dbg !48
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define linkonce_odr dso_local i32 @"?set@?$A at H@@SAHH at 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 at 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 at 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 at 4HA", align 4, !dbg !53
+  store i32 %0, i32* @"?local_int@?1??bar@@YAXXZ at 4HA", align 4, !dbg !53
+  %call = call i32 @"?set@?$A at I@@SAII at Z"(i32 42), !dbg !55
+  store i32 %call, i32* @"?local_int@?1??bar@@YAXXZ at 4HA", align 4, !dbg !55
+  ret void, !dbg !56
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define linkonce_odr dso_local i32 @"?set@?$A at I@@SAII at 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 at 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 at 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 at 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<int>", file: !3, line: 4, size: 8, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !23, templateParams: !27, identifier: ".?AU?$A at H@@")
+!23 = !{!21, !24}
+!24 = !DISubprogram(name: "set", linkageName: "?set@?$A at H@@SAHH at 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 at 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<unsigned int>", file: !3, line: 4, size: 8, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !34, templateParams: !38, identifier: ".?AU?$A at I@@")
+!34 = !{!32, !35}
+!35 = !DISubprogram(name: "set", linkageName: "?set@?$A at I@@SAII at 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 at H@@SAHH at 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 at I@@SAII at 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)

Modified: llvm/trunk/test/DebugInfo/COFF/type-quals.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/type-quals.ll?rev=349777&r1=349776&r2=349777&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/type-quals.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/type-quals.ll Thu Dec 20 09:33:45 2018
@@ -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: <field list> (0x101A)
+; CHECK:     FieldList: <field list> (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 [




More information about the llvm-commits mailing list