Skip to content

Commit 3473447

Browse files
Merge pull request #3845 from adrian-prantl/88033721-5.6
Fix UB in DwarfExpression::emitLegacyZExt()
2 parents 0d7d612 + 2fb951d commit 3473447

File tree

10 files changed

+263
-15
lines changed

10 files changed

+263
-15
lines changed

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2932,6 +2932,12 @@ class DIExpression : public MDNode {
29322932
return getNumElements() > 0 &&
29332933
getElement(0) == dwarf::DW_OP_LLVM_entry_value;
29342934
}
2935+
2936+
/// Try to shorten an expression with an initial constant operand.
2937+
/// Returns a new expression and constant on success, or the original
2938+
/// expression and constant on failure.
2939+
std::pair<DIExpression *, const ConstantInt *>
2940+
constantFold(const ConstantInt *CI);
29352941
};
29362942

29372943
inline bool operator==(const DIExpression::FragmentInfo &A,

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,9 +681,25 @@ void DwarfExpression::emitLegacySExt(unsigned FromBits) {
681681
}
682682

683683
void DwarfExpression::emitLegacyZExt(unsigned FromBits) {
684-
// (X & (1 << FromBits - 1))
685-
emitOp(dwarf::DW_OP_constu);
686-
emitUnsigned((1ULL << FromBits) - 1);
684+
// Heuristic to decide the most efficient encoding.
685+
// A ULEB can encode 7 1-bits per byte.
686+
if (FromBits / 7 < 1+1+1+1+1) {
687+
// (X & (1 << FromBits - 1))
688+
emitOp(dwarf::DW_OP_constu);
689+
emitUnsigned((1ULL << FromBits) - 1);
690+
} else {
691+
// Note that the DWARF 4 stack consists of pointer-sized elements,
692+
// so technically it doesn't make sense to shift left more than 64
693+
// bits. We leave that for the consumer to decide though. LLDB for
694+
// example uses APInt for the stack elements and can still deal
695+
// with this.
696+
emitOp(dwarf::DW_OP_lit1);
697+
emitOp(dwarf::DW_OP_constu);
698+
emitUnsigned(FromBits);
699+
emitOp(dwarf::DW_OP_shl);
700+
emitOp(dwarf::DW_OP_lit1);
701+
emitOp(dwarf::DW_OP_minus);
702+
}
687703
emitOp(dwarf::DW_OP_and);
688704
}
689705

llvm/lib/CodeGen/SelectionDAG/FastISel.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,18 +1292,22 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
12921292
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, false, 0U,
12931293
DI->getVariable(), DI->getExpression());
12941294
} else if (const auto *CI = dyn_cast<ConstantInt>(V)) {
1295+
// See if there's an expression to constant-fold.
1296+
DIExpression *Expr = DI->getExpression();
1297+
if (Expr)
1298+
std::tie(Expr, CI) = Expr->constantFold(CI);
12951299
if (CI->getBitWidth() > 64)
12961300
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
12971301
.addCImm(CI)
12981302
.addImm(0U)
12991303
.addMetadata(DI->getVariable())
1300-
.addMetadata(DI->getExpression());
1304+
.addMetadata(Expr);
13011305
else
13021306
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
13031307
.addImm(CI->getZExtValue())
13041308
.addImm(0U)
13051309
.addMetadata(DI->getVariable())
1306-
.addMetadata(DI->getExpression());
1310+
.addMetadata(Expr);
13071311
} else if (const auto *CF = dyn_cast<ConstantFP>(V)) {
13081312
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
13091313
.addFPImm(CF)

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -872,17 +872,28 @@ MachineInstr *
872872
InstrEmitter::EmitDbgValueFromSingleOp(SDDbgValue *SD,
873873
DenseMap<SDValue, Register> &VRBaseMap) {
874874
MDNode *Var = SD->getVariable();
875-
MDNode *Expr = SD->getExpression();
875+
DIExpression *Expr = SD->getExpression();
876876
DebugLoc DL = SD->getDebugLoc();
877877
const MCInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE);
878878

879879
assert(SD->getLocationOps().size() == 1 &&
880880
"Non variadic dbg_value should have only one location op");
881881

882+
// See about constant-folding the expression.
883+
// Copy the location operand in case we replace it.
884+
SmallVector<SDDbgOperand, 1> LocationOps(1, SD->getLocationOps()[0]);
885+
if (Expr && LocationOps[0].getKind() == SDDbgOperand::CONST) {
886+
const Value *V = LocationOps[0].getConst();
887+
if (auto *C = dyn_cast<ConstantInt>(V)) {
888+
std::tie(Expr, C) = Expr->constantFold(C);
889+
LocationOps[0] = SDDbgOperand::fromConst(C);
890+
}
891+
}
892+
882893
// Emit non-variadic dbg_value nodes as DBG_VALUE.
883894
// DBG_VALUE := "DBG_VALUE" loc, isIndirect, var, expr
884895
auto MIB = BuildMI(*MF, DL, II);
885-
AddDbgValueLocationOps(MIB, II, SD->getLocationOps(), VRBaseMap);
896+
AddDbgValueLocationOps(MIB, II, LocationOps, VRBaseMap);
886897

887898
if (SD->isIndirect())
888899
MIB.addImm(0U);

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,45 @@ Optional<DIExpression *> DIExpression::createFragmentExpression(
14781478
return DIExpression::get(Expr->getContext(), Ops);
14791479
}
14801480

1481+
std::pair<DIExpression *, const ConstantInt *>
1482+
DIExpression::constantFold(const ConstantInt *CI) {
1483+
// Copy the APInt so we can modify it.
1484+
APInt NewInt = CI->getValue();
1485+
SmallVector<uint64_t, 8> Ops;
1486+
1487+
// Fold operators only at the beginning of the expression.
1488+
bool First = true;
1489+
bool Changed = false;
1490+
for (auto Op : expr_ops()) {
1491+
switch (Op.getOp()) {
1492+
default:
1493+
// We fold only the leading part of the expression; if we get to a part
1494+
// that we're going to copy unchanged, and haven't done any folding,
1495+
// then the entire expression is unchanged and we can return early.
1496+
if (!Changed)
1497+
return {this, CI};
1498+
First = false;
1499+
break;
1500+
case dwarf::DW_OP_LLVM_convert:
1501+
if (!First)
1502+
break;
1503+
Changed = true;
1504+
if (Op.getArg(1) == dwarf::DW_ATE_signed)
1505+
NewInt = NewInt.sextOrTrunc(Op.getArg(0));
1506+
else {
1507+
assert(Op.getArg(1) == dwarf::DW_ATE_unsigned && "Unexpected operand");
1508+
NewInt = NewInt.zextOrTrunc(Op.getArg(0));
1509+
}
1510+
continue;
1511+
}
1512+
Op.appendToVector(Ops);
1513+
}
1514+
if (!Changed)
1515+
return {this, CI};
1516+
return {DIExpression::get(getContext(), Ops),
1517+
ConstantInt::get(getContext(), NewInt)};
1518+
}
1519+
14811520
uint64_t DIExpression::getNumLocationOperands() const {
14821521
uint64_t Result = 0;
14831522
for (auto ExprOp : expr_ops())
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
; RUN: llc -mtriple=x86_64 -filetype=obj < %s \
2+
; RUN: | llvm-dwarfdump -debug-info - | FileCheck %s
3+
; RUN: llc -mtriple=x86_64 -filetype=obj -fast-isel < %s \
4+
; RUN: | llvm-dwarfdump -debug-info - | FileCheck %s
5+
6+
;; The important thing is the DW_OP_lit2 with no converts.
7+
;; TODO: Make this work with global isel
8+
;; Indirectly related FIXME: Should be able to emit DW_AT_const_value instead.
9+
10+
; CHECK: DW_TAG_variable
11+
; CHECK-NEXT: DW_AT_location (DW_OP_lit2, DW_OP_stack_value)
12+
; CHECK-NEXT: DW_AT_name ("bIsShowingCollision")
13+
14+
%class.UClient = type { %class.UWorld*, %struct.FFlags }
15+
%class.UWorld = type { i16 }
16+
%struct.FFlags = type { [9 x i8], i32 }
17+
18+
define dso_local void @_ZN7UClient13ToggleVolumesEv(%class.UClient* nocapture nonnull align 8 dereferenceable(24) %this) local_unnamed_addr align 2 !dbg !8 {
19+
entry:
20+
call void @llvm.dbg.value(metadata i72 2, metadata !43, metadata !DIExpression(DW_OP_LLVM_convert, 72, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !48
21+
%World = getelementptr inbounds %class.UClient, %class.UClient* %this, i64 0, i32 0, !dbg !49
22+
%0 = load %class.UWorld*, %class.UWorld** %World, align 8, !dbg !49, !tbaa !51
23+
%1 = getelementptr %class.UWorld, %class.UWorld* %0, i64 0, i32 0, !dbg !58
24+
store i16 2, i16* %1, align 1, !dbg !59
25+
ret void, !dbg !60
26+
}
27+
28+
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
29+
declare void @llvm.dbg.value(metadata, metadata, metadata)
30+
31+
!llvm.dbg.cu = !{!0}
32+
!llvm.module.flags = !{!3, !4, !5, !6}
33+
!llvm.ident = !{!7}
34+
35+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
36+
!1 = !DIFile(filename: "min-test-3.cpp", directory: "/home/probinson/projects/scratch/tc8251")
37+
!2 = !{}
38+
!3 = !{i32 7, !"Dwarf Version", i32 4}
39+
!4 = !{i32 2, !"Debug Info Version", i32 3}
40+
!5 = !{i32 1, !"wchar_size", i32 4}
41+
!6 = !{i32 7, !"uwtable", i32 1}
42+
!7 = !{!"clang version 13.0.0"}
43+
!8 = distinct !DISubprogram(name: "ToggleVolumes", linkageName: "_ZN7UClient13ToggleVolumesEv", scope: !9, file: !1, line: 39, type: !37, scopeLine: 40, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !36, retainedNodes: !40)
44+
!9 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "UClient", file: !1, line: 31, size: 192, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !10, identifier: "_ZTS7UClient")
45+
!10 = !{!11, !20, !36}
46+
!11 = !DIDerivedType(tag: DW_TAG_member, name: "World", scope: !9, file: !1, line: 34, baseType: !12, size: 64, flags: DIFlagPublic)
47+
!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
48+
!13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "UWorld", file: !1, line: 8, size: 16, flags: DIFlagTypePassByValue, elements: !14, identifier: "_ZTS6UWorld")
49+
!14 = !{!15, !18, !19}
50+
!15 = !DIDerivedType(tag: DW_TAG_member, name: "bCollision", scope: !13, file: !1, line: 11, baseType: !16, size: 1, flags: DIFlagPublic | DIFlagBitField, extraData: i64 0)
51+
!16 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint8", file: !1, line: 1, baseType: !17)
52+
!17 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
53+
!18 = !DIDerivedType(tag: DW_TAG_member, name: "dummyA", scope: !13, file: !1, line: 12, baseType: !16, size: 7, offset: 1, flags: DIFlagPublic | DIFlagBitField, extraData: i64 0)
54+
!19 = !DIDerivedType(tag: DW_TAG_member, name: "dummyB", scope: !13, file: !1, line: 13, baseType: !16, size: 1, offset: 8, flags: DIFlagPublic | DIFlagBitField, extraData: i64 0)
55+
!20 = !DIDerivedType(tag: DW_TAG_member, name: "EngineShowFlags", scope: !9, file: !1, line: 35, baseType: !21, size: 128, offset: 64, flags: DIFlagPublic)
56+
!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "FFlags", file: !1, line: 16, size: 128, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !22, identifier: "_ZTS6FFlags")
57+
!22 = !{!23, !26, !27, !28, !29, !30, !32}
58+
!23 = !DIDerivedType(tag: DW_TAG_member, name: "Volumes", scope: !21, file: !1, line: 18, baseType: !24, size: 1, flags: DIFlagBitField, extraData: i64 0)
59+
!24 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32", file: !1, line: 2, baseType: !25)
60+
!25 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
61+
!26 = !DIDerivedType(tag: DW_TAG_member, name: "Collision", scope: !21, file: !1, line: 19, baseType: !24, size: 1, offset: 1, flags: DIFlagBitField, extraData: i64 0)
62+
!27 = !DIDerivedType(tag: DW_TAG_member, name: "dummy1", scope: !21, file: !1, line: 20, baseType: !24, size: 30, offset: 2, flags: DIFlagBitField, extraData: i64 0)
63+
!28 = !DIDerivedType(tag: DW_TAG_member, name: "dummy2", scope: !21, file: !1, line: 21, baseType: !24, size: 32, offset: 32, flags: DIFlagBitField, extraData: i64 0)
64+
!29 = !DIDerivedType(tag: DW_TAG_member, name: "dummy3", scope: !21, file: !1, line: 22, baseType: !24, size: 1, offset: 64, flags: DIFlagBitField, extraData: i64 0)
65+
!30 = !DIDerivedType(tag: DW_TAG_member, name: "CustomShowFlags", scope: !21, file: !1, line: 24, baseType: !31, size: 32, offset: 96)
66+
!31 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
67+
!32 = !DISubprogram(name: "FFlags", scope: !21, file: !1, line: 25, type: !33, scopeLine: 25, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
68+
!33 = !DISubroutineType(types: !34)
69+
!34 = !{null, !35}
70+
!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !21, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
71+
!36 = !DISubprogram(name: "ToggleVolumes", linkageName: "_ZN7UClient13ToggleVolumesEv", scope: !9, file: !1, line: 36, type: !37, scopeLine: 36, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagOptimized)
72+
!37 = !DISubroutineType(types: !38)
73+
!38 = !{null, !39}
74+
!39 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
75+
!40 = !{!41, !43}
76+
!41 = !DILocalVariable(name: "this", arg: 1, scope: !8, type: !42, flags: DIFlagArtificial | DIFlagObjectPointer)
77+
!42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64)
78+
!43 = !DILocalVariable(name: "bIsShowingCollision", scope: !44, file: !1, line: 45, type: !46)
79+
!44 = distinct !DILexicalBlock(scope: !45, file: !1, line: 42, column: 2)
80+
!45 = distinct !DILexicalBlock(scope: !8, file: !1, line: 41, column: 6)
81+
!46 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !47)
82+
!47 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
83+
!48 = !DILocation(line: 0, scope: !44)
84+
!49 = !DILocation(line: 51, column: 8, scope: !50)
85+
!50 = distinct !DILexicalBlock(scope: !44, file: !1, line: 51, column: 8)
86+
!51 = !{!52, !53, i64 0}
87+
!52 = !{!"_ZTS7UClient", !53, i64 0, !56, i64 8}
88+
!53 = !{!"any pointer", !54, i64 0}
89+
!54 = !{!"omnipotent char", !55, i64 0}
90+
!55 = !{!"Simple C++ TBAA"}
91+
!56 = !{!"_ZTS6FFlags", !57, i64 0, !57, i64 0, !57, i64 0, !57, i64 4, !57, i64 8, !57, i64 12}
92+
!57 = !{!"int", !54, i64 0}
93+
!58 = !DILocation(line: 52, column: 12, scope: !50)
94+
!59 = !DILocation(line: 52, column: 23, scope: !50)
95+
!60 = !DILocation(line: 55, column: 1, scope: !8)

