From b5fced732416c1d9a2ffa1980ca1af88c06edd83 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 9 May 2017 19:59:29 +0000 Subject: [PATCH] [codeview] Check for a DIExpression offset for local variables Fixes inalloca parameters, which previously all pointed to the same offset. Extend the test to use llvm-readobj so that we can test the offset in a readable way. llvm-svn: 302578 --- llvm/include/llvm/IR/DebugInfoMetadata.h | 4 ++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 10 ++++- llvm/lib/IR/DebugInfoMetadata.cpp | 18 ++++++++ .../DebugInfo/X86/dbg-declare-inalloca.ll | 41 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 0331d5229e7f..36bc5ce91b69 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2276,6 +2276,10 @@ public: /// Append \p Ops with operations to apply the \p Offset. static void appendOffset(SmallVectorImpl &Ops, int64_t Offset); + /// If this is a constant offset, extract it. If there is no expression, + /// return true with an offset of zero. + bool extractIfOffset(int64_t &Offset) const; + /// Constants for DIExpression::prepend. enum { NoDeref = false, WithDeref = true, WithStackValue = true }; diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 87b45c001de4..9d60fff3bccc 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -888,13 +888,21 @@ void CodeViewDebug::collectVariableInfoFromMFTable( if (!Scope) continue; + // If the variable has an attached offset expression, extract it. + // FIXME: Try to handle DW_OP_deref as well. + int64_t ExprOffset = 0; + if (VI.Expr) + if (!VI.Expr->extractIfOffset(ExprOffset)) + continue; + // Get the frame register used and the offset. unsigned FrameReg = 0; int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg); uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg); // Calculate the label ranges. - LocalVarDefRange DefRange = createDefRangeMem(CVReg, FrameOffset); + LocalVarDefRange DefRange = + createDefRangeMem(CVReg, FrameOffset + ExprOffset); for (const InsnRange &Range : Scope->getRanges()) { const MCSymbol *Begin = getLabelBeforeInsn(Range.first); const MCSymbol *End = getLabelAfterInsn(Range.second); diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index cdbe237766a3..e6c49cad0722 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -672,6 +672,24 @@ void DIExpression::appendOffset(SmallVectorImpl &Ops, } } +bool DIExpression::extractIfOffset(int64_t &Offset) const { + if (getNumElements() == 0) { + Offset = 0; + return true; + } + if (getNumElements() != 2) + return false; + if (Elements[0] == dwarf::DW_OP_plus) { + Offset = Elements[1]; + return true; + } + if (Elements[0] == dwarf::DW_OP_minus) { + Offset = -Elements[1]; + return true; + } + return false; +} + DIExpression *DIExpression::prepend(const DIExpression *Expr, bool Deref, int64_t Offset, bool StackValue) { SmallVector Ops; diff --git a/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll b/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll index 5301cd661467..e3f5c7e629b8 100644 --- a/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll +++ b/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll @@ -1,5 +1,6 @@ ; RUN: llc -O0 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DEBUG ; RUN: llc < %s | FileCheck %s +; RUN: llc -filetype=obj -O0 < %s | llvm-readobj -codeview - | FileCheck %s --check-prefix=OBJ ; IR generated by the following source: ; struct NonTrivial { @@ -54,6 +55,46 @@ ; CHECK: .asciz "c" ; CHECK: .cv_def_range [[start]] [[end]] +; OBJ-LABEL: ProcStart { +; OBJ: Kind: S_GPROC32_ID (0x1147) +; OBJ: DisplayName: f +; OBJ: } +; OBJ: Local { +; OBJ: Type: NonTrivial (0x1007) +; OBJ: Flags [ (0x1) +; OBJ: IsParameter (0x1) +; OBJ: ] +; OBJ: VarName: a +; OBJ: } +; OBJ: DefRangeRegisterRel { +; OBJ: BaseRegister: 21 +; OBJ: BasePointerOffset: 12 +; OBJ: } +; OBJ: Local { +; OBJ: Type: int (0x74) +; OBJ: Flags [ (0x1) +; OBJ: IsParameter (0x1) +; OBJ: ] +; OBJ: VarName: b +; OBJ: } +; OBJ: DefRangeRegisterRel { +; OBJ: BaseRegister: 21 +; OBJ: BasePointerOffset: 16 +; OBJ: } +; FIXME: Retain unused. +; OBJ: Local { +; OBJ: Type: int (0x74) +; OBJ: Flags [ (0x1) +; OBJ: IsParameter (0x1) +; OBJ: ] +; OBJ: VarName: c +; OBJ: } +; OBJ: DefRangeRegisterRel { +; OBJ: BaseRegister: 21 +; OBJ: BasePointerOffset: 24 +; OBJ: } +; OBJ-LABEL: ProcEnd { +; OBJ: } ; ModuleID = 't.cpp'