[llvm] r260746 - [codeview] Describe local variables in registers

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 12 13:48:31 PST 2016


Author: rnk
Date: Fri Feb 12 15:48:30 2016
New Revision: 260746

URL: http://llvm.org/viewvc/llvm-project?rev=260746&view=rev
Log:
[codeview] Describe local variables in registers

Added:
    llvm/trunk/test/DebugInfo/COFF/register-variables.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=260746&r1=260745&r2=260746&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Fri Feb 12 15:48:30 2016
@@ -105,18 +105,32 @@ unsigned CodeViewDebug::maybeRecordFile(
   return Insertion.first->second;
 }
 
-CodeViewDebug::InlineSite &CodeViewDebug::getInlineSite(const DILocation *Loc) {
-  const DILocation *InlinedAt = Loc->getInlinedAt();
+CodeViewDebug::InlineSite &
+CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
+                             const DISubprogram *Inlinee) {
   auto Insertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
   InlineSite *Site = &Insertion.first->second;
   if (Insertion.second) {
     Site->SiteFuncId = NextFuncId++;
-    Site->Inlinee = Loc->getScope()->getSubprogram();
-    InlinedSubprograms.insert(Loc->getScope()->getSubprogram());
+    Site->Inlinee = Inlinee;
+    InlinedSubprograms.insert(Inlinee);
   }
   return *Site;
 }
 