llvm/test/DebugInfo/X86/convert-debugloc.ll

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
; RUN: | FileCheck %s --check-prefix=VERBOSE --check-prefix=CONV "--implicit-check-not={{DW_TAG|NULL}}"
2828

2929

30-
; SPLITCONV: Compile Unit:{{.*}} DWO_id = 0xe91d8d1d7f9782c0
30+
; SPLITCONV: Compile Unit:{{.*}} DWO_id = 0x24191746f389535f
3131
; SPLIT: DW_TAG_skeleton_unit
3232

3333
; CONV: DW_TAG_compile_unit
@@ -41,20 +41,25 @@
4141
; CONV-NEXT:DW_AT_encoding {{.*}}DW_ATE_signed)
4242
; CONV-NEXT:DW_AT_byte_size {{.*}}0x04)
4343
; CONV-NOT: DW_AT
44+
; CONV: DW_TAG_base_type
45+
; CONV: DW_TAG_base_type
4446
; CONV: DW_TAG_subprogram
4547
; CONV: DW_TAG_formal_parameter
4648
; CONV: DW_TAG_variable
47-
; CONV: DW_AT_location {{.*}}DW_OP_constu 0x20, DW_OP_convert (
49+
; CONV: DW_AT_location {{.*}}DW_OP_constu 0x20, DW_OP_lit0, DW_OP_plus, DW_OP_convert (
4850
; VERBOSE-SAME: [[SIG8]] ->
4951
; CONV-SAME: [[SIG8]]) "DW_ATE_signed_8", DW_OP_convert (
5052
; VERBOSE-SAME: [[SIG32]] ->
5153
; CONV-SAME: [[SIG32]]) "DW_ATE_signed_32", DW_OP_stack_value)
5254
; CONV: DW_AT_name {{.*}}"y")
55+
; CONV: DW_TAG_variable
5356
; CONV: NULL
5457
; CONV: DW_TAG_base_type
5558
; CONV: DW_AT_name {{.*}}"signed char")
5659
; CONV: DW_TAG_base_type
5760
; CONV: DW_AT_name {{.*}}"int")
61+
; CONV: DW_TAG_base_type
62+
; CONV: DW_AT_name {{.*}}"unsigned long long")
5863
; CONV: NULL
5964

