summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorJay Kwak <82421531+jkwak-work@users.noreply.github.com>2024-07-18 15:20:42 -0700
committerGitHub <noreply@github.com>2024-07-18 15:20:42 -0700
commitce4ffc34204a56a7447db1e4aa0e7d89d74f34f1 (patch)
tree4ca464824f0ad66c249a2be84ae395dbdd447e11 /source
parentbe66cc88acebe87e175659df1afc2e4586ed8958 (diff)
Support OpDebugTypePointer for struct member pointer (#4527)
This change supports OpDebugTypePointer for a member variable whose type is a pointer type for the outer struct that hasn't been declared yet. It is done with new extension, "SPV_KHR_relaxed_extended_instruction", that comes with a new instruction, "OpExtInstWithForwardRefs". Closes #4304
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-emit-spirv-ops-debug-info-ext.h7
-rw-r--r--source/slang/slang-emit-spirv.cpp106
2 files changed, 108 insertions, 5 deletions
diff --git a/source/slang/slang-emit-spirv-ops-debug-info-ext.h b/source/slang/slang-emit-spirv-ops-debug-info-ext.h
index 0969b65a4..602adfee7 100644
--- a/source/slang/slang-emit-spirv-ops-debug-info-ext.h
+++ b/source/slang/slang-emit-spirv-ops-debug-info-ext.h
@@ -146,4 +146,11 @@ SpvInst* emitOpDebugExpression(SpvInstParent* parent, IRInst* inst, const T& idR
return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(31), operations);
}
+template<typename T>
+SpvInst* emitOpDebugForwardRefsComposite(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* name, IRInst* tag, IRInst* source, IRInst* line, IRInst* col, SpvInst* scope, IRInst* linkageName, IRInst* size, IRInst* flags)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInstWithForwardRefsKHR, idResultType, kResultID, set, SpvWord(10), name, tag, source, line, col, scope, linkageName, size, flags);
+}
+
#endif // SLANG_IN_SPIRV_EMIT_CONTEXT
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 6b84668e3..28d66497d 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -5816,11 +5816,11 @@ struct SPIRVEmitContext
}
Dictionary<IRType*, SpvInst*> m_mapTypeToDebugType;
+ Dictionary<IRType*, SpvInst*> m_mapForwardRefsToDebugType;
+ static constexpr const int kUnknownPhysicalLayout = 1 << 17;
SpvInst* emitDebugTypeImpl(IRType* type)
{
- static const int kUnknownPhysicalLayout = 1 << 17;
-
auto scope = findDebugScope(type);
if (!scope)
return ensureInst(m_voidType);
@@ -5851,7 +5851,7 @@ struct SPIRVEmitContext
{
static uint32_t uid = 0;
uid++;
- name = builder.getStringValue((String("unamed_type_") + String(uid)).getUnownedSlice());
+ name = builder.getStringValue((String("unnamed_type_") + String(uid)).getUnownedSlice());
}
IRSizeAndAlignment structSizeAlignment;
getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), type, &structSizeAlignment);
@@ -5862,14 +5862,47 @@ struct SPIRVEmitContext
IRIntegerValue offset = 0;
IRSizeAndAlignment sizeAlignment;
getNaturalOffset(m_targetProgram->getOptionSet(), field, &offset);
- getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), field->getFieldType(), &sizeAlignment);
+
+ auto fieldType = field->getFieldType();
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), fieldType, &sizeAlignment);
+
+ SpvInst* forwardRef = nullptr;
+ SpvInst* spvFieldType = nullptr;
+ if (auto fieldPtrType = as<IRPtrTypeBase>(fieldType))
+ {
+ auto fieldPtrBaseType = fieldPtrType->getValueType();
+ if (as<IRStructType>(fieldPtrBaseType)
+ && !m_mapTypeToDebugType.containsKey(fieldPtrBaseType))
+ {
+ forwardRef = emitDebugForwardRefs(type);
+
+ SpvStorageClass storageClass = SpvStorageClassFunction;
+ if (fieldPtrType->hasAddressSpace())
+ storageClass = (SpvStorageClass)fieldPtrType->getAddressSpace();
+
+ spvFieldType = emitOpDebugTypePointer(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ forwardRef,
+ builder.getIntValue(builder.getUIntType(), storageClass),
+ builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
+ }
+ }
+
+ if (spvFieldType == nullptr)
+ {
+ spvFieldType = emitDebugType(fieldType);
+ }
+
auto memberType = emitOpDebugTypeMember(
getSection(SpvLogicalSectionID::ConstantsAndTypes),
nullptr,
m_voidType,
getNonSemanticDebugInfoExtInst(),
getName(field->getKey()),
- emitDebugType(field->getFieldType()),
+ spvFieldType,
source,
line,
col,
@@ -5877,6 +5910,17 @@ 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++;
+ }
}
return emitOpDebugTypeComposite(
getSection(SpvLogicalSectionID::ConstantsAndTypes),
@@ -6035,6 +6079,58 @@ struct SPIRVEmitContext
return result;
}
+ SpvInst* emitDebugForwardRefsImpl(IRType* type)
+ {
+ auto scope = findDebugScope(type);
+ if (!scope)
+ return ensureInst(m_voidType);
+
+ auto name = getName(type);
+ IRBuilder builder(type);
+
+ if (auto structType = as<IRStructType>(type))
+ {
+ auto loc = structType->findDecoration<IRDebugLocationDecoration>();
+ IRInst* source = loc ? loc->getSource() : m_defaultDebugSource;
+ IRInst* line = loc ? loc->getLine() : builder.getIntValue(builder.getUIntType(), 0);
+ IRInst* col = loc ? loc->getCol() : line;
+ if (!name)
+ {
+ static uint32_t uid = 0;
+ uid++;
+ name = builder.getStringValue((String("unnamed_forward_type_") + String(uid)).getUnownedSlice());
+ }
+ IRSizeAndAlignment structSizeAlignment;
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), type, &structSizeAlignment);
+
+ ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_relaxed_extended_instruction"));
+ return emitOpDebugForwardRefsComposite(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ name,
+ builder.getIntValue(builder.getUIntType(), 1), // struct
+ source,
+ line,
+ col,
+ scope,
+ name,
+ builder.getIntValue(builder.getUIntType(), structSizeAlignment.size * 8),
+ builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
+ }
+ SLANG_UNIMPLEMENTED_X("Not implemented forward pointer debug type");
+ }
+
+ SpvInst* emitDebugForwardRefs(IRType* type)
+ {
+ if (auto debugType = m_mapForwardRefsToDebugType.tryGetValue(type))
+ return *debugType;
+ auto result = emitDebugForwardRefsImpl(type);
+ m_mapForwardRefsToDebugType[type] = result;
+ return result;
+ }
+
SpvInst* emitDebugFunction(SpvInst* firstBlock, SpvInst* spvFunc, IRFunc* function)
{
auto scope = findDebugScope(function);