+void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
+                                        const DILocation *InlinedAt) {
+  if (InlinedAt) {
+    // This variable was inlined. Associate it with the InlineSite.
+    const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
+    InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
+    Site.InlinedLocals.emplace_back(Var);
+  } else {
+    // This variable goes in the main ProcSym.
+    CurFn->Locals.emplace_back(Var);
+  }
+}
+
 static void addLocIfNotPresent(SmallVectorImpl<const DILocation *> &Locs,
                                const DILocation *Loc) {
   auto B = Locs.begin(), E = Locs.end();
@@ -154,18 +168,19 @@ void CodeViewDebug::maybeRecordLocation(
   CurFn->LastLoc = DL;
 
   unsigned FuncId = CurFn->FuncId;
-  if (DL->getInlinedAt()) {
+  if (const DILocation *SiteLoc = DL->getInlinedAt()) {
     const DILocation *Loc = DL.get();
 
     // If this location was actually inlined from somewhere else, give it the ID
     // of the inline call site.
-    FuncId = getInlineSite(Loc).SiteFuncId;
+    FuncId =
+        getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
 
     // Ensure we have links in the tree of inline call sites.
-    const DILocation *SiteLoc;
     bool FirstLoc = true;
     while ((SiteLoc = Loc->getInlinedAt())) {
-      InlineSite &Site = getInlineSite(Loc);
+      InlineSite &Site =
+          getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
       if (!FirstLoc)
         addLocIfNotPresent(Site.ChildSites, Loc);
       FirstLoc = false;
@@ -477,45 +492,148 @@ void CodeViewDebug::emitDebugInfoForFunc
   OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
 }
 
-void CodeViewDebug::collectVariableInfoFromMMITable() {
-  for (const auto &VI : MMI->getVariableDbgInfo()) {
+CodeViewDebug::LocalVarDefRange
+CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
+  LocalVarDefRange DR;
+  DR.InMemory = 1;
+  DR.DataOffset = Offset;
+  assert(DR.DataOffset == Offset && "truncation");
+  DR.StructOffset = 0;
+  DR.CVRegister = CVRegister;
+  return DR;
+}
+
+CodeViewDebug::LocalVarDefRange
+CodeViewDebug::createDefRangeReg(uint16_t CVRegister) {
+  LocalVarDefRange DR;
+  DR.InMemory = 0;
+  DR.DataOffset = 0;
+  DR.StructOffset = 0;
+  DR.CVRegister = CVRegister;
+  return DR;
+}
+
+void CodeViewDebug::collectVariableInfoFromMMITable(
+    DenseSet<InlinedVariable> &Processed) {
+  const TargetSubtargetInfo &TSI = Asm->MF->getSubtarget();
+  const TargetFrameLowering *TFI = TSI.getFrameLowering();
+  const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
+
+  for (const MachineModuleInfo::VariableDbgInfo &VI :
+       MMI->getVariableDbgInfo()) {
     if (!VI.Var)
       continue;
     assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
            "Expected inlined-at fields to agree");
 
+    Processed.insert(InlinedVariable(VI.Var, VI.Loc->getInlinedAt()));
     LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
 
     // If variable scope is not found then skip this variable.
     if (!Scope)
       continue;
 
-    LocalVariable Var;
-    Var.DIVar = VI.Var;
-
     // Get the frame register used and the offset.
     unsigned FrameReg = 0;
-    const TargetSubtargetInfo &TSI = Asm->MF->getSubtarget();
-    const TargetFrameLowering *TFI = TSI.getFrameLowering();
-    const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
-    Var.RegisterOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg);
-    Var.CVRegister = TRI->getCodeViewRegNum(FrameReg);
+    int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg);
+    uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);
 
     // Calculate the label ranges.
+    LocalVarDefRange DefRange = createDefRangeMem(CVReg, FrameOffset);
     for (const InsnRange &Range : Scope->getRanges()) {
       const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
       const MCSymbol *End = getLabelAfterInsn(Range.second);
-      Var.Ranges.push_back({Begin, End});
+      End = End ? End : Asm->getFunctionEnd();
+      DefRange.Ranges.emplace_back(Begin, End);
     }
 
-    if (VI.Loc->getInlinedAt()) {
-      // This variable was inlined. Associate it with the InlineSite.
-      InlineSite &Site = getInlineSite(VI.Loc);
-      Site.InlinedLocals.emplace_back(std::move(Var));
-    } else {
-      // This variable goes in the main ProcSym.
-      CurFn->Locals.emplace_back(std::move(Var));
+    LocalVariable Var;
+    Var.DIVar = VI.Var;
+    Var.DefRanges.emplace_back(std::move(DefRange));
+    recordLocalVariable(std::move(Var), VI.Loc->getInlinedAt());
+  }
+}
+
+void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
+  DenseSet<InlinedVariable> Processed;
+  // Grab the variable info that was squirreled away in the MMI side-table.
+  collectVariableInfoFromMMITable(Processed);
+
+  const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();
+
+  for (const auto &I : DbgValues) {
+    InlinedVariable IV = I.first;
+    if (Processed.count(IV))
+      continue;
+    const DILocalVariable *DIVar = IV.first;
+    const DILocation *InlinedAt = IV.second;
+
+    // Instruction ranges, specifying where IV is accessible.
+    const auto &Ranges = I.second;
+
+    LexicalScope *Scope = nullptr;
+    if (InlinedAt)
+      Scope = LScopes.findInlinedScope(DIVar->getScope(), InlinedAt);
+    else
+      Scope = LScopes.findLexicalScope(DIVar->getScope());
+    // If variable scope is not found then skip this variable.
+    if (!Scope)
+      continue;
+
+    LocalVariable Var;
+    Var.DIVar = DIVar;
+
+    // Calculate the definition ranges.
+    for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
+      const InsnRange &Range = *I;
+      const MachineInstr *DVInst = Range.first;
+      assert(DVInst->isDebugValue() && "Invalid History entry");
+      const DIExpression *DIExpr = DVInst->getDebugExpression();
+
+      // Bail if there is a complex DWARF expression for now.
+      if (DIExpr && DIExpr->getNumElements() > 0)
+        continue;
+
+      // Handle the two cases we can handle: indirect in memory and in register.
+      bool IsIndirect = DVInst->getOperand(1).isImm();
+      unsigned CVReg = TRI->getCodeViewRegNum(DVInst->getOperand(0).getReg());
+      {
+        LocalVarDefRange DefRange;
+        if (IsIndirect) {
+          int64_t Offset = DVInst->getOperand(1).getImm();
+          DefRange = createDefRangeMem(CVReg, Offset);
+        } else {
+          DefRange = createDefRangeReg(CVReg);
+        }
+        if (Var.DefRanges.empty() ||
+            Var.DefRanges.back().isDifferentLocation(DefRange)) {
+          Var.DefRanges.emplace_back(std::move(DefRange));
+        }
+      }
+
+      // Compute the label range.
+      const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
+      const MCSymbol *End = getLabelAfterInsn(Range.second);
+      if (!End) {
+        if (std::next(I) != E)
+          End = getLabelBeforeInsn(std::next(I)->first);
+        else
+          End = Asm->getFunctionEnd();
+      }
+
+      // If the last range end is our begin, just extend the last range.
+      // Otherwise make a new range.
+      SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &Ranges =
+          Var.DefRanges.back().Ranges;
+      if (!Ranges.empty() && Ranges.back().second == Begin)
+        Ranges.back().second = End;
+      else
+        Ranges.emplace_back(Begin, End);
+
+      // FIXME: Do more range combining.
     }
+
+    recordLocalVariable(std::move(Var), InlinedAt);
   }
 }
 
