[llvm] r335682 - [Debugify] Diagnose mis-sized dbg.values

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 26 15:46:41 PDT 2018


Author: vedantk
Date: Tue Jun 26 15:46:41 2018
New Revision: 335682

URL: http://llvm.org/viewvc/llvm-project?rev=335682&view=rev
Log:
[Debugify] Diagnose mis-sized dbg.values

Report an error in -check-debugify when the size of a dbg.value operand
doesn't match up with the size of the variable it describes.

Eventually this check should be moved into the IR verifier. For the
moment, it's useful to include the check in -check-debugify as a means
of catching regressions and finding existing bugs.

Here are some instances of bugs the new check finds in the -O2 pipeline
(all in InstCombine):

1) A float is used where a double is expected:

ERROR: dbg.value operand has size 32, but its variable has size 64:
call void @llvm.dbg.value(metadata float %expf, metadata !12, metadata
!DIExpression()), !dbg !15

2) An i8 is used where an i32 is expected:

ERROR: dbg.value operand has size 8, but its variable has size 32:
call void @llvm.dbg.value(metadata i8 %t4, metadata !14, metadata
!DIExpression()), !dbg !24

3) A <4 x i32> is used where something twice as large is expected
(perhaps a <4 x i64>, I haven't double-checked):

ERROR: dbg.value operand has size 128, but its variable has size 256:
call void @llvm.dbg.value(metadata <4 x i32> %4, metadata !40, metadata
!DIExpression()), !dbg !95

Differential Revision: https://reviews.llvm.org/D48408

Added:
    llvm/trunk/test/DebugInfo/debugify-bogus-dbg-value.ll
Modified:
    llvm/trunk/tools/opt/Debugify.cpp

Added: llvm/trunk/test/DebugInfo/debugify-bogus-dbg-value.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/debugify-bogus-dbg-value.ll?rev=335682&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/debugify-bogus-dbg-value.ll (added)
+++ llvm/trunk/test/DebugInfo/debugify-bogus-dbg-value.ll Tue Jun 26 15:46:41 2018
@@ -0,0 +1,52 @@
+; RUN: opt -check-debugify < %s 2>&1 | FileCheck %s
+
+define <2 x i64> @test-fun(<2 x i64> %A) !dbg !6 {
+  %and = and <2 x i64> %A, <i64 23, i64 42>, !dbg !14
+
+; CHECK: ERROR: dbg.value operand has size 128, but its variable has size 256
+  call void @llvm.dbg.value(metadata <2 x i64> %and, metadata !12, metadata !DIExpression()), !dbg !15
+
+; CHECK: ERROR: dbg.value operand has size 512, but its variable has size 256
+  call void @llvm.dbg.value(metadata <2 x i256> zeroinitializer, metadata !12, metadata !DIExpression()), !dbg !15
+
+; CHECK: ERROR: dbg.value operand has size 8, but its variable has size 256
+  call void @llvm.dbg.value(metadata i8 0, metadata !12, metadata !DIExpression()), !dbg !15
+
+; Assume the debugger implicitly uses the lower 256 bits.
+; CHECK-NOT: ERROR: dbg.value operand has size 512, but its variable has size 256
+  call void @llvm.dbg.value(metadata i512 0, metadata !12, metadata !DIExpression()), !dbg !15
+
+  ret <2 x i64> %and, !dbg !16
+}
+; CHECK: CheckModuleDebugify: FAIL
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!3, !4}
+!llvm.module.flags = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "/Users/vsk/src/llvm.org-master/llvm/test/DebugInfo/debugify-bogus-dbg-value.ll", directory: "/")
+!2 = !{}
+!3 = !{i32 4}
+!4 = !{i32 3}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = distinct !DISubprogram(name: "test-fun", linkageName: "test-fun", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
+!7 = !DISubroutineType(types: !2)
+!8 = !{!9, !11, !12}
+!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned)
+!11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !10)
+!12 = !DILocalVariable(name: "3", scope: !6, file: !1, line: 3, type: !13)
+
+; Set the size here to an incorrect value to check that the size diagnostic
+; triggers.
+!13 = !DIBasicType(name: "ty128", size: 256, encoding: DW_ATE_unsigned)
+
+!14 = !DILocation(line: 2, column: 1, scope: !6)
+!15 = !DILocation(line: 3, column: 1, scope: !6)
+!16 = !DILocation(line: 4, column: 1, scope: !6)

Modified: llvm/trunk/tools/opt/Debugify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Debugify.cpp?rev=335682&r1=335681&r2=335682&view=diff
==============================================================================
--- llvm/trunk/tools/opt/Debugify.cpp (original)
+++ llvm/trunk/tools/opt/Debugify.cpp Tue Jun 26 15:46:41 2018
@@ -40,6 +40,10 @@ cl::opt<bool> Quiet("debugify-quiet",
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
+  return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
+}
+
 bool isFunctionSkipped(Function &F) {
   return F.isDeclaration() || !F.hasExactDefinition();
 }
@@ -71,8 +75,7 @@ bool applyDebugifyMetadata(Module &M,
   // Get a DIType which corresponds to Ty.
   DenseMap<uint64_t, DIType *> TypeCache;
   auto getCachedDIType = [&](Type *Ty) -> DIType * {
-    uint64_t Size =
-        Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
+    uint64_t Size = getAllocSizeInBits(M, Ty);
     DIType *&DTy = TypeCache[Size];
     if (!DTy) {
       std::string Name = "ty" + utostr(Size);
@@ -163,6 +166,36 @@ bool applyDebugifyMetadata(Module &M,
   return true;
 }
 
+/// Return true if a mis-sized diagnostic is issued for \p DVI.
+bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
+  // The size of a dbg.value's value operand should match the size of the
+  // variable it corresponds to.
+  //
+  // TODO: This, along with a check for non-null value operands, should be
+  // promoted to verifier failures.
+  Value *V = DVI->getValue();
+  if (!V)
+    return false;
+
+  // For now, don't try to interpret anything more complicated than an empty
+  // DIExpression. Eventually we should try to handle OP_deref and fragments.
+  if (DVI->getExpression()->getNumElements())
+    return false;
+
+  Type *Ty = V->getType();
+  uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
+  uint64_t DbgVarSize = *DVI->getFragmentSizeInBits();
+  bool HasBadSize = Ty->isIntegerTy() ? (ValueOperandSize < DbgVarSize)
+                                      : (ValueOperandSize != DbgVarSize);
+  if (HasBadSize) {
+    dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
+          << ", but its variable has size " << DbgVarSize << ": ";
+    DVI->print(dbg());
+    dbg() << "\n";
+  }
+  return HasBadSize;
+}
+
 bool checkDebugifyMetadata(Module &M,
                            iterator_range<Module::iterator> Functions,
                            StringRef NameOfWrappedPass, StringRef Banner,
@@ -208,7 +241,7 @@ bool checkDebugifyMetadata(Module &M,
       HasErrors = true;
     }
 
-    // Find missing variables.
+    // Find missing variables and mis-sized debug values.
     for (Instruction &I : instructions(F)) {
       auto *DVI = dyn_cast<DbgValueInst>(&I);
       if (!DVI)
@@ -217,7 +250,10 @@ bool checkDebugifyMetadata(Module &M,
       unsigned Var = ~0U;
       (void)to_integer(DVI->getVariable()->getName(), Var, 10);
       assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
-      MissingVars.reset(Var - 1);
+      bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
+      if (!HasBadSize)
+        MissingVars.reset(Var - 1);
+      HasErrors |= HasBadSize;
     }
   }
 




More information about the llvm-commits mailing list