mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-08 18:30:04 +00:00
[DWARF] Fix a few corner cases in expression emission
Summary: I noticed an object file with `DW_OP_reg4 DW_OP_breg4 0` as a DWARF expression, which I traced to a missing break (and `++I`) in this code snippet. While I was at it, I also added support for a few other corner cases along the same lines that I could think of. Test Plan: Hand-crafted test case to exercises these cases is included. Reviewers: echristo, dblaikie, aprantl Reviewed By: aprantl Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D10302 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239380 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cfd8f11d48
commit
b4863a99c9
@ -1562,6 +1562,8 @@ void DwarfDebug::emitDebugLoc() {
|
|||||||
Asm->OutStreamer->EmitLabel(List.Label);
|
Asm->OutStreamer->EmitLabel(List.Label);
|
||||||
const DwarfCompileUnit *CU = List.CU;
|
const DwarfCompileUnit *CU = List.CU;
|
||||||
for (const auto &Entry : DebugLocs.getEntries(List)) {
|
for (const auto &Entry : DebugLocs.getEntries(List)) {
|
||||||
|
if (Entry.BeginSym == Entry.EndSym)
|
||||||
|
continue;
|
||||||
// Set up the range. This range is relative to the entry point of the
|
// Set up the range. This range is relative to the entry point of the
|
||||||
// compile unit. This is a hard coded 0 for low_pc when we're emitting
|
// compile unit. This is a hard coded 0 for low_pc when we're emitting
|
||||||
// ranges, or the DW_AT_low_pc on the compile unit otherwise.
|
// ranges, or the DW_AT_low_pc on the compile unit otherwise.
|
||||||
|
@ -65,6 +65,11 @@ void DwarfExpression::AddShr(unsigned ShiftBy) {
|
|||||||
EmitOp(dwarf::DW_OP_shr);
|
EmitOp(dwarf::DW_OP_shr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfExpression::AddOpStackValue() {
|
||||||
|
if (DwarfVersion >= 4)
|
||||||
|
EmitOp(dwarf::DW_OP_stack_value);
|
||||||
|
}
|
||||||
|
|
||||||
bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) {
|
bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) {
|
||||||
if (isFrameRegister(MachineReg)) {
|
if (isFrameRegister(MachineReg)) {
|
||||||
// If variable offset is based in frame register then use fbreg.
|
// If variable offset is based in frame register then use fbreg.
|
||||||
@ -172,16 +177,14 @@ void DwarfExpression::AddSignedConstant(int Value) {
|
|||||||
// value, so the producers and consumers started to rely on heuristics
|
// value, so the producers and consumers started to rely on heuristics
|
||||||
// to disambiguate the value vs. location status of the expression.
|
// to disambiguate the value vs. location status of the expression.
|
||||||
// See PR21176 for more details.
|
// See PR21176 for more details.
|
||||||
if (DwarfVersion >= 4)
|
AddOpStackValue();
|
||||||
EmitOp(dwarf::DW_OP_stack_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DwarfExpression::AddUnsignedConstant(unsigned Value) {
|
void DwarfExpression::AddUnsignedConstant(unsigned Value) {
|
||||||
EmitOp(dwarf::DW_OP_constu);
|
EmitOp(dwarf::DW_OP_constu);
|
||||||
EmitUnsigned(Value);
|
EmitUnsigned(Value);
|
||||||
// cf. comment in DwarfExpression::AddSignedConstant().
|
// cf. comment in DwarfExpression::AddSignedConstant().
|
||||||
if (DwarfVersion >= 4)
|
AddOpStackValue();
|
||||||
EmitOp(dwarf::DW_OP_stack_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned getOffsetOrZero(unsigned OffsetInBits,
|
static unsigned getOffsetOrZero(unsigned OffsetInBits,
|
||||||
@ -212,15 +215,30 @@ bool DwarfExpression::AddMachineRegExpression(const DIExpression *Expr,
|
|||||||
getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
|
getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
|
||||||
}
|
}
|
||||||
case dwarf::DW_OP_plus: {
|
case dwarf::DW_OP_plus: {
|
||||||
// [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset].
|
|
||||||
auto N = I.getNext();
|
auto N = I.getNext();
|
||||||
|
unsigned Offset = I->getArg(0);
|
||||||
|
// First combine all DW_OP_plus until we hit either a DW_OP_deref or a
|
||||||
|
// DW_OP_bit_piece
|
||||||
|
while (N != E && N->getOp() == dwarf::DW_OP_plus) {
|
||||||
|
Offset += N->getArg(0);
|
||||||
|
++I;
|
||||||
|
N = I.getNext();
|
||||||
|
}
|
||||||
if (N != E && N->getOp() == dwarf::DW_OP_deref) {
|
if (N != E && N->getOp() == dwarf::DW_OP_deref) {
|
||||||
unsigned Offset = I->getArg(0);
|
// [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset].
|
||||||
ValidReg = AddMachineRegIndirect(MachineReg, Offset);
|
ValidReg = AddMachineRegIndirect(MachineReg, Offset);
|
||||||
std::advance(I, 2);
|
std::advance(I, 2);
|
||||||
break;
|
} else {
|
||||||
} else
|
assert ((N == E) || (N->getOp() == dwarf::DW_OP_bit_piece));
|
||||||
ValidReg = AddMachineRegPiece(MachineReg);
|
if (Offset == 0) {
|
||||||
|
ValidReg = AddMachineRegPiece(MachineReg);
|
||||||
|
} else {
|
||||||
|
ValidReg = AddMachineRegIndirect(MachineReg, Offset);
|
||||||
|
AddOpStackValue();
|
||||||
|
}
|
||||||
|
++I;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case dwarf::DW_OP_deref: {
|
case dwarf::DW_OP_deref: {
|
||||||
// [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
|
// [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
|
||||||
@ -237,6 +255,7 @@ bool DwarfExpression::AddMachineRegExpression(const DIExpression *Expr,
|
|||||||
|
|
||||||
// Emit remaining elements of the expression.
|
// Emit remaining elements of the expression.
|
||||||
AddExpression(I, E, PieceOffsetInBits);
|
AddExpression(I, E, PieceOffsetInBits);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,9 @@ public:
|
|||||||
bool AddMachineRegPiece(unsigned MachineReg, unsigned PieceSizeInBits = 0,
|
bool AddMachineRegPiece(unsigned MachineReg, unsigned PieceSizeInBits = 0,
|
||||||
unsigned PieceOffsetInBits = 0);
|
unsigned PieceOffsetInBits = 0);
|
||||||
|
|
||||||
|
/// Emit a DW_OP_stack_value
|
||||||
|
void AddOpStackValue();
|
||||||
|
|
||||||
/// Emit a signed constant.
|
/// Emit a signed constant.
|
||||||
void AddSignedConstant(int Value);
|
void AddSignedConstant(int Value);
|
||||||
/// Emit an unsigned constant.
|
/// Emit an unsigned constant.
|
||||||
|
110
test/DebugInfo/expressions.ll
Normal file
110
test/DebugInfo/expressions.ll
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
; REQUIRES: object-emission
|
||||||
|
; RUN: %llc_dwarf -mtriple x86_64-apple-darwin14.0.0-elf -filetype=obj %s -o %t
|
||||||
|
; RUN: %llc_dwarf -mtriple x86_64-apple-darwin14.0.0-elf -O0 -filetype=obj %s -o %t0
|
||||||
|
; RUN: llvm-dwarfdump -debug-dump=loc %t | FileCheck %s
|
||||||
|
; RUN: llvm-dwarfdump -debug-dump=loc %t0 | FileCheck -check-prefix CHECK-O0 %s
|
||||||
|
|
||||||
|
; CHECK: 0x00000000: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK: Ending address offset: 0x[[END:[0-9a-f]+]]
|
||||||
|
; CHECK: Location description:
|
||||||
|
; CHECK-NOT: 75 00 55
|
||||||
|
; CHECK-SAME: 55
|
||||||
|
; CHECK: 0x00000023: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK: Ending address offset: 0x{{.*}}[[END]]
|
||||||
|
; CHECK: Location description: 75 08 9f
|
||||||
|
; CHECK: 0x00000048: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK: Ending address offset: 0x{{.*}}[[END]]
|
||||||
|
; CHECK: Location description: 75 10 9f
|
||||||
|
; CHECK: 0x0000006d: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK: Ending address offset: 0x{{.*}}[[END]]
|
||||||
|
; CHECK: Location description: 75 18
|
||||||
|
|
||||||
|
|
||||||
|
; CHECK-O0: 0x00000000: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK-O0: Ending address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Location description: 55
|
||||||
|
; CHECK-O0: Beginning address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Location description: 54
|
||||||
|
; CHECK-O0: Beginning address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000025
|
||||||
|
; CHECK-O0: Location description: 77 78 23 00
|
||||||
|
; CHECK-O0: 0x0000004c: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK-O0: Ending address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Location description: 75 08 9f
|
||||||
|
; CHECK-O0: Beginning address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Location description: 74 08 9f
|
||||||
|
; CHECK-O0: Beginning address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000025
|
||||||
|
; CHECK-O0: Location description: 77 78 23 08
|
||||||
|
; CHECK-O0: 0x0000009c: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK-O0: Ending address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Location description: 75 10 9f
|
||||||
|
; CHECK-O0: Beginning address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Location description: 74 10 9f
|
||||||
|
; CHECK-O0: Beginning address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000025
|
||||||
|
; CHECK-O0: Location description: 77 78 23 08 23 08
|
||||||
|
; CHECK-O0: 0x000000ee: Beginning address offset: 0x0000000000000000
|
||||||
|
; CHECK-O0: Ending address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Location description: 75 18
|
||||||
|
; CHECK-O0: Beginning address offset: 0x000000000000001b
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Location description: 74 18
|
||||||
|
; CHECK-O0: Beginning address offset: 0x0000000000000024
|
||||||
|
; CHECK-O0: Ending address offset: 0x0000000000000025
|
||||||
|
; CHECK-O0: Location description: 77 78 23 10 23 08 06
|
||||||
|
|
||||||
|
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
|
||||||
|
|
||||||
|
define float @foo(float* %args, float *%args2)
|
||||||
|
{
|
||||||
|
call void @llvm.dbg.value(metadata float* %args, i64 0, metadata !11, metadata !12), !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args, i64 0, metadata !13, metadata !14), !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args, i64 0, metadata !15, metadata !16), !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args, i64 0, metadata !17, metadata !18), !dbg !19
|
||||||
|
%a = load float, float* %args, !dbg !19
|
||||||
|
%bptr = getelementptr float, float* %args, i32 1, !dbg !19
|
||||||
|
%b = load float, float* %bptr, !dbg !19
|
||||||
|
%cptr = getelementptr float, float* %args, i32 2, !dbg !19
|
||||||
|
%c = load float, float* %cptr, !dbg !19
|
||||||
|
%dptr = getelementptr float, float* %args, i32 3, !dbg !19
|
||||||
|
%d = load float, float* %dptr, !dbg !19
|
||||||
|
%ret1 = fadd float %a, %b, !dbg !19
|
||||||
|
%ret2 = fadd float %c, %d, !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata !11, metadata !12), !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata !13, metadata !14), !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata !15, metadata !16), !dbg !19
|
||||||
|
call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata !17, metadata !18), !dbg !19
|
||||||
|
%ret = fsub float %ret1, %ret2, !dbg !19
|
||||||
|
ret float %ret, !dbg !19
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes #0 = { nounwind readnone }
|
||||||
|
|
||||||
|
!llvm.module.flags = !{!0, !1}
|
||||||
|
!llvm.dbg.cu = !{!2}
|
||||||
|
|
||||||
|
!0 = !{i32 2, !"Dwarf Version", i32 4}
|
||||||
|
!1 = !{i32 1, !"Debug Info Version", i32 3}
|
||||||
|
|
||||||
|
!2 = !DICompileUnit(language: DW_LANG_C89, file: !3, producer: "byHand", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !4, retainedTypes: !4, subprograms: !5, globals: !4, imports: !4)
|
||||||
|
!3 = !DIFile(filename: "expressions", directory: ".")
|
||||||
|
!4 = !{}
|
||||||
|
!5 = !{!6}
|
||||||
|
!6 = !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !3, type: !7, isLocal: false, isDefinition: true, isOptimized: true, function: float (float*, float*)* @foo, variables: !4)
|
||||||
|
!7 = !DISubroutineType(types: !8)
|
||||||
|
!8 = !{!10, !10}
|
||||||
|
!9 = !DIBasicType(name: "float", size: 4, align: 4, encoding: DW_ATE_float)
|
||||||
|
!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64)
|
||||||
|
!11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "a", arg: 1, scope: !6, file: !3, line: 1, type: !10)
|
||||||
|
!12 = !DIExpression(DW_OP_plus, 0)
|
||||||
|
!13 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "b", arg: 2, scope: !6, file: !3, line: 1, type: !10)
|
||||||
|
!14 = !DIExpression(DW_OP_plus, 8)
|
||||||
|
!15 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "c", arg: 3, scope: !6, file: !3, line: 1, type: !10)
|
||||||
|
!16 = !DIExpression(DW_OP_plus, 8, DW_OP_plus, 8)
|
||||||
|
!17 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "d", arg: 4, scope: !6, file: !3, line: 1, type: !9)
|
||||||
|
!18 = !DIExpression(DW_OP_plus, 16, DW_OP_plus, 8, DW_OP_deref)
|
||||||
|
!19 = !DILocation(line: 1, scope: !6)
|
Loading…
Reference in New Issue
Block a user