@@ -572,6 +690,8 @@ void CodeViewDebug::emitLocalVariable(co
   uint16_t Flags = 0;
   if (Var.DIVar->isParameter())
     Flags |= LocalSym::IsParameter;
+  if (Var.DefRanges.empty())
+    Flags |= LocalSym::IsOptimizedOut;
 
   OS.AddComment("TypeIndex");
   OS.EmitIntValue(TypeIndex::Int32().getIndex(), 4);
@@ -580,28 +700,42 @@ void CodeViewDebug::emitLocalVariable(co
   emitNullTerminatedString(OS, Var.DIVar->getName());
   OS.EmitLabel(LocalEnd);
 
-  // DefRangeRegisterRelSym record, see SymbolRecord.h for more info.  Omit the
-  // LocalVariableAddrRange field from the record. The directive will emit that.
-  DefRangeRegisterRelSym Sym{};
-  ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
-  Sym.BaseRegister = Var.CVRegister;
-  Sym.Flags = 0; // Unclear what matters here.
-  Sym.BasePointerOffset = Var.RegisterOffset;
-  SmallString<sizeof(Sym) + sizeof(SymKind) - sizeof(LocalVariableAddrRange)>
-      BytePrefix;
-  BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind),
-                          sizeof(SymKind));
-  BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
-                          sizeof(Sym) - sizeof(LocalVariableAddrRange));
+  // Calculate the on disk prefix of the appropriate def range record. The
+  // records and on disk formats are described in SymbolRecords.h. BytePrefix
+  // should be big enough to hold all forms without memory allocation.
+  SmallString<20> BytePrefix;
+  for (const LocalVarDefRange &DefRange : Var.DefRanges) {
+    BytePrefix.clear();
+    // FIXME: Handle bitpieces.
+    if (DefRange.StructOffset != 0)
+      continue;
 
-  OS.EmitCVDefRangeDirective(Var.Ranges, BytePrefix);
+    if (DefRange.InMemory) {
+      DefRangeRegisterRelSym Sym{};
+      ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
+      Sym.BaseRegister = DefRange.CVRegister;
+      Sym.Flags = 0; // Unclear what matters here.
+      Sym.BasePointerOffset = DefRange.DataOffset;
+      BytePrefix +=
+          StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
+      BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
+                              sizeof(Sym) - sizeof(LocalVariableAddrRange));
+    } else {
+      assert(DefRange.DataOffset == 0 && "unexpected offset into register");
+      DefRangeRegisterSym Sym{};
+      ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER);
+      Sym.Register = DefRange.CVRegister;
+      Sym.MayHaveNoName = 0; // Unclear what matters here.
+      BytePrefix +=
+          StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
+      BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
+                              sizeof(Sym) - sizeof(LocalVariableAddrRange));
+    }
+    OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix);
+  }
 }
 
 void CodeViewDebug::endFunction(const MachineFunction *MF) {
-  collectVariableInfoFromMMITable();
-
-  DebugHandlerBase::endFunction(MF);
-
   if (!Asm || !CurFn)  // We haven't created any debug info for this function.
     return;
 
@@ -609,6 +743,10 @@ void CodeViewDebug::endFunction(const Ma
   assert(FnDebugInfo.count(GV));
   assert(CurFn == &FnDebugInfo[GV]);
 
+  collectVariableInfo(getDISubprogram(GV));
+
+  DebugHandlerBase::endFunction(MF);
+
   // Don't emit anything if we don't have any line tables.
   if (!CurFn->HaveLineInfo) {
     FnDebugInfo.erase(GV);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=260746&r1=260745&r2=260746&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Fri Feb 12 15:48:30 2016
@@ -35,13 +35,40 @@ class LexicalScope;
 class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
   MCStreamer &OS;
 
+  /// Represents the most general definition range.
+  struct LocalVarDefRange {
+    /// Indicates that variable data is stored in memory relative to the
+    /// specified register.
+    int InMemory : 1;
+
+    /// Offset of variable data in memory.
+    int DataOffset : 31;
+
+    /// Offset of the data into the user level struct. If zero, no splitting
+    /// occurred.
+    uint16_t StructOffset;
+
+    /// Register containing the data or the register base of the memory
+    /// location containing the data.
+    uint16_t CVRegister;
+
+    /// Compares all location fields. This includes all fields except the label
+    /// ranges.
+    bool isDifferentLocation(LocalVarDefRange &O) {
+      return InMemory != O.InMemory || DataOffset != O.DataOffset ||
+             StructOffset != O.StructOffset || CVRegister != O.CVRegister;
+    }
+
+    SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 1> Ranges;
+  };
+
+  static LocalVarDefRange createDefRangeMem(uint16_t CVRegister, int Offset);
+  static LocalVarDefRange createDefRangeReg(uint16_t CVRegister);
+
   /// Similar to DbgVariable in DwarfDebug, but not dwarf-specific.
   struct LocalVariable {
     const DILocalVariable *DIVar = nullptr;
-    SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 1> Ranges;
-    unsigned CVRegister = 0;
-    int RegisterOffset = 0;
-    // FIXME: Add support for DIExpressions.
+    SmallVector<LocalVarDefRange, 1> DefRanges;
   };
 
   struct InlineSite {
@@ -74,7 +101,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
 
   unsigned NextFuncId = 0;
 
-  InlineSite &getInlineSite(const DILocation *Loc);
+  InlineSite &getInlineSite(const DILocation *InlinedAt,
+                            const DISubprogram *Inlinee);
 
   static void collectInlineSiteChildren(SmallVectorImpl<unsigned> &Children,
                                         const FunctionInfo &FI,
@@ -123,7 +151,15 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
                            const InlineSite &Site);
 
-  void collectVariableInfoFromMMITable();
+  typedef DbgValueHistoryMap::InlinedVariable InlinedVariable;
+
+  void collectVariableInfo(const DISubprogram *SP);
+
+  void collectVariableInfoFromMMITable(DenseSet<InlinedVariable> &Processed);
+
+  /// Records information about a local variable in the appropriate scope. In
+  /// particular, locals from inlined code live inside the inlining site.
+  void recordLocalVariable(LocalVariable &&Var, const DILocation *Loc);
 
   void emitLocalVariable(const LocalVariable &Var);
 

Added: llvm/trunk/test/DebugInfo/COFF/register-variables.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/register-variables.ll?rev=260746&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/register-variables.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/register-variables.ll Fri Feb 12 15:48:30 2016
@@ -0,0 +1,291 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc < %s -filetype=obj | llvm-readobj -codeview - | FileCheck %s --check-prefix=OBJ
+
+; Generated from:
+; volatile int x;
+; int getint(void);
+; void putint(int);
+; static inline int inlineinc(int a) {
+;   int b = a + 1;
+;   ++x;
+;   return b;
+; }
+; void f(int p) {
+;   if (p) {
+;     int a = getint();
+;     int b = inlineinc(a);
+;     putint(b);
+;   } else {
+;     int c = getint();
+;     putint(c);
+;   }
+; }
+
+; ASM: f:                                      # @f
+; ASM: .Lfunc_begin0:
+; ASM: # BB#0:                                 # %entry
+; ASM:         pushq   %rsi
+; ASM:         subq    $32, %rsp
+; ASM:         #DEBUG_VALUE: f:p <- %ECX
+; ASM:         movl    %ecx, %esi
+; ASM: [[p_ecx_esi:\.Ltmp.*]]:
+; ASM:         #DEBUG_VALUE: f:p <- %ESI
+; ASM:         callq   getint
+; ASM: [[after_getint:\.Ltmp.*]]:
+; ASM:         #DEBUG_VALUE: a <- %EAX
+; ASM:         #DEBUG_VALUE: inlineinc:a <- %EAX
+; ASM:         #DEBUG_VALUE: c <- %EAX
+; ASM:         testl   %esi, %esi
+; ASM:         je      .LBB0_2
+; ASM: # BB#1:                                 # %if.then
+; ASM:         #DEBUG_VALUE: c <- %EAX
+; ASM:         #DEBUG_VALUE: inlineinc:a <- %EAX
+; ASM:         #DEBUG_VALUE: a <- %EAX
+; ASM:         #DEBUG_VALUE: f:p <- %ESI
+; ASM:         incl    %eax
+; ASM: [[after_inc_eax:\.Ltmp.*]]:
+; ASM:         #DEBUG_VALUE: inlineinc:b <- %EAX
+; ASM:         #DEBUG_VALUE: b <- %EAX
+; ASM:         incl    x(%rip)
+; ASM: [[after_if:\.Ltmp.*]]:
+; ASM: .LBB0_2:                                # %if.else
+; ASM:         #DEBUG_VALUE: f:p <- %ESI
+; ASM:         movl    %eax, %ecx
+; ASM:         addq    $32, %rsp
+; ASM:         popq    %rsi
+; ASM: [[func_end:\.Ltmp.*]]:
+; ASM:         rex64 jmp       putint          # TAILCALL
+
+; ASM:         .short  4414                    # Record kind: S_LOCAL
+; ASM:         .asciz  "p"
+; ASM:         .cv_def_range    .Lfunc_begin0 [[p_ecx_esi]], "A\021\022\000\000\000"
+; ASM:         .cv_def_range    [[p_ecx_esi]] [[func_end]], "A\021\027\000\000\000"
+; ASM:         .short  4414                    # Record kind: S_LOCAL
+; ASM:         .asciz  "a"
+; ASM:         .cv_def_range    [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000"
+; ASM:         .short  4414                    # Record kind: S_LOCAL
+; ASM:         .asciz  "c"
+; ASM:         .cv_def_range    [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000"
+; ASM:         .short  4414                    # Record kind: S_LOCAL
+; ASM:         .asciz  "b"
+; ASM:         .cv_def_range    [[after_inc_eax]] [[after_if]], "A\021\021\000\000\000"
+
+; ASM:         .short  4429                    # Record kind: S_INLINESITE
+; ASM:         .short  4414                    # Record kind: S_LOCAL
+; ASM:         .asciz  "a"
+; ASM:         .cv_def_range    [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000"
+; ASM:         .short  4414                    # Record kind: S_LOCAL
+; ASM:         .asciz  "b"
+; ASM:         .cv_def_range    [[after_inc_eax]] [[after_if]], "A\021\021\000\000\000"
+; ASM:         .short  4430                    # Record kind: S_INLINESITE_END
+
+; OBJ: Subsection [
+; OBJ:   SubSectionType: Symbols (0xF1)
+; OBJ:   ProcStart {
+; OBJ:     DisplayName: f
+; OBJ:   }
+; OBJ:   Local {
+; OBJ:     Type: int (0x74)
+; OBJ:     Flags [ (0x1)
+; OBJ:       IsParameter (0x1)
+; OBJ:     ]
+; OBJ:     VarName: p
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 18
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0x0
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x7
+; OBJ:     }
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 23
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0x7
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x18
+; OBJ:     }
+; OBJ:   }
+; OBJ:   Local {
+; OBJ:     Type: int (0x74)
+; OBJ:     Flags [ (0x0)
+; OBJ:     ]
+; OBJ:     VarName: a
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 17
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0xC
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x6
+; OBJ:     }
+; OBJ:   }
+; OBJ:   Local {
+; OBJ:     Type: int (0x74)
+; OBJ:     Flags [ (0x0)
+; OBJ:     ]
+; OBJ:     VarName: c
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 17
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0xC
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x6
+; OBJ:     }
+; OBJ:   }
+; OBJ:   Local {
+; OBJ:     Type: int (0x74)
+; OBJ:     Flags [ (0x0)
+; OBJ:     ]
+; OBJ:     VarName: b
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 17
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0x12
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x6
+; OBJ:     }
+; OBJ:   }
+; OBJ:   InlineSite {
+; OBJ:     PtrParent: 0x0
+; OBJ:     PtrEnd: 0x0
+; OBJ:     Inlinee: inlineinc (0x1003)
+; OBJ:   }
+; OBJ:   Local {
+; OBJ:     Type: int (0x74)
+; OBJ:     Flags [ (0x1)
+; OBJ:       IsParameter (0x1)
+; OBJ:     ]
+; OBJ:     VarName: a
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 17
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0xC
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x6
+; OBJ:     }
+; OBJ:   }
+; OBJ:   Local {
+; OBJ:     Type: int (0x74)
+; OBJ:     Flags [ (0x0)
+; OBJ:     ]
+; OBJ:     VarName: b
+; OBJ:   }
+; OBJ:   DefRangeRegister {
+; OBJ:     Register: 17
+; OBJ:     LocalVariableAddrRange {
+; OBJ:       OffsetStart: .text+0x12
+; OBJ:       ISectStart: 0x0
+; OBJ:       Range: 0x6
+; OBJ:     }
+; OBJ:   }
+; OBJ:   InlineSiteEnd {
+; OBJ:   }
+; OBJ:   ProcEnd
+; OBJ: ]
+
+; ModuleID = 't.cpp'
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+ at x = internal global i32 0, align 4
+
+; Function Attrs: nounwind uwtable
+define void @f(i32 %p) #0 !dbg !4 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 %p, i64 0, metadata !9, metadata !29), !dbg !30
+  %tobool = icmp eq i32 %p, 0, !dbg !31
+  %call2 = tail call i32 @getint() #3, !dbg !32
+  br i1 %tobool, label %if.else, label %if.then, !dbg !33
+
+if.then:                                          ; preds = %entry
+  tail call void @llvm.dbg.value(metadata i32 %call2, i64 0, metadata !10, metadata !29), !dbg !34
+  tail call void @llvm.dbg.value(metadata i32 %call2, i64 0, metadata !20, metadata !29), !dbg !35
+  %add.i = add nsw i32 %call2, 1, !dbg !37
+  tail call void @llvm.dbg.value(metadata i32 %add.i, i64 0, metadata !21, metadata !29), !dbg !38
+  %0 = load volatile i32, i32* @x, align 4, !dbg !39, !tbaa !40
+  %inc.i = add nsw i32 %0, 1, !dbg !39
+  store volatile i32 %inc.i, i32* @x, align 4, !dbg !39, !tbaa !40
+  tail call void @llvm.dbg.value(metadata i32 %add.i, i64 0, metadata !13, metadata !29), !dbg !44
+  tail call void @putint(i32 %add.i) #3, !dbg !45
+  br label %if.end, !dbg !46
+
+if.else:                                          ; preds = %entry
+  tail call void @llvm.dbg.value(metadata i32 %call2, i64 0, metadata !14, metadata !29), !dbg !47
+  tail call void @putint(i32 %call2) #3, !dbg !48
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void, !dbg !49
+}
+
+declare i32 @getint() #1
+
+declare void @putint(i32) #1
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
+
+attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!25, !26, !27}
+!llvm.ident = !{!28}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 260617) (llvm/trunk 260619)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3, globals: !22)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!3 = !{!4, !16}
+!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 9, type: !5, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true, variables: !8)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null, !7}
+!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !{!9, !10, !13, !14}
+!9 = !DILocalVariable(name: "p", arg: 1, scope: !4, file: !1, line: 9, type: !7)
+!10 = !DILocalVariable(name: "a", scope: !11, file: !1, line: 11, type: !7)
+!11 = distinct !DILexicalBlock(scope: !12, file: !1, line: 10, column: 10)
+!12 = distinct !DILexicalBlock(scope: !4, file: !1, line: 10, column: 7)
+!13 = !DILocalVariable(name: "b", scope: !11, file: !1, line: 12, type: !7)
+!14 = !DILocalVariable(name: "c", scope: !15, file: !1, line: 15, type: !7)
+!15 = distinct !DILexicalBlock(scope: !12, file: !1, line: 14, column: 10)
+!16 = distinct !DISubprogram(name: "inlineinc", scope: !1, file: !1, line: 4, type: !17, isLocal: true, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: true, variables: !19)
+!17 = !DISubroutineType(types: !18)
+!18 = !{!7, !7}
+!19 = !{!20, !21}
+!20 = !DILocalVariable(name: "a", arg: 1, scope: !16, file: !1, line: 4, type: !7)
+!21 = !DILocalVariable(name: "b", scope: !16, file: !1, line: 5, type: !7)
+!22 = !{!23}
+!23 = !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 1, type: !24, isLocal: false, isDefinition: true, variable: i32* @x)
+!24 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
+!25 = !{i32 2, !"CodeView", i32 1}
+!26 = !{i32 2, !"Debug Info Version", i32 3}
+!27 = !{i32 1, !"PIC Level", i32 2}
+!28 = !{!"clang version 3.9.0 (trunk 260617) (llvm/trunk 260619)"}
+!29 = !DIExpression()
+!30 = !DILocation(line: 9, column: 12, scope: !4)
+!31 = !DILocation(line: 10, column: 7, scope: !12)
+!32 = !DILocation(line: 15, column: 13, scope: !15)
+!33 = !DILocation(line: 10, column: 7, scope: !4)
+!34 = !DILocation(line: 11, column: 9, scope: !11)
+!35 = !DILocation(line: 4, column: 33, scope: !16, inlinedAt: !36)
+!36 = distinct !DILocation(line: 12, column: 13, scope: !11)
+!37 = !DILocation(line: 5, column: 13, scope: !16, inlinedAt: !36)
+!38 = !DILocation(line: 5, column: 7, scope: !16, inlinedAt: !36)
+!39 = !DILocation(line: 6, column: 3, scope: !16, inlinedAt: !36)
+!40 = !{!41, !41, i64 0}
+!41 = !{!"int", !42, i64 0}
+!42 = !{!"omnipotent char", !43, i64 0}
+!43 = !{!"Simple C/C++ TBAA"}
+!44 = !DILocation(line: 12, column: 9, scope: !11)
+!45 = !DILocation(line: 13, column: 5, scope: !11)
+!46 = !DILocation(line: 14, column: 3, scope: !11)
+!47 = !DILocation(line: 15, column: 9, scope: !15)
+!48 = !DILocation(line: 16, column: 5, scope: !15)
+!49 = !DILocation(line: 18, column: 1, scope: !4)




More information about the llvm-commits mailing list