Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -71,6 +71,7 @@ #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugLoc.h" @@ -1441,41 +1442,85 @@ const DbgValueInst *DI = cast(II); const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); const Value *V = DI->getValue(); + const DIExpression *DE = DI->getExpression(); + DILocalVariable *Var = DI->getVariable(); + DILocalVariable *PtrVar = nullptr; + unsigned Level = DE->implicitPointerCount(); assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) && "Expected inlined-at fields to agree"); + + Module *Mod = const_cast(DI->getModule()); + DIBuilder DIB(*Mod, /*AllowUnresolved*/ false); + + SmallVector PtrVars; + if (Level > 0) { + DIScope *Scope = DI->getDebugLoc()->getScope(); + DIType *Type = DI->getVariable()->getType(); + PtrVars.push_back(Var); + unsigned Count = 0; + while (Count++ < Level) { + if (DIDerivedType *DT = dyn_cast(Type)) + Type = DT->getBaseType(); + uint32_t AlignInBits = DI->getVariable()->getAlignInBytes(); + + PtrVar = DIB.createImplicitTempVariable(Scope, Type, AlignInBits); + PtrVars.push_back(PtrVar); + } + + Var = PtrVars[Level]; + DE = DIExpression::get(DE->getContext(), {}); + } else { + Var = DI->getVariable(); + DE = DI->getExpression(); + } + if (!V || isa(V)) { // Currently the optimizer can produce this; insert an undef to // help debugging. - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, false, 0U, - DI->getVariable(), DI->getExpression()); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, false, 0U, Var, DE); } else if (const auto *CI = dyn_cast(V)) { if (CI->getBitWidth() > 64) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II) .addCImm(CI) .addImm(0U) - .addMetadata(DI->getVariable()) - .addMetadata(DI->getExpression()); + .addMetadata(Var) + .addMetadata(DE); else BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II) .addImm(CI->getZExtValue()) .addImm(0U) - .addMetadata(DI->getVariable()) - .addMetadata(DI->getExpression()); + .addMetadata(Var) + .addMetadata(DE); } else if (const auto *CF = dyn_cast(V)) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II) .addFPImm(CF) .addImm(0U) - .addMetadata(DI->getVariable()) - .addMetadata(DI->getExpression()); + .addMetadata(Var) + .addMetadata(DE); } else if (Register Reg = lookUpRegForValue(V)) { // FIXME: This does not handle register-indirect values at offset 0. bool IsIndirect = false; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg, - DI->getVariable(), DI->getExpression()); + Var, DE); } else { // We don't know how to handle other cases, so we drop. LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n"); } + + if (!PtrVars.empty()) { + unsigned Count = Level; + while (Count-- > 0) { + SmallVector Ops; + Ops.push_back(dwarf::DW_OP_LLVM_implicit_pointer); + DIExpression *DIExprNew = DIExpression::get(DE->getContext(), Ops); + + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II) + .addImplicitPtrMetadata(PtrVars[Count + 1]) + .addReg(0U) + .addMetadata(PtrVars[Count]) + .addMetadata(DIExprNew); + } + } return true; } case Intrinsic::dbg_label: { Index: llvm/test/DebugInfo/X86/implicit_pointer_fast.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/implicit_pointer_fast.ll @@ -0,0 +1,99 @@ +; RUN: llc %s -fast-isel -O2 -filetype=obj -o %t.o +; RUN: llvm-dwarfdump %t.o | FileCheck %s + +; CHECK-LABEL: DW_TAG_inlined_subroutine + +; Test if More than 2 member location list is printed (for pointer pointing to aggregate) +; CHECK-LABEL: DW_TAG_formal_parameter +; CHECK-NEXT: DW_AT_location +; CHECK-NEXT: : DW_OP_implicit_pointer [[DIE1:0x.+]] +0 +; CHECK-NEXT: : DW_OP_implicit_pointer [[DIE2:0x.+]] +0) +; CHECK-NEXT: DW_AT_abstract_origin ({{0x.+}} "ptr") + +; Below is the original test case this IR is generated from +;--------------------------- +;static const char *b = "opq"; +;volatile int v; +;static inline void foo(int *ptr) { +; (*ptr)++; +; v++; +; ptr++; +; (*ptr)++; +; v++; +;} +; +;int main() { +; int arr[2] = {1, 2}; +; v++; +; foo(arr); +; return arr[0] + arr[1] - 5; +;} +;--------------------------- + +; ModuleID = 'dwarfdump-implicit_pointer_sroa_inline.c' +source_filename = "dwarfdump-implicit_pointer_sroa_inline.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@v = common dso_local global i32 0, align 4, !dbg !0 + +; Function Attrs: nounwind uwtable +define dso_local i32 @main() local_unnamed_addr #0 !dbg !12 { +entry: + %0 = load volatile i32, i32* @v, align 4, !dbg !20 + %inc = add nsw i32 %0, 1, !dbg !20 + store volatile i32 %inc, i32* @v, align 4, !dbg !20 + call void @llvm.dbg.value(metadata i32 2, metadata !25, metadata !DIExpression(DW_OP_LLVM_implicit_pointer)), !dbg !31 + %1 = load volatile i32, i32* @v, align 4, !dbg !33 + %inc1.i = add nsw i32 %1, 1, !dbg !33 + store volatile i32 %inc1.i, i32* @v, align 4, !dbg !33 + call void @llvm.dbg.value(metadata i32 3, metadata !25, metadata !DIExpression(DW_OP_LLVM_implicit_pointer)), !dbg !34 + %2 = load volatile i32, i32* @v, align 4, !dbg !34 + %inc3.i = add nsw i32 %2, 1, !dbg !34 + store volatile i32 %inc3.i, i32* @v, align 4, !dbg !34 + ret i32 0, !dbg !35 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "v", scope: !2, file: !3, line: 14, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "dwarfdump-implicit_pointer_sroa_inline.c", directory: "/dir", checksumkind: CSK_MD5, checksum: "f9bbaee6b152b3bc05125796b573408a") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 10.0.0"} +!12 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 23, type: !13, scopeLine: 23, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !15) +!13 = !DISubroutineType(types: !14) +!14 = !{!7} +!15 = !{!16} +!16 = !DILocalVariable(name: "arr", scope: !12, file: !3, line: 24, type: !17) +!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 64, elements: !18) +!18 = !{!19} +!19 = !DISubrange(count: 2) +!20 = !DILocation(line: 25, column: 4, scope: !12) +!21 = !{!22, !22, i64 0} +!22 = !{!"int", !23, i64 0} +!23 = !{!"omnipotent char", !24, i64 0} +!24 = !{!"Simple C/C++ TBAA"} +!25 = !DILocalVariable(name: "ptr", arg: 1, scope: !26, file: !3, line: 15, type: !29) +!26 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 15, type: !27, scopeLine: 15, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !30) +!27 = !DISubroutineType(types: !28) +!28 = !{null, !29} +!29 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!30 = !{!25} +!31 = !DILocation(line: 0, scope: !26, inlinedAt: !32) +!32 = distinct !DILocation(line: 26, column: 3, scope: !12) +!33 = !DILocation(line: 17, column: 4, scope: !26, inlinedAt: !32) +!34 = !DILocation(line: 20, column: 4, scope: !26, inlinedAt: !32) +!35 = !DILocation(line: 27, column: 3, scope: !12)