[llvm] r311957 - [codeview] support more DW_OPs for more complete debug info

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 28 17:19:58 PDT 2017


On Mon, Aug 28, 2017 at 5:08 PM Bob Haarman via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: inglorion
> Date: Mon Aug 28 17:06:59 2017
> New Revision: 311957
>
> URL: http://llvm.org/viewvc/llvm-project?rev=311957&view=rev
> Log:
> [codeview] support more DW_OPs for more complete debug info
>
> Summary:
> Some variables show up in Visual Studio as "optimized out" even in -O0
> -Od builds. This change fixes two issues that would cause this to
> happen. The first issue is that not all DIExpressions we generate were
> recognized by the CodeView writer. This has been addressed by adding
> support for DW_OP_constu, DW_OP_minus, and DW_OP_plus. The second
> issue is that we had no way to encode DW_OP_deref in CodeView. We get
> around that by changinge the type we encode in the debug info to be
> a reference to the type in the source code.
>

I've seen this done before & would really advise against it - this was
originally how LLVM handled non-trivial pass-by-value (where the actual ABI
parameter is a pointer - it would encode the parameter type as T& instead
of T). That caused some problems.

What does MSVC do in this sort of situation?


>
> This fixes PR34261.
>
> Reviewers: aprantl, rnk, zturner
>
> Reviewed By: rnk
>
> Subscribers: mgorny, llvm-commits, aprantl, hiraditya
>
> Differential Revision: https://reviews.llvm.org/D36907
>
> Added:
>     llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir
> Modified:
>     llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
>     llvm/trunk/test/DebugInfo/COFF/pieces.ll
>     llvm/trunk/test/DebugInfo/COFF/types-array-advanced.ll
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=311957&r1=311956&r2=311957&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Mon Aug 28
> 17:06:59 2017
> @@ -949,13 +949,103 @@ void CodeViewDebug::collectVariableInfoF
>    }
>  }
>
> +void CodeViewDebug::calculateRanges(
> +    LocalVariable &Var, const DbgValueHistoryMap::InstrRanges &Ranges) {
> +  const TargetRegisterInfo *TRI =
> Asm->MF->getSubtarget().getRegisterInfo();
> +
> +  // 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");
> +    // FIXME: Find a way to represent constant variables, since they are
> +    // relatively common.
> +    DbgVariableLocation Location;
> +    bool Supported =
> +        DbgVariableLocation::extractFromMachineInstruction(Location,
> *DVInst);
> +
> +    // Because we cannot express DW_OP_deref in CodeView directly,
> +    // we use a trick: we encode the type as a reference to the
> +    // real type.
> +    if (Var.Deref) {
> +      // When we're encoding the type as a reference to the original type,
> +      // we need to remove a level of indirection from incoming locations.
> +      // E.g. [RSP+8] with DW_OP_deref becomes [RSP+8],
> +      // and [RCX+0] without DW_OP_deref becomes RCX.
> +      if (!Location.Deref) {
> +        if (Location.InMemory)
> +          Location.InMemory = false;
> +        else
> +          Supported = false;
> +      }
> +    } else if (Location.Deref) {
> +      // We've encountered a Deref range when we had not applied the
> +      // reference encoding. Start over using reference encoding.
> +      Var.Deref = true;
> +      Var.DefRanges.clear();
> +      calculateRanges(Var, Ranges);
> +      return;
> +    }
> +
> +    // If we don't know how to handle this range, skip past it.
> +    if (!Supported || (Location.Offset && !Location.InMemory))
> +      continue;
> +
> +    // Handle the two cases we can handle: indirect in memory and in
> register.
> +    {
> +      LocalVarDefRange DR;
> +      DR.CVRegister = TRI->getCodeViewRegNum(Location.Register);
> +      DR.InMemory = Location.InMemory;
> +      DR.DataOffset = Location.Offset;
> +      if (Location.FragmentInfo) {
> +        DR.IsSubfield = true;
> +        DR.StructOffset = Location.FragmentInfo->OffsetInBits / 8;
> +      } else {
> +        DR.IsSubfield = false;
> +        DR.StructOffset = 0;
> +      }
> +
> +      if (Var.DefRanges.empty() ||
> +          Var.DefRanges.back().isDifferentLocation(DR)) {
> +        Var.DefRanges.emplace_back(std::move(DR));
> +      }
> +    }
> +
> +    // Compute the label range.
> +    const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
> +    const MCSymbol *End = getLabelAfterInsn(Range.second);
> +    if (!End) {
> +      // This range is valid until the next overlapping bitpiece. In the
> +      // common case, ranges will not be bitpieces, so they will overlap.
> +      auto J = std::next(I);
> +      const DIExpression *DIExpr = DVInst->getDebugExpression();
> +      while (J != E &&
> +             !fragmentsOverlap(DIExpr, J->first->getDebugExpression()))
> +        ++J;
> +      if (J != E)
> +        End = getLabelBeforeInsn(J->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 *>> &R =
> +        Var.DefRanges.back().Ranges;
> +    if (!R.empty() && R.back().second == Begin)
> +      R.back().second = End;
> +    else
> +      R.emplace_back(Begin, End);
> +
> +    // FIXME: Do more range combining.
> +  }
> +}
> +
>  void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
>    DenseSet<InlinedVariable> Processed;
>    // Grab the variable info that was squirreled away in the MMI
> side-table.
>    collectVariableInfoFromMFTable(Processed);
>
> -  const TargetRegisterInfo *TRI =
> Asm->MF->getSubtarget().getRegisterInfo();
> -
>    for (const auto &I : DbgValues) {
>      InlinedVariable IV = I.first;
>      if (Processed.count(IV))
> @@ -978,89 +1068,7 @@ void CodeViewDebug::collectVariableInfo(
>      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();
> -      bool InMemory = DVInst->getOperand(1).isImm();
> -      bool IsSubfield = false;
> -      unsigned StructOffset = 0;
> -      // Recognize a +Offset expression.
> -      int Offset = 0;
> -      DIExpressionCursor Ops(DIExpr);
> -      auto Op = Ops.peek();
> -      if (Op && Op->getOp() == dwarf::DW_OP_plus_uconst) {
> -        Offset = Op->getArg(0);
> -        Ops.take();
> -      }
> -
> -      // Handle fragments.
> -      auto Fragment = Ops.getFragmentInfo();
> -      if (Fragment) {
> -        IsSubfield = true;
> -        StructOffset = Fragment->OffsetInBits / 8;
> -      }
> -      // Ignore unrecognized exprs.
> -      if (Ops.peek() && Ops.peek()->getOp() != dwarf::DW_OP_LLVM_fragment)
> -        continue;
> -      if (!InMemory && Offset)
> -        continue;
> -
> -      // Bail if operand 0 is not a valid register. This means the
> variable is a
> -      // simple constant, or is described by a complex expression.
> -      // FIXME: Find a way to represent constant variables, since they are
> -      // relatively common.
> -      unsigned Reg =
> -          DVInst->getOperand(0).isReg() ? DVInst->getOperand(0).getReg()
> : 0;
> -      if (Reg == 0)
> -        continue;
> -
> -      // Handle the two cases we can handle: indirect in memory and in
> register.
> -      unsigned CVReg = TRI->getCodeViewRegNum(Reg);
> -      {
> -        LocalVarDefRange DR;
> -        DR.CVRegister = CVReg;
> -        DR.InMemory = InMemory;
> -        DR.DataOffset = Offset;
> -        DR.IsSubfield = IsSubfield;
> -        DR.StructOffset = StructOffset;
> -
> -        if (Var.DefRanges.empty() ||
> -            Var.DefRanges.back().isDifferentLocation(DR)) {
> -          Var.DefRanges.emplace_back(std::move(DR));
> -        }
> -      }
> -
> -      // Compute the label range.
> -      const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
> -      const MCSymbol *End = getLabelAfterInsn(Range.second);
> -      if (!End) {
> -        // This range is valid until the next overlapping bitpiece. In the
> -        // common case, ranges will not be bitpieces, so they will
> overlap.
> -        auto J = std::next(I);
> -        while (J != E &&
> -               !fragmentsOverlap(DIExpr, J->first->getDebugExpression()))
> -          ++J;
> -        if (J != E)
> -          End = getLabelBeforeInsn(J->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.
> -    }
> -
> +    calculateRanges(Var, Ranges);
>      recordLocalVariable(std::move(Var), InlinedAt);
>    }
>  }
> @@ -1987,6 +1995,16 @@ TypeIndex CodeViewDebug::getTypeIndex(DI
>    return recordTypeIndexForDINode(Ty, TI, ClassTy);
>  }
>
> +TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
> +  DIType *Ty = TypeRef.resolve();
> +  PointerRecord PR(getTypeIndex(Ty),
> +                   getPointerSizeInBytes() == 8 ? PointerKind::Near64
> +                                                : PointerKind::Near32,
> +                   PointerMode::LValueReference, PointerOptions::None,
> +                   Ty->getSizeInBits() / 8);
> +  return TypeTable.writeKnownType(PR);
> +}
> +
>  TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
>    const DIType *Ty = TypeRef.resolve();
>
> @@ -2094,7 +2112,8 @@ void CodeViewDebug::emitLocalVariable(co
>      Flags |= LocalSymFlags::IsOptimizedOut;
>
>    OS.AddComment("TypeIndex");
> -  TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
> +  TypeIndex TI = Var.Deref ?
> getTypeIndexForReferenceTo(Var.DIVar->getType())
> +                           : getCompleteTypeIndex(Var.DIVar->getType());
>    OS.EmitIntValue(TI.getIndex(), 4);
>    OS.AddComment("Flags");
>    OS.EmitIntValue(static_cast<uint16_t>(Flags), 2);
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=311957&r1=311956&r2=311957&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Mon Aug 28 17:06:59
> 2017
> @@ -94,6 +94,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
>    struct LocalVariable {
>      const DILocalVariable *DIVar = nullptr;
>      SmallVector<LocalVarDefRange, 1> DefRanges;
> +    bool Deref = false;
>    };
>
>    struct InlineSite {
> @@ -147,6 +148,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
>
>    codeview::TypeIndex getFuncIdForSubprogram(const DISubprogram *SP);
>
> +  void calculateRanges(LocalVariable &Var,
> +                       const DbgValueHistoryMap::InstrRanges &Ranges);
> +
>    static void collectInlineSiteChildren(SmallVectorImpl<unsigned>
> &Children,
>                                          const FunctionInfo &FI,
>                                          const InlineSite &Site);
> @@ -259,6 +263,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
>    codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
>                                     DITypeRef ClassTyRef = DITypeRef());
>
> +  codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef);
> +
>    codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
>                                              const DICompositeType *Class);
>
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp?rev=311957&r1=311956&r2=311957&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp Mon Aug 28
> 17:06:59 2017
> @@ -23,6 +23,57 @@
>
>  using namespace llvm;
>
> +bool DbgVariableLocation::extractFromMachineInstruction(
> +    DbgVariableLocation &Location, const MachineInstr &Instruction) {
> +  if (!Instruction.isDebugValue())
> +    return false;
> +  if (!Instruction.getOperand(0).isReg())
> +    return false;
> +  Location.Register = Instruction.getOperand(0).getReg();
> +  Location.InMemory = Instruction.getOperand(1).isImm();
> +  Location.Deref = false;
> +  Location.FragmentInfo.reset();
> +  // We only handle expressions generated by DIExpression::appendOffset,
> +  // which doesn't require a full stack machine.
> +  int64_t Offset = 0;
> +  const DIExpression *DIExpr = Instruction.getDebugExpression();
> +  auto Op = DIExpr->expr_op_begin();
> +  while (Op != DIExpr->expr_op_end()) {
> +    switch (Op->getOp()) {
> +    case dwarf::DW_OP_constu: {
> +      int Value = Op->getArg(0);
> +      ++Op;
> +      if (Op != DIExpr->expr_op_end()) {
> +        switch (Op->getOp()) {
> +        case dwarf::DW_OP_minus:
> +          Offset -= Value;
> +          break;
> +        case dwarf::DW_OP_plus:
> +          Offset += Value;
> +        default:
> +          continue;
> +        }
> +      }
> +    } break;
> +    case dwarf::DW_OP_plus_uconst:
> +      Offset += Op->getArg(0);
> +      break;
> +    case dwarf::DW_OP_LLVM_fragment:
> +      Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)};
> +      break;
> +    case dwarf::DW_OP_deref:
> +      Location.Deref = true;
> +      break;
> +    default:
> +      return false;
> +    }
> +    ++Op;
> +  }
> +
> +  Location.Offset = Offset;
> +  return true;
> +}
> +
>  DebugHandlerBase::DebugHandlerBase(AsmPrinter *A) : Asm(A), MMI(Asm->MMI)
> {}
>
>  // Each LexicalScope has first instruction and last instruction to mark
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h?rev=311957&r1=311956&r2=311957&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DebugHandlerBase.h Mon Aug 28
> 17:06:59 2017
> @@ -17,14 +17,44 @@
>
>  #include "AsmPrinterHandler.h"
>  #include "DbgValueHistoryCalculator.h"
> +#include "llvm/ADT/Optional.h"
>  #include "llvm/CodeGen/LexicalScopes.h"
>  #include "llvm/CodeGen/MachineInstr.h"
> +#include "llvm/IR/DebugInfoMetadata.h"
>
>  namespace llvm {
>
>  class AsmPrinter;
> +class MachineInstr;
>  class MachineModuleInfo;
>
> +/// Represents the location at which a variable is stored.
> +struct DbgVariableLocation {
> +  /// Offset relative to base register.
> +  int64_t Offset;
> +
> +  /// Base register.
> +  unsigned Register;
> +
> +  /// If false, Register is the location. If true,
> +  /// Register+Offset point at the location.
> +  unsigned InMemory : 1;
> +
> +  /// If false, the location holds the variable's value.
> +  /// If true, the location holds the variable's address.
> +  unsigned Deref : 1;
> +
> +  /// Present if the location is part of a larger variable.
> +  llvm::Optional<llvm::DIExpression::FragmentInfo> FragmentInfo;
> +
> +  /// Extract a VariableLocation from a MachineInstr.  The struct passed
> in as
> +  /// Location is populated.  The MachineInstr must be a debug value
> +  /// instruction.
> +  /// @return true if successful and false if not.
> +  static bool extractFromMachineInstruction(DbgVariableLocation &Location,
> +                                            const MachineInstr
> &Instruction);
> +};
> +
>  /// Base class for debug information backends. Common functionality
> related to
>  /// tracking which variables and scopes are alive at a given PC live here.
>  class DebugHandlerBase : public AsmPrinterHandler {
>
> Added: llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir?rev=311957&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir (added)
> +++ llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir Mon Aug 28 17:06:59
> 2017
> @@ -0,0 +1,253 @@
> +# RUN: llc -filetype=obj -O0 %s -o - | llvm-readobj -codeview | FileCheck
> %s
> +#
> +# (DW_OP_plus_uconst 12)
> +# CHECK: LocalSym {
> +# CHECK-NEXT:   Kind: S_LOCAL (0x113E)
> +# CHECK-NEXT:   Type: string* (0x
> +# CHECK-NEXT:   Flags [ (0x0)
> +# CHECK-NEXT:   ]
> +# CHECK-NEXT:   VarName: Str
> +# CHECK-NEXT: }
> +# CHECK-NEXT: DefRangeRegisterRelSym {
> +# CHECK-NEXT:   Kind: S_DEFRANGE_REGISTER_REL (0x1145)
> +# CHECK-NEXT:   BaseRegister:
> +# CHECK-NEXT:   HasSpilledUDTMember: No
> +# CHECK-NEXT:   OffsetInParent: 0
> +# CHECK-NEXT:   BasePointerOffset: 12
> +# CHECK-NEXT:   LocalVariableAddrRange {
> +# CHECK-NEXT:     OffsetStart:
> +# CHECK-NEXT:     ISectStart:
> +# CHECK-NEXT:     Range:
> +# CHECK-NEXT:   }
> +# CHECK-NEXT: }
> +# (DW_OP_plus_uconst, 8, DW_OP_deref)
> +# CHECK: LocalSym {
> +# CHECK-NEXT:   Kind: S_LOCAL (0x113E)
> +# CHECK-NEXT:   Type: string& (0x
> +# CHECK-NEXT:   Flags [ (0x0)
> +# CHECK-NEXT:   ]
> +# CHECK-NEXT:   VarName: Result
> +# CHECK-NEXT: }
> +# CHECK-NEXT: DefRangeRegisterRelSym {
> +# CHECK-NEXT:   Kind: S_DEFRANGE_REGISTER_REL (0x1145)
> +# CHECK-NEXT:   BaseRegister:
> +# CHECK-NEXT:   HasSpilledUDTMember: No
> +# CHECK-NEXT:   OffsetInParent: 0
> +# CHECK-NEXT:   BasePointerOffset: 8
> +# CHECK-NEXT:   LocalVariableAddrRange {
> +# CHECK-NEXT:     OffsetStart:
> +# CHECK-NEXT:     ISectStart:
> +# CHECK-NEXT:     Range:
> +# CHECK-NEXT:   }
> +# CHECK-NEXT: }
> +# (DW_OP_constu, 4, DW_OP_minus)
> +# CHECK: LocalSym {
> +# CHECK-NEXT:   Kind: S_LOCAL (0x113E)
> +# CHECK-NEXT:   Type: long (0x12)
> +# CHECK-NEXT:   Flags [ (0x0)
> +# CHECK-NEXT:   ]
> +# CHECK-NEXT:   VarName: Bytes
> +# CHECK-NEXT: }
> +# CHECK-NEXT: DefRangeRegisterRelSym {
> +# CHECK-NEXT:   Kind: S_DEFRANGE_REGISTER_REL (0x1145)
> +# CHECK-NEXT:   BaseRegister:
> +# CHECK-NEXT:   HasSpilledUDTMember: No
> +# CHECK-NEXT:   OffsetInParent: 0
> +# CHECK-NEXT:   BasePointerOffset: -4
> +# CHECK-NEXT:   LocalVariableAddrRange {
> +# CHECK-NEXT:     OffsetStart:
> +# CHECK-NEXT:     ISectStart:
> +# CHECK-NEXT:     Range:
> +# CHECK-NEXT:   }
> +# CHECK-NEXT: }
> +--- |
> +  ; ModuleID = '<stdin>'
> +  source_filename = "<stdin>"
> +  target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
> +  target triple = "i386-pc-windows-msvc19.0.24215"
> +
> +  %struct.string = type { i32, i32, i8* }
> +
> +  define void @fun(%struct.string* noalias sret %agg.result,
> %struct.string* noalias %str) !dbg !12 {
> +  entry:
> +    call void @llvm.dbg.value(metadata %struct.string* %agg.result,
> metadata !23, metadata !24), !dbg !25
> +    call void @llvm.dbg.value(metadata %struct.string* %str, metadata
> !26, metadata !28), !dbg !25
> +    %call = call dereferenceable(12) %struct.string* @getString(), !dbg
> !29
> +    %0 = bitcast %struct.string* %agg.result to i8*, !dbg !29
> +    %1 = bitcast %struct.string* %call to i8*, !dbg !29
> +    call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 12, i32 4,
> i1 false), !dbg !29
> +    ret void, !dbg !30
> +  }
> +
> +  define i32 @len(%struct.string* %s, i32 %acc) !dbg !31 {
> +  entry:
> +    %0 = bitcast %struct.string* %s to i32*
> +    %bytes = load i32, i32* %0, !dbg !34
> +    call void @llvm.dbg.declare(metadata i32 %bytes, metadata !35,
> metadata !28), !dbg !34
> +    %1 = add i32 %bytes, %acc, !dbg !36
> +    ret i32 %1, !dbg !36
> +  }
> +
> +  ; Function Attrs: nounwind readnone speculatable
> +  declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
> +
> +  ; Function Attrs: nounwind readnone speculatable
> +  declare void @llvm.dbg.value(metadata, metadata, metadata) #0
> +
> +  declare dereferenceable(12) %struct.string* @getString()
> +
> +  ; Function Attrs: argmemonly nounwind
> +  declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8*
> nocapture readonly, i32, i32, i1) #1
> +
> +  ; Function Attrs: nounwind
> +  declare void @llvm.stackprotector(i8*, i8**) #2
> +
> +  attributes #0 = { nounwind readnone speculatable }
> +  attributes #1 = { argmemonly nounwind }
> +  attributes #2 = { nounwind }
> +
> +  !llvm.dbg.cu = !{!0}
> +  !llvm.linker.options = !{!3, !4}
> +  !llvm.module.flags = !{!5, !6, !7, !8}
> +  !llvm.ident = !{!9}
> +
> +  !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0,
> emissionKind: FullDebug, enums: !2)
> +  !1 = !DIFile(filename: "diexpr.ll", directory: "C:\5Csrc",
> checksumkind: CSK_MD5, checksum: "c547c362c610fa79e7abaddc76e1efe7")
> +  !2 = !{}
> +  !3 = !{!"/DEFAULTLIB:libcmt.lib"}
> +  !4 = !{!"/DEFAULTLIB:oldnames.lib"}
> +  !5 = !{i32 1, !"NumRegisterParameters", i32 0}
> +  !6 = !{i32 2, !"CodeView", i32 1}
> +  !7 = !{i32 2, !"Debug Info Version", i32 3}
> +  !8 = !{i32 1, !"wchar_size", i32 2}
> +  !9 = !{!"clang version 6.0.0 "}
> +  !10 = !DIExpression(DW_OP_plus_uconst, 12)
> +  !11 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref)
> +  !12 = distinct !DISubprogram(name: "fun", linkageName: "fun", scope:
> !1, file: !1, line: 9, type: !13, isLocal: false, isDefinition: true,
> scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0,
> variables: !2)
> +  !13 = !DISubroutineType(types: !14)
> +  !14 = !{!15}
> +  !15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name:
> "string", file: !1, line: 1, size: 96, elements: !16, identifier:
> ".?AUstring@@")
> +  !16 = !{!17, !19, !20}
> +  !17 = !DIDerivedType(tag: DW_TAG_member, name: "length", scope: !15,
> file: !1, line: 2, baseType: !18, size: 32)
> +  !18 = !DIBasicType(name: "long int", size: 32, encoding: DW_ATE_signed)
> +  !19 = !DIDerivedType(tag: DW_TAG_member, name: "size", scope: !15,
> file: !1, line: 3, baseType: !18, size: 32, offset: 32)
> +  !20 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !15,
> file: !1, line: 4, baseType: !21, size: 32, offset: 64)
> +  !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 32)
> +  !22 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
> +  !23 = !DILocalVariable(name: "Result", scope: !12, file: !1, line: 10,
> type: !15)
> +  !24 = !DIExpression(DW_OP_deref)
> +  !25 = !DILocation(line: 10, scope: !12)
> +  !26 = !DILocalVariable(name: "Str", scope: !12, file: !1, line: 10,
> type: !27)
> +  !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 32)
> +  !28 = !DIExpression(DW_OP_constu, 4, DW_OP_minus)
> +  !29 = !DILocation(line: 11, scope: !12)
> +  !30 = !DILocation(line: 12, scope: !12)
> +  !31 = distinct !DISubprogram(name: "len", linkageName: "len", scope:
> !1, file: !1, line: 14, type: !32, isLocal: false, isDefinition: true,
> scopeLine: 14, flags: DIFlagPrototyped, isOptimized: false, unit: !0,
> variables: !2)
> +  !32 = !DISubroutineType(types: !33)
> +  !33 = !{!18}
> +  !34 = !DILocation(line: 15, scope: !31)
> +  !35 = !DILocalVariable(name: "Bytes", scope: !31, file: !1, line: 15,
> type: !18)
> +  !36 = !DILocation(line: 16, scope: !31)
> +
> +...
> +---
> +name:            fun
> +alignment:       4
> +exposesReturnsTwice: false
> +legalized:       false
> +regBankSelected: false
> +selected:        false
> +tracksRegLiveness: true
> +registers:
> +liveins:
> +frameInfo:
> +  isFrameAddressTaken: false
> +  isReturnAddressTaken: false
> +  hasStackMap:     false
> +  hasPatchPoint:   false
> +  stackSize:       4
> +  offsetAdjustment: 0
> +  maxAlignment:    4
> +  adjustsStack:    true
> +  hasCalls:        true
> +  stackProtector:  ''
> +  maxCallFrameSize: 0
> +  hasOpaqueSPAdjustment: false
> +  hasVAStart:      false
> +  hasMustTailInVarArgFunc: false
> +  savePoint:       ''
> +  restorePoint:    ''
> +fixedStack:
> +  - { id: 0, type: spill-slot, offset: -8, size: 4, alignment: 4,
> stack-id: 0,
> +      callee-saved-register: '%esi' }
> +  - { id: 1, type: default, offset: 4, size: 4, alignment: 4, stack-id: 0,
> +      isImmutable: true, isAliased: false, callee-saved-register: '' }
> +  - { id: 2, type: default, offset: 0, size: 4, alignment: 4, stack-id: 0,
> +      isImmutable: true, isAliased: false, callee-saved-register: '' }
> +stack:
> +constants:
> +body:             |
> +  bb.0.entry:
> +    liveins: %esi
> +
> +    frame-setup PUSH32r killed %esi, implicit-def %esp, implicit %esp
> +    CFI_INSTRUCTION def_cfa_offset 8
> +    CFI_INSTRUCTION offset %esi, -8
> +    %esi = MOV32rm %esp, 1, _, 8, _ :: (load 4 from %fixed-stack.2)
> +    DBG_VALUE %esp, 0, !26, !10, debug-location !25
> +    DBG_VALUE %esp, 0, !23, !11, debug-location !25
> +    CALLpcrel32 @getString, csr_32, implicit %esp, implicit-def %esp,
> implicit-def %eax, debug-location !29
> +    %ecx = MOV32rm %eax, 1, _, 0, _, debug-location !29 ::
> (dereferenceable load 4 from %ir.1)
> +    %edx = MOV32rm %eax, 1, _, 4, _, debug-location !29 ::
> (dereferenceable load 4 from %ir.1 + 4)
> +    MOV32mr %esi, 1, _, 0, _, killed %ecx, debug-location !29 :: (store 4
> into %ir.0)
> +    MOV32mr %esi, 1, _, 4, _, killed %edx, debug-location !29 :: (store 4
> into %ir.0 + 4)
> +    %eax = MOV32rm killed %eax, 1, _, 8, _, debug-location !29 ::
> (dereferenceable load 4 from %ir.1 + 8)
> +    MOV32mr %esi, 1, _, 8, _, killed %eax, debug-location !29 :: (store 4
> into %ir.0 + 8)
> +    %eax = COPY killed %esi, debug-location !30
> +    %esi = POP32r implicit-def %esp, implicit %esp, debug-location !30
> +    RET 0, %eax, debug-location !30
> +
> +...
> +---
> +name:            len
> +alignment:       4
> +exposesReturnsTwice: false
> +legalized:       false
> +regBankSelected: false
> +selected:        false
> +tracksRegLiveness: true
> +registers:
> +liveins:
> +frameInfo:
> +  isFrameAddressTaken: false
> +  isReturnAddressTaken: false
> +  hasStackMap:     false
> +  hasPatchPoint:   false
> +  stackSize:       0
> +  offsetAdjustment: 0
> +  maxAlignment:    4
> +  adjustsStack:    false
> +  hasCalls:        false
> +  stackProtector:  ''
> +  maxCallFrameSize: 0
> +  hasOpaqueSPAdjustment: false
> +  hasVAStart:      false
> +  hasMustTailInVarArgFunc: false
> +  savePoint:       ''
> +  restorePoint:    ''
> +fixedStack:
> +  - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: 0,
> +      isImmutable: true, isAliased: false, callee-saved-register: '' }
> +  - { id: 1, type: default, offset: 0, size: 4, alignment: 4, stack-id: 0,
> +      isImmutable: true, isAliased: false, callee-saved-register: '' }
> +stack:
> +constants:
> +body:             |
> +  bb.0.entry:
> +    %eax = MOV32rm %esp, 1, _, 4, _ :: (load 4 from %fixed-stack.1)
> +    %eax = MOV32rm killed %eax, 1, _, 0, _, debug-location !34 :: (load 4
> from %ir.0)
> +    DBG_VALUE debug-use %eax, 0, !35, !28, debug-location !34
> +    %eax = ADD32rm killed %eax, %esp, 1, _, 8, _, implicit-def dead
> %eflags, debug-location !36 :: (load 4 from %fixed-stack.0)
> +    RET 0, %eax, debug-location !36
> +
> +...
>
> Modified: llvm/trunk/test/DebugInfo/COFF/pieces.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/pieces.ll?rev=311957&r1=311956&r2=311957&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/pieces.ll (original)
> +++ llvm/trunk/test/DebugInfo/COFF/pieces.ll Mon Aug 28 17:06:59 2017
> @@ -179,8 +179,7 @@
>  ; ASM:        .asciz  "nested"                # Function name
>  ; ASM:        .short  4414                    # Record kind: S_LOCAL
>  ; ASM:        .asciz  "o"
> -; FIXME: We should have a .cv_def_range for 'o', but we don't yet.
> -; ASM-NOT:    .cv_def_range
> +; ASM:        .cv_def_range    .Lfunc_begin3 .Lfunc_end3,
> "E\021J\001\000\000\000\000\000\000"
>  ; ASM:        .short  4414                    # Record kind: S_LOCAL
>  ; ASM:        .asciz  "p"
>  ; ASM:        .cv_def_range    [[p_start]] .Lfunc_end3,
> "C\021\021\000\000\000\004\000\000\000"
> @@ -190,8 +189,17 @@
>  ; OBJ:         DisplayName: nested
>  ; OBJ:       }
>  ; OBJ:       LocalSym {
> +; OBJ:         Type: Nested&
>  ; OBJ:         VarName: o
>  ; OBJ:       }
> +; OBJ:       DefRangeRegisterRelSym {
> +; OBJ:         BaseRegister: 330
> +; OBJ:         HasSpilledUDTMember: No
> +; OBJ:         OffsetInParent: 0
> +; OBJ:         BasePointerOffset: 0
> +; OBJ:         LocalVariableAddrRange {
> +; OBJ:         }
> +; OBJ:       }
>  ; OBJ:       LocalSym {
>  ; OBJ:         VarName: p
>  ; OBJ:       }
>
> Modified: llvm/trunk/test/DebugInfo/COFF/types-array-advanced.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-array-advanced.ll?rev=311957&r1=311956&r2=311957&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/types-array-advanced.ll (original)
> +++ llvm/trunk/test/DebugInfo/COFF/types-array-advanced.ll Mon Aug 28
> 17:06:59 2017
> @@ -50,28 +50,40 @@
>  ; CHECK:     SizeOf: 4
>  ; CHECK:     Name:
>  ; CHECK:   }
> -; CHECK:   Array (0x1004) {
> +; CHECK:   Pointer (0x1004) {
> +; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
> +; CHECK:     PointeeType: 0x1003
> +; CHECK:     PointerAttributes: 0x2A
> +; CHECK:     PtrType: Near32 (0xA)
> +; CHECK:     PtrMode: LValueReference (0x1)
> +; CHECK:     IsFlat: 0
> +; CHECK:     IsConst: 0
> +; CHECK:     IsVolatile: 0
> +; CHECK:     IsUnaligned: 0
> +; CHECK:     SizeOf: 0
> +; CHECK:   }
> +; CHECK:   Array (0x1005) {
>  ; CHECK:     TypeLeafKind: LF_ARRAY (0x1503)
>  ; CHECK:     ElementType: char (0x70)
>  ; CHECK:     IndexType: unsigned long (0x22)
>  ; CHECK:     SizeOf: 7
>  ; CHECK:     Name:
>  ; CHECK:   }
> -; CHECK:   Array (0x1005) {
> +; CHECK:   Array (0x1006) {
>  ; CHECK:     TypeLeafKind: LF_ARRAY (0x1503)
> -; CHECK:     ElementType: 0x1004
> +; CHECK:     ElementType: 0x1005
>  ; CHECK:     IndexType: unsigned long (0x22)
>  ; CHECK:     SizeOf: 35
>  ; CHECK:     Name:
>  ; CHECK:   }
> -; CHECK:   Array (0x1006) {
> +; CHECK:   Array (0x1007) {
>  ; CHECK:     TypeLeafKind: LF_ARRAY (0x1503)
> -; CHECK:     ElementType: 0x1005
> +; CHECK:     ElementType: 0x1006
>  ; CHECK:     IndexType: unsigned long (0x22)
>  ; CHECK:     SizeOf: 70
>  ; CHECK:     Name:
>  ; CHECK:   }
> -; CHECK:   Struct (0x1007) {
> +; CHECK:   Struct (0x1008) {
>  ; CHECK:     TypeLeafKind: LF_STRUCTURE (0x1505)
>  ; CHECK:     MemberCount: 0
>  ; CHECK:     Properties [ (0x280)
> @@ -85,16 +97,16 @@
>  ; CHECK:     Name: incomplete_struct
>  ; CHECK:     LinkageName: .?AUincomplete_struct@@
>  ; CHECK:   }
> -; CHECK:   Array (0x1008) {
> +; CHECK:   Array (0x1009) {
>  ; CHECK:     TypeLeafKind: LF_ARRAY (0x1503)
> -; CHECK:     ElementType: incomplete_struct (0x1007)
> +; CHECK:     ElementType: incomplete_struct (0x1008)
>  ; CHECK:     IndexType: unsigned long (0x22)
>  ; CHECK:     SizeOf: 12
>  ; CHECK:     Name:
>  ; CHECK:   }
> -; CHECK:   Pointer (0x1009) {
> +; CHECK:   Pointer (0x100A) {
>  ; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
> -; CHECK:     PointeeType: 0x1008
> +; CHECK:     PointeeType: 0x1009
>  ; CHECK:     PointerAttributes: 0x800A
>  ; CHECK:     PtrType: Near32 (0xA)
>  ; CHECK:     PtrMode: Pointer (0x0)
> @@ -104,8 +116,41 @@
>  ; CHECK:     IsUnaligned: 0
>  ; CHECK:     SizeOf: 4
>  ; CHECK:   }
> -;
> -; CHECK:   Modifier (0x100E) {
> +; CHECK:   FieldList (0x100B) {
> +; CHECK:     TypeLeafKind: LF_FIELDLIST (0x1203)
> +; CHECK:     DataMember {
> +; CHECK:       TypeLeafKind: LF_MEMBER (0x150D)
> +; CHECK:       AccessSpecifier: Public (0x3)
> +; CHECK:       Type: int (0x74)
> +; CHECK:       FieldOffset: 0x0
> +; CHECK:       Name: s1
> +; CHECK:     }
> +; CHECK:   }
> +; CHECK:   Struct (0x100C) {
> +; CHECK:     TypeLeafKind: LF_STRUCTURE (0x1505)
> +; CHECK:     MemberCount: 1
> +; CHECK:     Properties [ (0x200)
> +; CHECK:       HasUniqueName (0x200)
> +; CHECK:     ]
> +; CHECK:     FieldList: <field list> (0x100B)
> +; CHECK:     DerivedFrom: 0x0
> +; CHECK:     VShape: 0x0
> +; CHECK:     SizeOf: 4
> +; CHECK:     Name: incomplete_struct
> +; CHECK:     LinkageName: .?AUincomplete_struct@@
> +; CHECK:   }
> +; CHECK:   StringId (0x100D) {
> +; CHECK:     TypeLeafKind: LF_STRING_ID (0x1605)
> +; CHECK:     Id: 0x0
> +; CHECK:     StringData: \t.cpp
> +; CHECK:   }
> +; CHECK:   UdtSourceLine (0x100E) {
> +; CHECK:     TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
> +; CHECK:     UDT: incomplete_struct (0x100C)
> +; CHECK:     SourceFile: \t.cpp (0x100D)
> +; CHECK:     LineNumber: 4
> +; CHECK:   }
> +; CHECK:   Modifier (0x100F) {
>  ; CHECK:     TypeLeafKind: LF_MODIFIER (0x1001)
>  ; CHECK:     ModifiedType: int (0x74)
>  ; CHECK:     Modifiers [ (0x3)
> @@ -113,12 +158,12 @@
>  ; CHECK:       Volatile (0x2)
>  ; CHECK:     ]
>  ; CHECK:   }
> -; CHECK:   Array (0x100F) {
> +; CHECK:   Array (0x1010) {
>  ; CHECK:     TypeLeafKind: LF_ARRAY (0x1503)
> -; CHECK:     ElementType: const volatile int (0x100E)
> +; CHECK:     ElementType: const volatile int (0x100F)
>  ; CHECK:     IndexType: unsigned long (0x22)
>  ; CHECK:     SizeOf: 16
> -; CHECK:     Name:
> +; CHECK:     Name:
>  ; CHECK:   }
>  ; CHECK: ]
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170829/cd3e742e/attachment.html>


More information about the llvm-commits mailing list