Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 16e81ea

Browse files
TNorthoverahmedbougacha
authored andcommitted
GlobalISel: support debug intrinsics.
The translation scheme is mostly cribbed from FastISel, and it's not entirely convincing semantically. But it does seem to work in the common cases and allow variables to be printed so it can't be all wrong. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293228 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit ac8bbff)
1 parent 1840e45 commit 16e81ea

File tree

5 files changed

+192
-38
lines changed

5 files changed

+192
-38
lines changed

include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class MachineIRBuilder {
108108
/// Set the debug location to \p DL for all the next build instructions.
109109
void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
110110

111+
/// Get the current instruction's debug location.
112+
DebugLoc getDebugLoc() { return DL; }
113+
111114
/// Build and insert <empty> = \p Opcode <empty>.
112115
/// The insertion point is the one set by the last call of either
113116
/// setBasicBlock or setMI.
@@ -127,6 +130,29 @@ class MachineIRBuilder {
127130
/// Insert an existing instruction at the insertion point.
128131
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB);
129132

133+
/// Build and insert a DBG_VALUE instruction expressing the fact that the
134+
/// associated \p Variable lives in \p Reg (suitably modified by \p Expr).
135+
MachineInstrBuilder buildDirectDbgValue(unsigned Reg, const MDNode *Variable,
136+
const MDNode *Expr);
137+
138+
/// Build and insert a DBG_VALUE instruction expressing the fact that the
139+
/// associated \p Variable lives in memory at \p Reg + \p Offset (suitably
140+
/// modified by \p Expr).
141+
MachineInstrBuilder buildIndirectDbgValue(unsigned Reg, unsigned Offset,
142+
const MDNode *Variable,
143+
const MDNode *Expr);
144+
/// Build and insert a DBG_VALUE instruction expressing the fact that the
145+
/// associated \p Variable lives in the stack slot specified by \p FI
146+
/// (suitably modified by \p Expr).
147+
MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable,
148+
const MDNode *Expr);
149+
150+
/// Build and insert a DBG_VALUE instructions specifying that \p Variable is
151+
/// given by \p C (suitably modified by \p Expr).
152+
MachineInstrBuilder buildConstDbgValue(const Constant &C, unsigned Offset,
153+
const MDNode *Variable,
154+
const MDNode *Expr);
155+
130156
/// Build and insert \p Res<def> = G_FRAME_INDEX \p Idx
131157
///
132158
/// G_FRAME_INDEX materializes the address of an alloca value or other

lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/CodeGen/MachineRegisterInfo.h"
2323
#include "llvm/CodeGen/TargetPassConfig.h"
2424
#include "llvm/IR/Constant.h"
25+
#include "llvm/IR/DebugInfo.h"
2526
#include "llvm/IR/Function.h"
2627
#include "llvm/IR/GetElementPtrTypeIterator.h"
2728
#include "llvm/IR/IntrinsicInst.h"
@@ -522,12 +523,60 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
522523
switch (ID) {
523524
default:
524525
break;
525-
case Intrinsic::dbg_declare:
526-
case Intrinsic::dbg_value:
527-
// FIXME: these obviously need to be supported properly.
528-
if (!TPC->isGlobalISelAbortEnabled())
529-
MF->getProperties().set(MachineFunctionProperties::Property::FailedISel);
526+
case Intrinsic::dbg_declare: {
527+
const DbgDeclareInst &DI = cast<DbgDeclareInst>(CI);
528+
assert(DI.getVariable() && "Missing variable");
529+
530+
const Value *Address = DI.getAddress();
531+
if (!Address || isa<UndefValue>(Address)) {
532+
DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
533+
return true;
534+
}
535+
536+
unsigned Reg = getOrCreateVReg(*Address);
537+
auto RegDef = MRI->def_instr_begin(Reg);
538+
assert(DI.getVariable()->isValidLocationForIntrinsic(
539+
MIRBuilder.getDebugLoc()) &&
540+
"Expected inlined-at fields to agree");
541+
542+
if (RegDef != MRI->def_instr_end() &&
543+
RegDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
544+
MIRBuilder.buildFIDbgValue(RegDef->getOperand(1).getIndex(),
545+
DI.getVariable(), DI.getExpression());
546+
} else
547+
MIRBuilder.buildDirectDbgValue(Reg, DI.getVariable(), DI.getExpression());
548+
return true;
549+
}
550+
case Intrinsic::dbg_value: {
551+
// This form of DBG_VALUE is target-independent.
552+
const DbgValueInst &DI = cast<DbgValueInst>(CI);
553+
const Value *V = DI.getValue();
554+
assert(DI.getVariable()->isValidLocationForIntrinsic(
555+
MIRBuilder.getDebugLoc()) &&
556+
"Expected inlined-at fields to agree");
557+
if (!V) {
558+
// Currently the optimizer can produce this; insert an undef to
559+
// help debugging. Probably the optimizer should not do this.
560+
MIRBuilder.buildIndirectDbgValue(0, DI.getOffset(), DI.getVariable(),
561+
DI.getExpression());
562+
} else if (const auto *CI = dyn_cast<Constant>(V)) {
563+
MIRBuilder.buildConstDbgValue(*CI, DI.getOffset(), DI.getVariable(),
564+
DI.getExpression());
565+
} else {
566+
unsigned Reg = getOrCreateVReg(*V);
567+
// FIXME: This does not handle register-indirect values at offset 0. The
568+
// direct/indirect thing shouldn't really be handled by something as
569+
// implicit as reg+noreg vs reg+imm in the first palce, but it seems
570+
// pretty baked in right now.
571+
if (DI.getOffset() != 0)
572+
MIRBuilder.buildIndirectDbgValue(Reg, DI.getOffset(), DI.getVariable(),
573+
DI.getExpression());
574+
else
575+
MIRBuilder.buildDirectDbgValue(Reg, DI.getVariable(),
576+
DI.getExpression());
577+
}
530578
return true;
579+
}
531580
case Intrinsic::uadd_with_overflow:
532581
return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDE, MIRBuilder);
533582
case Intrinsic::sadd_with_overflow:

lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/CodeGen/MachineInstr.h"
1616
#include "llvm/CodeGen/MachineInstrBuilder.h"
1717
#include "llvm/CodeGen/MachineRegisterInfo.h"
18+
#include "llvm/IR/DebugInfo.h"
1819
#include "llvm/Target/TargetInstrInfo.h"
1920
#include "llvm/Target/TargetOpcodes.h"
2021
#include "llvm/Target/TargetSubtargetInfo.h"
@@ -82,6 +83,66 @@ MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
8283
return MIB;
8384
}
8485

86+
MachineInstrBuilder MachineIRBuilder::buildDirectDbgValue(
87+
unsigned Reg, const MDNode *Variable, const MDNode *Expr) {
88+
assert(isa<DILocalVariable>(Variable) && "not a variable");
89+
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
90+
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
91+
"Expected inlined-at fields to agree");
92+
return buildInstr(TargetOpcode::DBG_VALUE)
93+
.addReg(Reg, RegState::Debug)
94+
.addReg(0, RegState::Debug)
95+
.addMetadata(Variable)
96+
.addMetadata(Expr);
97+
}
98+
99+
MachineInstrBuilder MachineIRBuilder::buildIndirectDbgValue(
100+
unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) {
101+
assert(isa<DILocalVariable>(Variable) && "not a variable");
102+
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
103+
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
104+
"Expected inlined-at fields to agree");
105+
return buildInstr(TargetOpcode::DBG_VALUE)
106+
.addReg(Reg, RegState::Debug)
107+
.addImm(Offset)
108+
.addMetadata(Variable)
109+
.addMetadata(Expr);
110+
}
111+
112+
MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
113+
const MDNode *Variable,
114+
const MDNode *Expr) {
115+
assert(isa<DILocalVariable>(Variable) && "not a variable");
116+
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
117+
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
118+
"Expected inlined-at fields to agree");
119+
return buildInstr(TargetOpcode::DBG_VALUE)
120+
.addFrameIndex(FI)
121+
.addImm(0)
122+
.addMetadata(Variable)
123+
.addMetadata(Expr);
124+
}
125+
126+
MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
127+
unsigned Offset,
128+
const MDNode *Variable,
129+
const MDNode *Expr) {
130+
assert(isa<DILocalVariable>(Variable) && "not a variable");
131+
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
132+
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
133+
"Expected inlined-at fields to agree");
134+
auto MIB = buildInstr(TargetOpcode::DBG_VALUE);
135+
if (auto *CI = dyn_cast<ConstantInt>(&C)) {
136+
if (CI->getBitWidth() > 64)
137+
MIB.addCImm(CI);
138+
else
139+
MIB.addImm(CI->getZExtValue());
140+
} else
141+
MIB.addFPImm(&cast<ConstantFP>(C));
142+
143+
return MIB.addImm(Offset).addMetadata(Variable).addMetadata(Expr);
144+
}
145+
85146
MachineInstrBuilder MachineIRBuilder::buildFrameIndex(unsigned Res, int Idx) {
86147
assert(MRI->getType(Res).isPointer() && "invalid operand type");
87148
return buildInstr(TargetOpcode::G_FRAME_INDEX)

test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -82,36 +82,3 @@ define void @legal_default(i64 %in) {
8282
insertvalue [2 x i64] undef, i64 %in, 0
8383
ret void
8484
}
85-
86-
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for debug_insts
87-
; FALLBACK-WITH-REPORT-LABEL: debug_insts:
88-
define void @debug_insts(i32 %in) #0 !dbg !7 {
89-
entry:
90-
%in.addr = alloca i32, align 4
91-
store i32 %in, i32* %in.addr, align 4
92-
call void @llvm.dbg.declare(metadata i32* %in.addr, metadata !11, metadata !12), !dbg !13
93-
ret void, !dbg !14
94-
}
95-
96-
; Function Attrs: nounwind readnone
97-
declare void @llvm.dbg.declare(metadata, metadata, metadata)
98-
99-
!llvm.dbg.cu = !{!0}
100-
!llvm.module.flags = !{!3, !4, !5}
101-
!llvm.ident = !{!6}
102-
103-
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
104-
!1 = !DIFile(filename: "tmp.c", directory: "/Users/tim/llvm/build")
105-
!2 = !{}
106-
!3 = !{i32 2, !"Dwarf Version", i32 4}
107-
!4 = !{i32 2, !"Debug Info Version", i32 3}
108-
!5 = !{i32 1, !"PIC Level", i32 2}
109-
!6 = !{!"clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)"}
110-
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
111-
!8 = !DISubroutineType(types: !9)
112-
!9 = !{null, !10}
113-
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
114-
!11 = !DILocalVariable(name: "in", arg: 1, scope: !7, file: !1, line: 1, type: !10)
115-
!12 = !DIExpression()
116-
!13 = !DILocation(line: 1, column: 14, scope: !7)
117-
!14 = !DILocation(line: 2, column: 1, scope: !7)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; RUN: llc -global-isel -mtriple=aarch64 %s -stop-after=irtranslator -o - | FileCheck %s
2+
3+
4+
; CHECK-LABEL: name: debug_declare
5+
; CHECK: DBG_VALUE %stack.0.in.addr, 0, !11, !12, debug-location !13
6+
; CHECK: DBG_VALUE debug-use %0(s32), debug-use _, !11, !12, debug-location !13
7+
define void @debug_declare(i32 %in) #0 !dbg !7 {
8+
entry:
9+
%in.addr = alloca i32, align 4
10+
store i32 %in, i32* %in.addr, align 4
11+
call void @llvm.dbg.declare(metadata i32* %in.addr, metadata !11, metadata !12), !dbg !13
12+
call void @llvm.dbg.declare(metadata i32 %in, metadata !11, metadata !12), !dbg !13
13+
ret void, !dbg !14
14+
}
15+
16+
; CHECK-LABEL: name: debug_value
17+
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0
18+
; CHECK: DBG_VALUE debug-use [[IN]](s32), debug-use _, !11, !12, debug-location !13
19+
; CHECK: DBG_VALUE debug-use %1(p0), debug-use _, !11, !15, debug-location !13
20+
define void @debug_value(i32 %in) #0 !dbg !7 {
21+
%addr = alloca i32
22+
call void @llvm.dbg.value(metadata i32 %in, i64 0, metadata !11, metadata !12), !dbg !13
23+
store i32 %in, i32* %addr
24+
call void @llvm.dbg.value(metadata i32* %addr, i64 0, metadata !11, metadata !15), !dbg !13
25+
ret void
26+
}
27+
28+
; Function Attrs: nounwind readnone
29+
declare void @llvm.dbg.declare(metadata, metadata, metadata)
30+
declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
31+
32+
!llvm.dbg.cu = !{!0}
33+
!llvm.module.flags = !{!3, !4, !5}
34+
!llvm.ident = !{!6}
35+
36+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
37+
!1 = !DIFile(filename: "tmp.c", directory: "/Users/tim/llvm/build")
38+
!2 = !{}
39+
!3 = !{i32 2, !"Dwarf Version", i32 4}
40+
!4 = !{i32 2, !"Debug Info Version", i32 3}
41+
!5 = !{i32 1, !"PIC Level", i32 2}
42+
!6 = !{!"clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)"}
43+
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
44+
!8 = !DISubroutineType(types: !9)
45+
!9 = !{null, !10}
46+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
47+
!11 = !DILocalVariable(name: "in", arg: 1, scope: !7, file: !1, line: 1, type: !10)
48+
!12 = !DIExpression()
49+
!13 = !DILocation(line: 1, column: 14, scope: !7)
50+
!14 = !DILocation(line: 2, column: 1, scope: !7)
51+
!15 = !DIExpression(DW_OP_deref)

0 commit comments

Comments
 (0)