llvm.org GIT mirror llvm / f80f771
PR32288: Describe a bool parameter's DWARF location with a simple register There's no need (& a bit incorrect) to mask off the high bits of the register reference when describing a simple bool value. Reviewers: aprantl Differential Revision: https://reviews.llvm.org/D31062 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303117 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 2 years ago
2 changed file(s) with 99 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
11041104 void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
11051105 StoreInst *SI, DIBuilder &Builder) {
11061106 auto *DIVar = DDI->getVariable();
1107 assert(DIVar && "Missing variable");
11071108 auto *DIExpr = DDI->getExpression();
1108 assert(DIVar && "Missing variable");
1109 Value *DV = SI->getOperand(0);
11091110
11101111 // If an argument is zero extended then use argument directly. The ZExt
11111112 // may be zapped by an optimization pass in future.
11151116 if (SExtInst *SExt = dyn_cast(SI->getOperand(0)))
11161117 ExtendedArg = dyn_cast(SExt->getOperand(0));
11171118 if (ExtendedArg) {
1118 // We're now only describing a subset of the variable. The fragment we're
1119 // describing will always be smaller than the variable size, because
1120 // VariableSize == Size of Alloca described by DDI. Since SI stores
1121 // to the alloca described by DDI, if it's first operand is an extend,
1122 // we're guaranteed that before extension, the value was narrower than
1123 // the size of the alloca, hence the size of the described variable.
1124 SmallVector Ops;
1125 unsigned FragmentOffset = 0;
1126 // If this already is a bit fragment, we drop the bit fragment from the
1127 // expression and record the offset.
1128 auto Fragment = DIExpr->getFragmentInfo();
1129 if (Fragment) {
1130 Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()-3);
1131 FragmentOffset = Fragment->OffsetInBits;
1132 } else {
1133 Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
1134 }
1135 Ops.push_back(dwarf::DW_OP_LLVM_fragment);
1136 Ops.push_back(FragmentOffset);
1137 const DataLayout &DL = DDI->getModule()->getDataLayout();
1138 Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType()));
1139 auto NewDIExpr = Builder.createExpression(Ops);
1140 if (!LdStHasDebugValue(DIVar, NewDIExpr, SI))
1141 Builder.insertDbgValueIntrinsic(ExtendedArg, 0, DIVar, NewDIExpr,
1142 DDI->getDebugLoc(), SI);
1143 } else if (!LdStHasDebugValue(DIVar, DIExpr, SI))
1144 Builder.insertDbgValueIntrinsic(SI->getOperand(0), 0, DIVar, DIExpr,
1145 DDI->getDebugLoc(), SI);
1119 // If this DDI was already describing only a fragment of a variable, ensure
1120 // that fragment is appropriately narrowed here.
1121 // But if a fragment wasn't used, describe the value as the original
1122 // argument (rather than the zext or sext) so that it remains described even
1123 // if the sext/zext is optimized away. This widens the variable description,
1124 // leaving it up to the consumer to know how the smaller value may be
1125 // represented in a larger register.
1126 if (auto Fragment = DIExpr->getFragmentInfo()) {
1127 unsigned FragmentOffset = Fragment->OffsetInBits;
1128 SmallVector Ops(DIExpr->elements_begin(),
1129 DIExpr->elements_end() - 3);
1130 Ops.push_back(dwarf::DW_OP_LLVM_fragment);
1131 Ops.push_back(FragmentOffset);
1132 const DataLayout &DL = DDI->getModule()->getDataLayout();
1133 Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType()));
1134 DIExpr = Builder.createExpression(Ops);
1135 }
1136 DV = ExtendedArg;
1137 }
1138 if (!LdStHasDebugValue(DIVar, DIExpr, SI))
1139 Builder.insertDbgValueIntrinsic(DV, 0, DIVar, DIExpr, DDI->getDebugLoc(),
1140 SI);
11461141 }
11471142
11481143 /// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
22 ; if it only describes part of the variable.
33 ; RUN: opt -S -sroa %s | FileCheck %s
44
5 ; Function Attrs: nounwind readnone
6 declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
5 ; Built from:
6 ; struct foo { bool b; long i; };
7 ; void f(bool b, bool expr, foo g) {
8 ; }
9 ; And modifying the frag dbg.declare to use a fragmented DIExpression (with offset: 0, size: 4)
10 ; to test the dbg.declare+fragment case here.
711
8 ; Function Attrs: nounwind uwtable
9 define hidden void @_ZN6__tsan9FastState14SetHistorySizeEi(i32 %hs) #1 align 2 {
12 ; Expect two fragments:
13 ; * first starting at bit 0, 8 bits (for the bool)
14 ; * second starting at bit 32, 32 bits (for the long)
15 ; (this happens to create/demonstrate a gap from bits [7, 32))
16
17 ; But also check that a complex expression is not used for a lone bool
18 ; parameter. It can reference the register it's in directly without masking off
19 ; high bits or anything
20
21 ; CHECK: call void @llvm.dbg.value(metadata i8 %g.coerce0, i64 0, metadata ![[VAR_STRUCT:[0-9]+]], metadata ![[EXPR_STRUCT1:[0-9]+]])
22 ; CHECK: call void @llvm.dbg.value(metadata i64 %g.coerce1, i64 0, metadata ![[VAR_STRUCT]], metadata ![[EXPR_STRUCT2:[0-9]+]])
23 ; CHECK: call void @llvm.dbg.value(metadata i1 %b, i64 0, metadata ![[VAR_BOOL:[0-9]+]], metadata ![[EXPR_BOOL:[0-9]+]])
24 ; CHECK: call void @llvm.dbg.value(metadata i1 %frag, i64 0, metadata ![[FRAG_BOOL:[0-9]+]], metadata ![[FRAG_BOOL:[0-9]+]])
25 ; CHECK: ![[EXPR_STRUCT1]] = !DIExpression(DW_OP_LLVM_fragment, 0, 8)
26 ; CHECK: ![[EXPR_STRUCT2]] = !DIExpression(DW_OP_LLVM_fragment, 32, 64)
27 ; CHECK: ![[EXPR_BOOL]] = !DIExpression()
28 ; CHECK: ![[FRAG_BOOL]] = !DIExpression(DW_OP_LLVM_fragment, 0, 1)
29
30 %struct.foo = type { i8, i64 }
31
32 ; Function Attrs: noinline nounwind uwtable
33 define void @_Z1fbb3foo(i1 zeroext %b, i1 zeroext %frag, i8 %g.coerce0, i64 %g.coerce1) #0 !dbg !6 {
1034 entry:
11 %hs.addr = alloca i32, align 4
12 %v1 = alloca i64, align 8
13 %v2 = alloca i64, align 8
14 store i32 %hs, i32* %hs.addr, align 4
15 ; CHECK: call void @llvm.dbg.value(metadata i32 %hs, i64 0, metadata !{{[0-9]+}}, metadata ![[EXPR:[0-9]+]])
16 ; CHECK: ![[EXPR]] = !DIExpression(DW_OP_LLVM_fragment, 0
17 call void @llvm.dbg.declare(metadata i64* %v1, metadata !9, metadata !12), !dbg !13
18 %0 = load i32, i32* %hs.addr, align 4
19 %conv = sext i32 %0 to i64
20 store i64 %conv, i64* %v1, align 8
21 %1 = load i64, i64* %v2, align 8
22 unreachable
35 %g = alloca %struct.foo, align 8
36 %b.addr = alloca i8, align 1
37 %frag.addr = alloca i8, align 1
38 %0 = bitcast %struct.foo* %g to { i8, i64 }*
39 %1 = getelementptr inbounds { i8, i64 }, { i8, i64 }* %0, i32 0, i32 0
40 store i8 %g.coerce0, i8* %1, align 8
41 %2 = getelementptr inbounds { i8, i64 }, { i8, i64 }* %0, i32 0, i32 1
42 store i64 %g.coerce1, i64* %2, align 8
43 %frombool = zext i1 %b to i8
44 store i8 %frombool, i8* %b.addr, align 1
45 call void @llvm.dbg.declare(metadata i8* %b.addr, metadata !15, metadata !16), !dbg !17
46 %frombool1 = zext i1 %frag to i8
47 store i8 %frombool1, i8* %frag.addr, align 1
48 call void @llvm.dbg.declare(metadata i8* %frag.addr, metadata !18, metadata !23), !dbg !19
49 call void @llvm.dbg.declare(metadata %struct.foo* %g, metadata !20, metadata !16), !dbg !21
50 ret void, !dbg !22
2351 }
2452
25 attributes #0 = { nounwind readnone }
53 ; Function Attrs: nounwind readnone speculatable
54 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
55
56 attributes #0 = { noinline nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
57 attributes #1 = { nounwind readnone speculatable }
2658
2759 !llvm.dbg.cu = !{!0}
28 !llvm.module.flags = !{!7}
29 !llvm.ident = !{!8}
60 !llvm.module.flags = !{!3, !4}
61 !llvm.ident = !{!5}
3062
31 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2)
32 !1 = !DIFile(filename: "tsan_shadow_test.cc", directory: "/tmp")
33 !2 = !{!3, !5}
34 !3 = !DICompositeType(tag: DW_TAG_class_type, name: "FastState", file: !4, line: 91, size: 64, align: 64, identifier: "_ZTSN6__tsan9FastStateE")
35 !4 = !DIFile(filename: "/mnt/extra/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_rtl.h", directory: "/tmp")
36 !5 = distinct !DIDerivedType(tag: DW_TAG_typedef, name: "u64", line: 78, baseType: !6)
37 !6 = !DIBasicType(name: "long long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned)
38 !7 = !{i32 2, !"Debug Info Version", i32 3}
39 !8 = !{!"clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)"}
40 !9 = !DILocalVariable(name: "v1", scope: !10, file: !4, line: 136, type: !5)
41 !10 = distinct !DILexicalBlock(scope: !11, file: !4, line: 136, column: 5)
42 !11 = distinct !DISubprogram(name: "SetHistorySize", linkageName: "_ZN6__tsan9FastState14SetHistorySizeEi", scope: !3, file: !4, line: 135, isLocal: false, isDefinition: true, scopeLine: 135, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
43 !12 = !DIExpression()
44 !13 = !DILocation(line: 136, column: 5, scope: !10)
63 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 303077) (llvm/trunk 303098)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
64 !1 = !DIFile(filename: "foo.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch")
65 !2 = !{}
66 !3 = !{i32 2, !"Dwarf Version", i32 4}
67 !4 = !{i32 2, !"Debug Info Version", i32 3}
68 !5 = !{!"clang version 5.0.0 (trunk 303077) (llvm/trunk 303098)"}
69 !6 = distinct !DISubprogram(name: "f", linkageName: "_Z1fbb3foo", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
70 !7 = !DISubroutineType(types: !8)
71 !8 = !{null, !9, !9, !10}
72 !9 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
73 !10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 1, size: 128, elements: !11, identifier: "_ZTS3foo")
74 !11 = !{!12, !13}
75 !12 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !1, line: 1, baseType: !9, size: 8)
76 !13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 1, baseType: !14, size: 64, offset: 64)
77 !14 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
78 !15 = !DILocalVariable(name: "b", arg: 1, scope: !6, file: !1, line: 2, type: !9)
79 !16 = !DIExpression()
80 !17 = !DILocation(line: 2, column: 13, scope: !6)
81 !18 = !DILocalVariable(name: "frag", arg: 2, scope: !6, file: !1, line: 2, type: !9)
82 !19 = !DILocation(line: 2, column: 21, scope: !6)
83 !20 = !DILocalVariable(name: "g", arg: 3, scope: !6, file: !1, line: 2, type: !10)
84 !21 = !DILocation(line: 2, column: 31, scope: !6)
85 !22 = !DILocation(line: 3, column: 1, scope: !6)
86 !23 = !DIExpression(DW_OP_LLVM_fragment, 0, 4)