6065
; NOCONV: DW_TAG_compile_unit
@@ -64,19 +69,30 @@
6469
; NOCONV: DW_AT_location (
6570
; NOCONV: {{.*}}, DW_OP_dup, DW_OP_constu 0x7, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_constu 0x8, DW_OP_shl, DW_OP_or, DW_OP_stack_value)
6671
; NOCONV: DW_AT_name ("y")
72+
; NOCONV: DW_TAG_variable
73+
; NOCONV: DW_AT_location (
74+
; NOCONV: DW_OP_constu 0x40, DW_OP_lit0, DW_OP_plus, DW_OP_lit1, DW_OP_constu 0x40, DW_OP_shl, DW_OP_lit1, DW_OP_minus, DW_OP_and, DW_OP_stack_value)
75+
; NOCONV: DW_AT_name ("z")
6776
; NOCONV: NULL
6877
; NOCONV: DW_TAG_base_type
6978
; NOCONV: DW_AT_name ("signed char")
7079
; NOCONV: DW_TAG_base_type
7180
; NOCONV: DW_AT_name ("int")
81+
; NOCONV: DW_TAG_base_type
82+
; NOCONV: DW_AT_name ("unsigned long long")
7283
; NOCONV: NULL
7384

7485

7586
; Function Attrs: noinline nounwind uwtable
7687
define dso_local signext i8 @foo(i8 signext %x) !dbg !7 {
7788
entry:
7889
call void @llvm.dbg.value(metadata i8 %x, metadata !11, metadata !DIExpression()), !dbg !12
79-
call void @llvm.dbg.value(metadata i8 32, metadata !13, metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)), !dbg !15
90+
;; This test depends on "convert" surviving all the way to the final object.
91+
;; So, insert something before DW_OP_LLVM_convert that the expression folder
92+
;; will not attempt to eliminate. At the moment, only "convert" ops are folded.
93+
;; If you have to change the expression, the expected DWO_id also changes.
94+
call void @llvm.dbg.value(metadata i8 32, metadata !13, metadata !DIExpression(DW_OP_lit0, DW_OP_plus, DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)), !dbg !15
95+
call void @llvm.dbg.value(metadata i8 64, metadata !17, metadata !DIExpression(DW_OP_lit0, DW_OP_plus, DW_OP_LLVM_convert, 64, DW_ATE_unsigned, DW_OP_LLVM_convert, 128, DW_ATE_unsigned, DW_OP_LLVM_convert, 64, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !15
8096
ret i8 %x, !dbg !16
8197
}
8298

@@ -107,3 +123,5 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
107123
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
108124
!15 = !DILocation(line: 3, column: 14, scope: !7)
109125
!16 = !DILocation(line: 4, column: 3, scope: !7)
126+
!17 = !DILocalVariable(name: "z", scope: !7, file: !1, line: 3, type: !18)
127+
!18 = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned)

