Index: llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -40,6 +40,7 @@ class Constant; class ConstrainedFPIntrinsic; class DataLayout; +class DIBuilder; class Instruction; class MachineBasicBlock; class MachineFunction; Index: llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -405,6 +405,17 @@ const MDNode *Variable, const MDNode *Expr); + /// Build and insert a DBG_VALUE instructions specifying that the dereferenced + /// value of \p Variable is given by \p V (suitably modified by \p Expr). + MachineInstrBuilder buildDerefDbgValue(const Value *V, const MDNode *Variable, + const MDNode *Expr); + + /// Build and insert a DBG_VALUE instructions specifying that the dereferenced + /// value of \p Variable is given by \p V (suitably modified by \p Expr). + MachineInstrBuilder buildDerefDbgValue(const MDNode *DerefVar, + const MDNode *Variable, + const MDNode *Expr); + /// Build and insert a DBG_LABEL instructions specifying that \p Label is /// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label". MachineInstrBuilder buildDbgLabel(const MDNode *Label); Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -44,6 +44,7 @@ #include "llvm/IR/CFG.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/DerivedTypes.h" @@ -56,6 +57,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" @@ -1909,24 +1911,62 @@ // This form of DBG_VALUE is target-independent. const DbgValueInst &DI = cast(CI); const Value *V = DI.getValue(); + const DIExpression *DE = DI.getExpression(); assert(DI.getVariable()->isValidLocationForIntrinsic( MIRBuilder.getDebugLoc()) && "Expected inlined-at fields to agree"); + DILocalVariable *Var = DI.getVariable(); + DILocalVariable *PtrVar = nullptr; + Module *Mod = const_cast(CI.getModule()); + + DIBuilder DIB(*Mod, /*AllowUnresolved*/ false); + + unsigned Level = DE->implicitPointerCount(); + SmallVector PtrVars; + if (Level > 0) { + DIScope *Scope = DI.getDebugLoc()->getScope(); + DIType *Type = DI.getVariable()->getType(); + PtrVar = Var; + PtrVars.push_back(PtrVar); + unsigned Count = Level; + while (Count-- > 0) { + if (DIDerivedType *DT = dyn_cast(Type)) + Type = DT->getBaseType(); + uint32_t AlignInBits = DI.getVariable()->getAlignInBytes(); + Var = DIB.createImplicitTempVariable(Scope, Type, AlignInBits); + PtrVars.push_back(Var); + } + Var = PtrVars[Level]; + DE = DIExpression::get(DE->getContext(), {}); + } else { + Var = DI.getVariable(); + DE = DI.getExpression(); + } + if (!V) { // Currently the optimizer can produce this; insert an undef to // help debugging. Probably the optimizer should not do this. - MIRBuilder.buildIndirectDbgValue(0, DI.getVariable(), DI.getExpression()); + MIRBuilder.buildIndirectDbgValue(0, Var, DE); } else if (const auto *CI = dyn_cast(V)) { - MIRBuilder.buildConstDbgValue(*CI, DI.getVariable(), DI.getExpression()); + MIRBuilder.buildConstDbgValue(*CI, Var, DE); } else { for (Register Reg : getOrCreateVRegs(*V)) { // FIXME: This does not handle register-indirect values at offset 0. The // direct/indirect thing shouldn't really be handled by something as // implicit as reg+noreg vs reg+imm in the first place, but it seems // pretty baked in right now. - MIRBuilder.buildDirectDbgValue(Reg, DI.getVariable(), DI.getExpression()); + MIRBuilder.buildDirectDbgValue(Reg, Var, DE); } } + unsigned Count = Level; + while (Count-- > 0) { + SmallVector Ops; + Ops.push_back(dwarf::DW_OP_LLVM_implicit_pointer); + DIExpression *DIExprNew = DIExpression::get(DE->getContext(), Ops); + + MIRBuilder.buildDerefDbgValue(PtrVars[Count + 1], PtrVars[Count], + DIExprNew); + } return true; } case Intrinsic::uadd_with_overflow: Index: llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -114,6 +114,49 @@ return insertInstr(MIB); } +MachineInstrBuilder MachineIRBuilder::buildDerefDbgValue(const Value *Derefval, + const MDNode *Variable, + const MDNode *Expr) { + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + assert( + cast(Variable)->isValidLocationForIntrinsic(getDL()) && + "Expected inlined-at fields to agree"); + auto MIB = buildInstr(TargetOpcode::DBG_VALUE); + if (const auto *MDV = dyn_cast(Derefval)) { + if (const auto *LDV = dyn_cast(MDV->getMetadata())) { + MIB.addImplicitPtrMetadata(LDV); + } + } else if (auto *CI = dyn_cast(Derefval)) { + if (CI->getBitWidth() > 64) + MIB.addCImm(CI); + else + MIB.addImm(CI->getZExtValue()); + } else if (auto *CFP = dyn_cast(Derefval)) { + MIB.addFPImm(CFP); + } else { + // Insert %noreg if we didn't find a usable constant and had to drop it. + MIB.addReg(0U); + } + + return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr); +} + +MachineInstrBuilder MachineIRBuilder::buildDerefDbgValue(const MDNode *DerefVar, + const MDNode *Variable, + const MDNode *Expr) { + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + assert( + cast(Variable)->isValidLocationForIntrinsic(getDL()) && + "Expected inlined-at fields to agree"); + auto MIB = buildInstr(TargetOpcode::DBG_VALUE); + + MIB.addImplicitPtrMetadata(DerefVar); + + return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr); +} + MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) { assert(isa(Label) && "not a label"); assert(cast(Label)->isValidLocationForIntrinsic(State.DL) && Index: llvm/test/DebugInfo/X86/implicit_pointer_global.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/implicit_pointer_global.ll @@ -0,0 +1,99 @@ +; RUN: llc %s -global-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)