[llvm] 3137fe4 - [DebugInfo][DAG] Distinguish different kinds of location indirection

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 30 11:41:43 PDT 2019


Author: Jeremy Morse
Date: 2019-10-30T18:41:44Z
New Revision: 3137fe4d23eeb8df08c03e9111465325eeafe08e

URL: https://github.com/llvm/llvm-project/commit/3137fe4d23eeb8df08c03e9111465325eeafe08e
DIFF: https://github.com/llvm/llvm-project/commit/3137fe4d23eeb8df08c03e9111465325eeafe08e.diff

LOG: [DebugInfo][DAG] Distinguish different kinds of location indirection

>From SelectionDAGs point of view, debug variable locations specified with
dbg.declare and dbg.addr are indirect -- they specify the address of
something. But calling conventions might mean that a Value is placed on
the stack somewhere, and this too is indirection. Previously this was
mixed up in the "IsIndirect" field of DBG_VALUE insts; this patch
separates them by encoding the indirection in a DIExpression.

If we have a dbg.declare or dbg.addr, then the expression produces an
address that then becomes a DWARF memory location. We can represent
this by putting a DW_OP_deref on the _end_ of the expression. If a Value
has been placed on the stack, then we need to put a DW_OP_deref on the
_start_ of the expression, to load the Value from the stack and have
the rest of the expression operate on it.

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

Added: 
    llvm/test/DebugInfo/X86/stack-arg-deref.ll

Modified: 
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index da96c9ac435a..67d24025abef 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5493,7 +5493,6 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
   MachineFunction &MF = DAG.getMachineFunction();
   const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo();
 
-  bool IsIndirect = false;
   Optional<MachineOperand> Op;
   // Some arguments' frame index is recorded during argument lowering.
   int FI = FuncInfo.getArgumentFrameIndex(Arg);
@@ -5515,7 +5514,6 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
     }
     if (Reg) {
       Op = MachineOperand::CreateReg(Reg, false);
-      IsIndirect = IsDbgDeclare;
     }
   }
 
@@ -5559,7 +5557,6 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
       }
 
       Op = MachineOperand::CreateReg(VMI->second, false);
-      IsIndirect = IsDbgDeclare;
     } else if (ArgRegsAndSizes.size() > 1) {
       // This was split due to the calling convention, and no virtual register
       // mapping exists for the value.
@@ -5573,9 +5570,26 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
 
   assert(Variable->isValidLocationForIntrinsic(DL) &&
          "Expected inlined-at fields to agree");
-  IsIndirect = (Op->isReg()) ? IsIndirect : true;
-  if (IsIndirect)
+
+  // If the argument arrives in a stack slot, then what the IR thought was a
+  // normal Value is actually in memory, and we must add a deref to load it.
+  if (Op->isFI()) {
+    int FI = Op->getIndex();
+    unsigned Size = DAG.getMachineFunction().getFrameInfo().getObjectSize(FI);
+    if (Expr->isImplicit()) {
+      SmallVector<uint64_t, 2> Ops = {dwarf::DW_OP_deref_size, Size};
+      Expr = DIExpression::prependOpcodes(Expr, Ops);
+    } else {
+      Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
+    }
+  }
+
+  // If this location was specified with a dbg.declare, then it and its
+  // expression calculate the address of the variable. Append a deref to
+  // force it to be a memory location.
+  if (IsDbgDeclare)
     Expr = DIExpression::append(Expr, {dwarf::DW_OP_deref});
+
   FuncInfo.ArgDbgValues.push_back(
       BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), false,
               *Op, Variable, Expr));

