浏览代码

Merge debug info for global variables lowered into local allocas. (#2846)

Adam Yang 5 年之前
父节点
当前提交
1053ca45ab

+ 80 - 9
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -6278,21 +6278,73 @@ private:
 };
 }
 
-static
-DIGlobalVariable *FindGlobalVariableFor(const DebugInfoFinder &DbgFinder, GlobalVariable *GV) {
-  for (auto *DGV : DbgFinder.global_variables()) {
-    if (DGV->getVariable() == GV) {
-      return DGV;
+// Go through the base type chain of TyA and see if
+// we eventually get to TyB
+//
+// Note: Not necessarily about inheritance. Could be
+// typedef, const type, ref type, MEMBER type (TyA
+// being a member of TyB).
+//
+static bool IsDerivedTypeOf(DIType *TyA, DIType *TyB) {
+  DITypeIdentifierMap EmptyMap;
+  while (TyA) {
+    if (DIDerivedType *Derived = dyn_cast<DIDerivedType>(TyA)) {
+      if (Derived->getBaseType() == TyB)
+        return true;
+      else
+        TyA = Derived->getBaseType().resolve(EmptyMap);
+    }
+    else {
+      break;
     }
   }
-  return nullptr;
+
+  return false;
+}
+
+// See if 'DGV' a member type of some other variable, and return that variable
+// and the offset and size DGV is into it.
+//
+// If DGV is not a member, just return nullptr.
+//
+static DIGlobalVariable *FindGlobalVariableFragment(const DebugInfoFinder &DbgFinder, DIGlobalVariable *DGV, unsigned *Out_OffsetInBits, unsigned *Out_SizeInBits) {
+  DITypeIdentifierMap EmptyMap;
+
+  StringRef FullName = DGV->getName();
+  size_t FirstDot = FullName.find_first_of('.');
+  if (FirstDot == StringRef::npos)
+    return nullptr;
+
+  StringRef BaseName = FullName.substr(0, FirstDot);
+  assert(BaseName.size());
+
+  DIType *Ty = DGV->getType().resolve(EmptyMap);
+  assert(isa<DIDerivedType>(Ty) && Ty->getTag() == dwarf::DW_TAG_member);
+
+  DIGlobalVariable *FinalResult = nullptr;
+
+  for (DIGlobalVariable *DGV_It : DbgFinder.global_variables()) {
+    if (DGV_It->getName() == BaseName &&
+      IsDerivedTypeOf(Ty, DGV_It->getType().resolve(EmptyMap)))
+    {
+      FinalResult = DGV_It;
+      break;
+    }
+  }
+
+  if (FinalResult) {
+    *Out_OffsetInBits = Ty->getOffsetInBits();
+    *Out_SizeInBits = Ty->getSizeInBits();
+  }
+
+  return FinalResult;
 }
 
 // Create a fake local variable for the GlobalVariable GV that has just been
 // lowered to local Alloca.
 //
 static
-void PatchDebugInfo(const DebugInfoFinder &DbgFinder, Function *F, GlobalVariable *GV, AllocaInst *AI) {
+void PatchDebugInfo(DebugInfoFinder &DbgFinder, Function *F, GlobalVariable *GV, AllocaInst *AI) {
   if (!DbgFinder.compile_unit_count())
     return;
 
@@ -6305,7 +6357,7 @@ void PatchDebugInfo(const DebugInfoFinder &DbgFinder, Function *F, GlobalVariabl
     }
   }
 
-  DIGlobalVariable *DGV = FindGlobalVariableFor(DbgFinder, GV);
+  DIGlobalVariable *DGV = dxilutil::FindGlobalVariableDebugInfo(GV, DbgFinder);
   if (!DGV)
     return;
 
@@ -6314,6 +6366,15 @@ void PatchDebugInfo(const DebugInfoFinder &DbgFinder, Function *F, GlobalVariabl
   DIScope *Scope = Subprogram;
   DebugLoc Loc = DebugLoc::get(0, 0, Scope);
 
+  // If the variable is a member of another variable, find the offset and size
+  bool IsFragment = false;
+  unsigned OffsetInBits = 0,
+           SizeInBits = 0;
+  if (DIGlobalVariable *UnsplitDGV = FindGlobalVariableFragment(DbgFinder, DGV, &OffsetInBits, &SizeInBits)) {
+    DGV = UnsplitDGV;
+    IsFragment = true;
+  }
+
   std::string Name = "global.";
   Name += DGV->getName();
   // Using arg_variable instead of auto_variable because arg variables can use
@@ -6321,10 +6382,20 @@ void PatchDebugInfo(const DebugInfoFinder &DbgFinder, Function *F, GlobalVariabl
   llvm::dwarf::Tag Tag = llvm::dwarf::Tag::DW_TAG_arg_variable;
 
   DIType *Ty = DGV->getType().resolve(EmptyMap);
+  DXASSERT(Ty->getTag() != dwarf::DW_TAG_member, "Member type is not allowed for variables.");
   DILocalVariable *ConvertedLocalVar =
     DIB.createLocalVariable(Tag, Scope,
       Name, DGV->getFile(), DGV->getLine(), Ty);
-  DIB.insertDeclare(AI, ConvertedLocalVar, DIB.createExpression(ArrayRef<int64_t>()), Loc, AI->getNextNode());
+
+  DIExpression *Expr = nullptr;
+  if (IsFragment) {
+    Expr = DIB.createBitPieceExpression(OffsetInBits, SizeInBits);
+  }
+  else {
+    Expr = DIB.createExpression(ArrayRef<int64_t>());
+  }
+
+  DIB.insertDeclare(AI, ConvertedLocalVar, Expr, Loc, AI->getNextNode());
 }
 
 bool LowerStaticGlobalIntoAlloca::lowerStaticGlobalIntoAlloca(GlobalVariable *GV, const DataLayout &DL) {

+ 1 - 3
tools/clang/test/HLSLFileCheck/dxil/debug/global_vec.hlsl

@@ -16,7 +16,5 @@ float4 main(float4 vec : COLOR, int index : INDEX) : SV_Target {
 // Exclude quoted source file (see readme)
 // CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
 
-// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.MyGlobal
-// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.MyGlobal
-// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.MyGlobal
+// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.MyGlobal"
 

+ 49 - 0
tools/clang/test/HLSLFileCheck/dxil/debug/merged_global_alloca.hlsl

@@ -0,0 +1,49 @@
+// RUN: %dxc %s /T ps_6_0 /Zi /Od | FileCheck %s
+
+// CHECK-LABEL: @main
+
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 0, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 32, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 64, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 96, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 128, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 160, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 192, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 224, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 256, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 288, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 320, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 352, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 384, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 416, 32)
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+struct Baz {
+  float4 a;
+};
+
+struct Bar_ {
+  float4 a;
+  Baz baz;
+};
+typedef Bar_ Bar;
+
+struct Foo {
+  float4 a;
+  Bar bar;
+  float2 b;
+};
+
+static Foo foo;
+
+[RootSignature("")]
+float4 main(float4 a : A, float2 b : B) : SV_Target {
+  foo.a = a * 2;
+  foo.bar.a = a /2;
+  foo.bar.baz.a = a + float4(2,2,2,2);
+  foo.b = b * 2;
+  return foo.a + float4(foo.b, foo.b) * foo.bar.a + foo.bar.baz.a;
+}
+

+ 43 - 0
tools/clang/test/HLSLFileCheck/dxil/debug/merged_global_alloca_array.hlsl

@@ -0,0 +1,43 @@
+// RUN: %dxc %s /T ps_6_0 /Zi /Od | FileCheck %s
+// CHECK-LABEL: @main
+
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 0, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 32, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 64, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 96, 32)
+
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 896, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 928, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 960, 32)
+// CHECK-DAG: call void @llvm.dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"global.foo" !DIExpression(DW_OP_bit_piece, 992, 32)
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+struct Foo {
+  float4 a;
+  float2 b[12];
+  float4 c;
+};
+
+static Foo foo;
+
+[RootSignature("")]
+float4 main(float4 a : A, float2 b : B, float4 c : C, uint i : I) : SV_Target {
+  foo.a = a * 2;
+  foo.b[0] = b;
+  foo.b[1] = b*2;
+  foo.b[2] = b*3;
+  foo.b[3] = b*5;
+  foo.b[4] = b*6;
+  foo.b[5] = b*7;
+  foo.b[6] = b*8;
+  foo.b[7] = b*9;
+  foo.b[8] = b*10;
+  foo.b[9] = b*11;
+  foo.b[10] = b*12;
+  foo.b[11] = b*13;
+  foo.c = c * 2;
+  return foo.a + float4(foo.b[i%4+2], foo.b[i%4]) + foo.c;
+}
+