llvm/test/DebugInfo/X86/convert-linked.ll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,20 @@
1919
define dso_local signext i8 @foo(i8 signext %x) !dbg !9 {
2020
entry:
2121
call void @llvm.dbg.value(metadata i8 %x, metadata !13, metadata !DIExpression()), !dbg !14
22-
call void @llvm.dbg.value(metadata i8 32, metadata !15, metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)), !dbg !17
22+
;; This test depends on "convert" surviving all the way to the final object.
23+
;; So, insert something before DW_OP_LLVM_convert that the expression folder
24+
;; will not attempt to eliminate. At the moment, only "convert" ops are folded.
25+
call void @llvm.dbg.value(metadata i8 32, metadata !15, metadata !DIExpression(DW_OP_lit0, DW_OP_plus, DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)), !dbg !17
2326
ret i8 %x, !dbg !18
2427
}
2528

2629
define dso_local signext i8 @bar(i8 signext %x) !dbg !19 {
2730
entry:
2831
call void @llvm.dbg.value(metadata i8 %x, metadata !20, metadata !DIExpression()), !dbg !21
29-
call void @llvm.dbg.value(metadata i8 32, metadata !22, metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 16, DW_ATE_signed, DW_OP_stack_value)), !dbg !24
32+
;; This test depends on "convert" surviving all the way to the final object.
33+
;; So, insert something before DW_OP_LLVM_convert that the expression folder
34+
;; will not attempt to eliminate. At the moment, only "convert" ops are folded.
35+
call void @llvm.dbg.value(metadata i8 32, metadata !22, metadata !DIExpression(DW_OP_lit0, DW_OP_plus, DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 16, DW_ATE_signed, DW_OP_stack_value)), !dbg !24
3036
ret i8 %x, !dbg !25
3137
}
3238

