Przeglądaj źródła

Make sure bitpiece not generated that covers the entire variable (#3223)

Adam Yang 4 lat temu
rodzic
commit
99840a506f

+ 53 - 0
lib/HLSL/DxilPreparePasses.cpp

@@ -28,6 +28,7 @@
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/Pass.h"
 #include "llvm/Pass.h"
@@ -439,6 +440,9 @@ public:
         AddFunctionAnnotationForInitializers(M, DM);
         AddFunctionAnnotationForInitializers(M, DM);
       }
       }
 
 
+      // Fix DIExpression fragments that cover whole variables
+      LegalizeDbgFragments(M);
+
       return true;
       return true;
     }
     }
 
 
@@ -481,6 +485,55 @@ private:
     }
     }
   }
   }
 
 
+  static bool BitPieceCoversEntireVar(DIExpression *expr, DILocalVariable *var, DITypeIdentifierMap &TypeIdentifierMap) {
+    if (expr->isBitPiece()) {
+      DIType *ty = var->getType().resolve(TypeIdentifierMap);
+      return expr->getBitPieceOffset() == 0 && expr->getBitPieceSize() == ty->getSizeInBits();
+    }
+    return false;
+  }
+
+  static void LegalizeDbgFragmentsForDbgIntrinsic(Function *f, DITypeIdentifierMap &TypeIdentifierMap) {
+    Intrinsic::ID intrinsic = f->getIntrinsicID();
+
+    DIBuilder dib(*f->getParent());
+    if (intrinsic == Intrinsic::dbg_value) {
+      for (auto it = f->user_begin(), end = f->user_end(); it != end;) {
+        User *u = *(it++);
+        DbgValueInst *di = cast<DbgValueInst>(u);
+        DIExpression *expr = di->getExpression();
+        DILocalVariable *var = di->getVariable();
+        if (BitPieceCoversEntireVar(expr, var, TypeIdentifierMap)) {
+          dib.insertDbgValueIntrinsic(di->getValue(), 0, var, DIExpression::get(di->getContext(), {}), di->getDebugLoc(), di);
+          di->eraseFromParent();
+        }
+      }
+    }
+    else if (intrinsic == Intrinsic::dbg_declare) {
+      for (auto it = f->user_begin(), end = f->user_end(); it != end;) {
+        User *u = *(it++);
+        DbgDeclareInst *di = cast<DbgDeclareInst>(u);
+        DIExpression *expr = di->getExpression();
+        DILocalVariable *var = di->getVariable();
+        if (BitPieceCoversEntireVar(expr, var, TypeIdentifierMap)) {
+          dib.insertDeclare(di->getAddress(), var, DIExpression::get(di->getContext(), {}), di->getDebugLoc(), di);
+          di->eraseFromParent();
+        }
+      }
+    }
+  }
+
+  static void LegalizeDbgFragments(Module &M) {
+    DITypeIdentifierMap TypeIdentifierMap;
+
+    if (Function *f = M.getFunction(Intrinsic::getName(Intrinsic::dbg_value))) {
+      LegalizeDbgFragmentsForDbgIntrinsic(f, TypeIdentifierMap);
+    }
+    if (Function *f = M.getFunction(Intrinsic::getName(Intrinsic::dbg_declare))) {
+      LegalizeDbgFragmentsForDbgIntrinsic(f, TypeIdentifierMap);
+    }
+  }
+
   void RemoveStoreUndefOutput(Module &M, hlsl::OP *hlslOP) {
   void RemoveStoreUndefOutput(Module &M, hlsl::OP *hlslOP) {
     for (iplist<Function>::iterator F : M.getFunctionList()) {
     for (iplist<Function>::iterator F : M.getFunctionList()) {
       if (!hlslOP->IsDxilOpFunc(F))
       if (!hlslOP->IsDxilOpFunc(F))

+ 20 - 0
tools/clang/test/HLSLFileCheck/dxil/debug/bitpiece_full_var.hlsl

@@ -0,0 +1,20 @@
+// RUN: %dxc -Zi -Od -E main -T ps_6_0 %s | FileCheck %s
+
+// Regression test for structs with just a single 32-bit member.
+
+// CHECK-DAG: call void @llvm.dbg.value(metadata float %{{.*}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"my_s" !DIExpression()
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+struct MyStruct {
+  float1 foo;
+};
+
+[RootSignature("")]
+float main(float a : A) : SV_Target {
+  MyStruct my_s;
+  my_s.foo.x = a;
+  return my_s.foo.x;
+}
+