From ce4ffc34204a56a7447db1e4aa0e7d89d74f34f1 Mon Sep 17 00:00:00 2001 From: Jay Kwak <82421531+jkwak-work@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:20:42 -0700 Subject: 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 --- source/slang/slang-emit-spirv-ops-debug-info-ext.h | 7 ++ source/slang/slang-emit-spirv.cpp | 106 ++++++++++++++++++++- 2 files changed, 108 insertions(+), 5 deletions(-) (limited to 'source') 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 +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); + 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 m_mapTypeToDebugType; + Dictionary 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(fieldType)) + { + auto fieldPtrBaseType = fieldPtrType->getValueType(); + if (as(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(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(type)) + { + auto loc = structType->findDecoration(); + 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); -- cgit v1.2.3