summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-10-16 09:54:43 -0700
committerGitHub <noreply@github.com>2024-10-16 09:54:43 -0700
commit2ee898109006986250d5356a59003eb741a89ca4 (patch)
treed1c6f9c4cc7b17878c8bba53f6f89754e0a713e1
parent9e32b006318814e688501c4b547308d7fb472e78 (diff)
Fix spirv debug info for pointer types. (#5319)
* Fix spirv debug info for pointer types. * fix comment.
-rw-r--r--source/slang/slang-emit-spirv.cpp65
-rw-r--r--source/slang/slang-type-layout.h6
-rw-r--r--tests/spirv/debug-type-pointer-2.slang24
-rw-r--r--tests/spirv/debug-type-pointer.slang2
4 files changed, 60 insertions, 37 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index ede573581..0f123b8fd 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -6233,6 +6233,7 @@ struct SPIRVEmitContext
}
Dictionary<IRType*, SpvInst*> m_mapTypeToDebugType;
+ HashSet<IRType*> m_emittingTypes; // Types that are being emitted.
Dictionary<IRType*, SpvInst*> m_mapForwardRefsToDebugType;
static constexpr const int kUnknownPhysicalLayout = 1 << 17;
@@ -6289,9 +6290,9 @@ struct SPIRVEmitContext
{
auto fieldPtrBaseType = fieldPtrType->getValueType();
if (as<IRStructType>(fieldPtrBaseType)
- && !m_mapTypeToDebugType.containsKey(fieldPtrBaseType))
+ && m_emittingTypes.contains(fieldPtrBaseType))
{
- forwardRef = emitDebugForwardRefs(type);
+ forwardRef = emitDebugForwardRefs(fieldPtrBaseType);
SpvStorageClass storageClass = SpvStorageClassFunction;
if (fieldPtrType->hasAddressSpace())
@@ -6327,18 +6328,21 @@ struct SPIRVEmitContext
builder.getIntValue(builder.getUIntType(), sizeAlignment.size * 8),
builder.getIntValue(builder.getUIntType(), 0));
members.add(memberType);
+ }
- if (forwardRef)
- {
- // "OpExtInstWithForwardRefsKHR" requires "forward declared ID" at the end.
- // TODO: May want to free/release the memory properly
- auto tmp = m_memoryArena.allocateArray<SpvWord>(forwardRef->operandWordsCount + 1u);
- ::memcpy(tmp, forwardRef->operandWords, forwardRef->operandWordsCount * sizeof(SpvWord));
- tmp[forwardRef->operandWordsCount] = getID(memberType);
- forwardRef->operandWords = tmp;
- forwardRef->operandWordsCount++;
- }
+ SpvInst* forwardRef = nullptr;
+ // If `type` has been declared with a forward reference, fill in the forward reference.
+ if (m_mapForwardRefsToDebugType.tryGetValue(type, forwardRef))
+ {
+ // "OpExtInstWithForwardRefsKHR" requires "forward declared ID" at the end.
+ auto tmp = m_memoryArena.allocateArray<SpvWord>(forwardRef->operandWordsCount + members.getCount());
+ memcpy(tmp, forwardRef->operandWords, forwardRef->operandWordsCount * sizeof(SpvWord));
+ for (Index i = 0; i < members.getCount(); i++)
+ tmp[forwardRef->operandWordsCount + i] = getID(members[i]);
+ forwardRef->operandWords = tmp;
+ forwardRef->operandWordsCount += (uint32_t)members.getCount();
}
+
return emitOpDebugTypeComposite(
getSection(SpvLogicalSectionID::ConstantsAndTypes),
nullptr,
@@ -6453,35 +6457,19 @@ struct SPIRVEmitContext
else if (auto ptrType = as<IRPtrTypeBase>(type))
{
IRType* baseType = ptrType->getValueType();
- if (as<IRBasicType>(baseType))
- {
- // If the base type of the pointer is basic types,
- // emit the basic types and emit DebugTypePointer with it.
- SpvInst* debugBaseType = emitDebugType(baseType);
- SpvStorageClass storageClass = SpvStorageClassFunction;
- if (ptrType->hasAddressSpace())
- storageClass = addressSpaceToStorageClass(ptrType->getAddressSpace());
-
- return emitOpDebugTypePointer(
- getSection(SpvLogicalSectionID::ConstantsAndTypes),
- nullptr,
- m_voidType,
- getNonSemanticDebugInfoExtInst(),
- debugBaseType,
- builder.getIntValue(builder.getUIntType(), storageClass),
- builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
- }
+ // Emit DebugTypePointer for pointer types.
+ SpvInst* debugBaseType = emitDebugType(baseType);
+ SpvStorageClass storageClass = SpvStorageClassFunction;
+ if (ptrType->hasAddressSpace())
+ storageClass = addressSpaceToStorageClass(ptrType->getAddressSpace());
- // If the base type of the pointer is more complex,
- // emit the pointer as "uintptr" of DebugTypeBasic.
- return emitOpDebugTypeBasic(
+ return emitOpDebugTypePointer(
getSection(SpvLogicalSectionID::ConstantsAndTypes),
nullptr,
m_voidType,
getNonSemanticDebugInfoExtInst(),
- builder.getStringValue(String("uint64").getUnownedSlice()),
- builder.getIntValue(builder.getUIntType(), 64),
- builder.getIntValue(builder.getUIntType(), 0),
+ debugBaseType,
+ builder.getIntValue(builder.getUIntType(), storageClass),
builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
}
return ensureInst(m_voidType);
@@ -6491,7 +6479,12 @@ struct SPIRVEmitContext
{
if (auto debugType = m_mapTypeToDebugType.tryGetValue(type))
return *debugType;
+ bool isStruct = type->getOp() == kIROp_StructType;
+ if (isStruct)
+ m_emittingTypes.add(type);
auto result = emitDebugTypeImpl(type);
+ if (isStruct)
+ m_emittingTypes.remove(type);
m_mapTypeToDebugType[type] = result;
return result;
}
diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h
index 701708363..4248df508 100644
--- a/source/slang/slang-type-layout.h
+++ b/source/slang/slang-type-layout.h
@@ -692,6 +692,12 @@ public:
// Should this derive from SequenceTypeLayout? A pointer is kind of like an array without
// bounds - in that it can be indexed. Of it it can be looked at as an indirection to a value.
// Is the "Just Work"iness applicable?
+ // TODO(Yong):
+ // This reference can lead to memory leak when we have `struct S{ S* f; };`
+ // where `f` will have a var layout whose type layout is a pointer type layout
+ // whose valueTypeLayout is the layout for `S` itself, forming a cycle.
+ // We need to stop using reference pointers for layouts and instead allocate all
+ // type layout object from MemoryArena on the linkage.
RefPtr<TypeLayout> valueTypeLayout;
};
diff --git a/tests/spirv/debug-type-pointer-2.slang b/tests/spirv/debug-type-pointer-2.slang
new file mode 100644
index 000000000..4112d4905
--- /dev/null
+++ b/tests/spirv/debug-type-pointer-2.slang
@@ -0,0 +1,24 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv
+
+// Check that we do not emit forward reference for debug pointer types if there isn't a need to do so.
+
+// CHECK-NOT: OpExtension "SPV_KHR_relaxed_extended_instruction"
+struct T
+{
+ uint inner;
+}
+
+struct Problem
+{
+ int getVal() { return some_bda_ptr->inner;}
+ T *some_bda_ptr;
+}
+
+uniform Problem probs;
+
+RWStructuredBuffer<float4> outputBuffer;
+[shader("compute")]
+float4 main()
+{
+ outputBuffer[0] = float(probs.getVal());
+} \ No newline at end of file
diff --git a/tests/spirv/debug-type-pointer.slang b/tests/spirv/debug-type-pointer.slang
index fd3248c59..f6add1735 100644
--- a/tests/spirv/debug-type-pointer.slang
+++ b/tests/spirv/debug-type-pointer.slang
@@ -9,7 +9,7 @@ RWStructuredBuffer<float> outputBuffer;
//SPV:OpExtension "SPV_KHR_relaxed_extended_instruction"
//SPV: [[STRING_float:%[1-9][0-9]*]] = OpString "float"
//SPV: [[STRING_pValue:%[1-9][0-9]*]] = OpString "pValue"
-//SPV: [[STRING_LinkedNode:%[1-9][0-9]*]] = OpString "LinkedNode"
+//SPV: [[STRING_LinkedNode:%[1-9][0-9]*]] = OpString "LinkedNode{{.*}}"
//SPV: [[STRING_pNext:%[1-9][0-9]*]] = OpString "pNext"
struct LinkedNode