diff  --git a/llvm/test/DebugInfo/X86/stack-arg-deref.ll b/llvm/test/DebugInfo/X86/stack-arg-deref.ll
new file mode 100644
index 000000000000..7b7fcac7dc3f
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/stack-arg-deref.ll
@@ -0,0 +1,85 @@
+; RUN: llc -stop-before=finalize-isel -o - %s -mtriple=i386-- | FileCheck %s --check-prefix=MIR
+; RUN: llc -o - %s -mtriple=i386-- --filetype=obj | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF --implicit-check-not=DW_TAG_subprogram
+; REQUIRES: object-emission
+;
+; Test that, when arguments are passed on the stack (such as i386),
+; variable location dereferences occur in the right place. When referring to
+; argument stack slots a deref must be used to load the slot first.
+
+; MIR: ![[FOOVAR:[0-9]+]] = !DILocalVariable(name: "foovar"
+; MIR: ![[BARVAR:[0-9]+]] = !DILocalVariable(name: "barvar"
+; MIR: ![[BAZVAR:[0-9]+]] = !DILocalVariable(name: "bazvar"
+
+; Plain i32 on the stack.
+; MIR-LABEL: name: foo
+; MIR:       DBG_VALUE %fixed-stack.0, $noreg, ![[FOOVAR]],
+; MIR-SAME:  !DIExpression(DW_OP_deref)
+; DWARF: DW_TAG_subprogram
+; DWARF-LABEL: DW_AT_name ("cheese")
+; DWARF:       DW_TAG_variable
+; DWARF-NEXT:  DW_AT_location (DW_OP_fbreg +4)
+; DWARF-NEXT:  DW_AT_name ("foovar")
+define i8 @foo(i32 %blah) !dbg !20 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %blah, metadata !23, metadata !DIExpression()), !dbg !21
+  ret i8 0, !dbg !21
+}
+
+; Pointer on the stack that we fiddle with.
+; MIR-LABEL: name: bar
+; MIR:       DBG_VALUE %fixed-stack.0, $noreg, ![[BARVAR]],
+; MIR-SAME:  !DIExpression(DW_OP_deref_size, 4, DW_OP_plus_uconst, 4, DW_OP_stack_value)
+; DWARF: DW_TAG_subprogram
+; DWARF-LABEL: DW_AT_name ("nope")
+; DWARF:       DW_TAG_variable
+; DWARF-NEXT:  DW_AT_location (DW_OP_fbreg +4, DW_OP_deref_size 0x4, DW_OP_plus_uconst 0x4, DW_OP_stack_value)
+; DWARF-NEXT:  DW_AT_name ("barvar")
+define i8 @bar(i32 *%blah) !dbg !30 {
+entry:
+  call void @llvm.dbg.value(metadata i32* %blah, metadata !33, metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value)), !dbg !31
+  ret i8 0, !dbg !31
+}
+
+; Pointer that we use as a dbg.declare variable location, after fiddling with
+; the pointer value.
+; MIR-LABEL: name: baz
+; MIR:       DBG_VALUE %fixed-stack.0, $noreg, ![[BAZVAR]],
+; MIR-SAME:  !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 4, DW_OP_deref)
+; DWARF: DW_TAG_subprogram
+; DWARF-LABEL: DW_AT_name ("brains")
+; DWARF:       DW_TAG_variable
+; DWARF-NEXT:  DW_AT_location (DW_OP_fbreg +4, DW_OP_deref, DW_OP_plus_uconst 0x4)
+; DWARF-NEXT:  DW_AT_name ("bazvar")
+define i8 @baz(i32 *%blah) !dbg !40 {
+entry:
+  call void @llvm.dbg.declare(metadata i32* %blah, metadata !43, metadata !DIExpression(DW_OP_plus_uconst, 4)), !dbg !41
+  ret i8 0, !dbg !41
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "asdf", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "nil", directory: "/")
+!2 = !{}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = !DISubroutineType(types: !2)
+!8 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
+
+!20 = distinct !DISubprogram(name: "cheese", linkageName: "cheese", scope: null, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: true, unit: !0, retainedNodes: !22)
+!21 = !DILocation(line: 1, column: 1, scope: !20)
+!22 = !{!23}
+!23 = !DILocalVariable(name: "foovar", scope: !20, file: !1, line: 14, type: !8)
+
+!30 = distinct !DISubprogram(name: "nope", linkageName: "nope", scope: null, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: true, unit: !0, retainedNodes: !32)
+!31 = !DILocation(line: 1, column: 1, scope: !30)
+!32 = !{!33}
+!33 = !DILocalVariable(name: "barvar", scope: !30, file: !1, line: 14, type: !8)
+
+!40 = distinct !DISubprogram(name: "brains", linkageName: "brains", scope: null, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: true, unit: !0, retainedNodes: !42)
+!41 = !DILocation(line: 1, column: 1, scope: !40)
+!42 = !{!43}
+!43 = !DILocalVariable(name: "bazvar", scope: !40, file: !1, line: 14, type: !8)


        


More information about the llvm-commits mailing list