llvm/test/DebugInfo/X86/convert-loclist.ll

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
; often - add another IR file with a different DW_OP_convert that's otherwise
1414
; identical and demonstrate that they have different DWO IDs.
1515

16-
; SPLIT: 0x00000000: Compile Unit: {{.*}} DWO_id = 0xafd73565c68bc661
16+
; SPLIT: 0x00000000: Compile Unit: {{.*}} DWO_id = 0xecf2563326b0bdd3
1717

1818
; Regression testing a fairly quirky bug where instead of hashing (see above),
1919
; extra bytes would be emitted into the output assembly in no
@@ -23,13 +23,17 @@
2323
; CHECK: 0x{{0*}}[[TYPE:.*]]: DW_TAG_base_type
2424
; CHECK-NEXT: DW_AT_name ("DW_ATE_unsigned_32")
2525

26-
; CHECK: DW_LLE_offset_pair ({{.*}}): DW_OP_consts +7, DW_OP_convert 0x[[TYPE]], DW_OP_stack_value
26+
; CHECK: DW_LLE_offset_pair ({{.*}}): DW_OP_consts +7, DW_OP_lit0, DW_OP_plus, DW_OP_convert 0x[[TYPE]], DW_OP_stack_value
2727

2828
; Function Attrs: uwtable
2929
define dso_local void @_Z2f2v() local_unnamed_addr #0 !dbg !11 {
3030
entry:
3131
tail call void @_Z2f1v(), !dbg !15
32-
call void @llvm.dbg.value(metadata i32 7, metadata !13, metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !16
32+
;; This test depends on "convert" surviving all the way to the final object.
33+
;; So, insert something before DW_OP_LLVM_convert that the expression folder
34+
;; will not attempt to eliminate. At the moment, only "convert" ops are folded.
35+
;; If you have to change the expression, the expected DWO_id also changes.
36+
call void @llvm.dbg.value(metadata i32 7, metadata !13, metadata !DIExpression(DW_OP_lit0, DW_OP_plus, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !16
3337
tail call void @_Z2f1v(), !dbg !17
3438
ret void, !dbg !18
3539
}

0 commit comments

Comments
 (0)