From 9863705ff71972caa5c54bddfc0e7bc1cf2f7311 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 30 Aug 2017 20:51:20 +0000 Subject: [PATCH] SelectionDAG: Emit correct debug info for multi-register function arguments. Previously we would just describe the first register and then call it quits. This patch emits fragment expressions for each register. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312169 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../SelectionDAG/SelectionDAGBuilder.cpp | 21 +++++ test/DebugInfo/ARM/sdag-split-arg.ll | 77 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 test/DebugInfo/ARM/sdag-split-arg.ll diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 1371f52187c..4da821e6c55 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -45,6 +45,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/GlobalVariable.h" @@ -4808,6 +4809,26 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue( // Check if ValueMap has reg number. DenseMap::iterator VMI = FuncInfo.ValueMap.find(V); if (VMI != FuncInfo.ValueMap.end()) { + auto *Ty = V->getType(); + const auto &TLI = DAG.getTargetLoweringInfo(); + EVT VT = TLI.getValueType(DAG.getDataLayout(), Ty); + unsigned NumRegs = TLI.getNumRegisters(Ty->getContext(), VT); + if (NumRegs > 1) { + // The registers are guaranteed to be allocated in sequence. + unsigned Offset = 0; + MVT RegisterVT = TLI.getRegisterType(Ty->getContext(), VT); + unsigned RegisterSize = RegisterVT.getSizeInBits(); + for (unsigned I = 0; I != NumRegs; ++I) { + Op = MachineOperand::CreateReg(VMI->second + I, false); + auto *FragmentExpr = DIExpression::createFragmentExpression( + Expr, Offset, RegisterSize); + FuncInfo.ArgDbgValues.push_back( + BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), IsDbgDeclare, + Op->getReg(), Variable, FragmentExpr)); + Offset += RegisterSize; + } + return true; + } Op = MachineOperand::CreateReg(VMI->second, false); IsIndirect = IsDbgDeclare; } diff --git a/test/DebugInfo/ARM/sdag-split-arg.ll b/test/DebugInfo/ARM/sdag-split-arg.ll new file mode 100644 index 00000000000..9f13d4f8486 --- /dev/null +++ b/test/DebugInfo/ARM/sdag-split-arg.ll @@ -0,0 +1,77 @@ +; RUN: llc -filetype=asm %s -o - | FileCheck %s +; Test large integral function arguments passed in multiple registers. +; +; Generated from (-Os): +; +; signed long long g; +; void write(signed long long offset); +; signed long long foo(signed long long offset) { +; if (offset != g) +; write(offset); +; return offset; +; } +source_filename = "test.ii" +target datalayout = "e-m:o-p:32:32-i64:64-a:0:32-n32-S128" +target triple = "thumbv7k-apple-watchos2.0.0" + +@g = local_unnamed_addr global i64 0, align 8, !dbg !0 + +; Function Attrs: optsize ssp +define i64 @_Z3foox(i64 returned) local_unnamed_addr #0 !dbg !13 { + tail call void @llvm.dbg.value(metadata i64 %0, metadata !17, metadata !DIExpression()), !dbg !18 + ; CHECK: @DEBUG_VALUE: foo:offset <- [DW_OP_LLVM_fragment 0 32] %R5 + ; CHECK: @DEBUG_VALUE: foo:offset <- [DW_OP_LLVM_fragment 32 32] %R4 + + %2 = load i64, i64* @g, align 8, !dbg !19, !tbaa !21 + %3 = icmp eq i64 %2, %0, !dbg !19 + br i1 %3, label %5, label %4, !dbg !25 + +;