diff options
| -rw-r--r-- | source/slang/slang-emit-spirv-ops-debug-info-ext.h | 8 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 245 | ||||
| -rw-r--r-- | source/slang/slang-ir-addr-inst-elimination.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-insert-debug-value-store.cpp | 51 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-ir-legalize-types.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 7 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 23 | ||||
| -rw-r--r-- | tests/spirv/debug-type-pointer-2.slang | 2 | ||||
| -rw-r--r-- | tests/spirv/debug-type-pointer.slang | 1 |
10 files changed, 236 insertions, 114 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 602adfee7..fdfcd7d1a 100644 --- a/source/slang/slang-emit-spirv-ops-debug-info-ext.h +++ b/source/slang/slang-emit-spirv-ops-debug-info-ext.h @@ -138,6 +138,14 @@ SpvInst* emitOpDebugValue(SpvInstParent* parent, IRInst* inst, const T& idResult } template<typename T, typename Ts> +SpvInst* emitOpDebugDeclare(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, SpvInst* debugLocalVar, IRInst* actualLocalVar, SpvInst* expression, const Ts& indices) +{ + static_assert(isSingular<T>); + static_assert(isPlural<Ts>); + + return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(28), debugLocalVar, actualLocalVar, expression, indices); +} +template<typename T, typename Ts> SpvInst* emitOpDebugExpression(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, const Ts& operations) { static_assert(isSingular<T>); diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index c1fe8c7e1..3ba7cf43b 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1432,7 +1432,7 @@ struct SPIRVEmitContext return m_targetProgram->getOptionSet().getBoolOption(CompilerOptionName::VulkanEmitReflection); } - void requireVariablePointers() + void requirePhysicalStorageAddressing() { if (m_addressingMode == SpvAddressingModelPhysicalStorageBuffer64) return; @@ -1511,7 +1511,7 @@ struct SPIRVEmitContext ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_storage_buffer_storage_class")); if (storageClass == SpvStorageClassPhysicalStorageBuffer) { - requireVariablePointers(); + requirePhysicalStorageAddressing(); } auto valueType = ptrType->getValueType(); // If we haven't emitted the inner type yet, we need to emit a forward declaration. @@ -1688,7 +1688,7 @@ struct SPIRVEmitContext return emitOpTypeHitObject(inst); case kIROp_HLSLConstBufferPointerType: - requireVariablePointers(); + requirePhysicalStorageAddressing(); return emitOpTypePointer(inst, SpvStorageClassPhysicalStorageBuffer, inst->getOperand(0)); case kIROp_FuncType: @@ -2724,41 +2724,32 @@ struct SPIRVEmitContext auto spvBlock = emitOpLabel(spvFunc, irBlock); if (irBlock == irFunc->getFirstBlock()) { - // OpVariable + // OpVariable and OpDebugVariable // All variables used in the function must be declared before anything else. for (auto block : irFunc->getBlocks()) { for (auto inst : block->getChildren()) { - if (as<IRVar>(inst)) + switch (inst->getOp()) + { + case kIROp_Var: emitLocalInst(spvBlock, inst); + break; + case kIROp_DebugVar: + // Declare an ordinary local variable for debugDeclare association of a debug variable. + // This variable is what we will actually write values to upon a `kIROp_DebugValue` inst. + emitDebugVarBackingLocalVarDeclaration(spvBlock, as<IRDebugVar>(inst)); + break; + } } } // DebugInfo. funcDebugScope = emitDebugFunction(spvBlock, spvFunc, irFunc); } - if (funcDebugScope) { - if (auto entryPointDecor = irFunc->findDecoration<IREntryPointDecoration>()) - { - if (auto debugScope = findDebugScope(irFunc->getModule()->getModuleInst())) - { - IRBuilder builder(irFunc); - String cmdArgs = getDebugInfoCommandLineArgumentForEntryPoint(entryPointDecor); - emitOpDebugEntryPoint( - getSection(SpvLogicalSectionID::ConstantsAndTypes), - m_voidType, - getNonSemanticDebugInfoExtInst(), - funcDebugScope, - debugScope, - builder.getStringValue(toSlice("slangc")), - builder.getStringValue(cmdArgs.getUnownedSlice())); - } - } emitOpDebugScope(spvBlock, nullptr, m_voidType, getNonSemanticDebugInfoExtInst(), funcDebugScope); } - // In addition to normal basic blocks, // all loops gets a header block. for (auto irInst : irBlock->getChildren()) @@ -2770,6 +2761,26 @@ struct SPIRVEmitContext } } + if (funcDebugScope) + { + if (auto entryPointDecor = irFunc->findDecoration<IREntryPointDecoration>()) + { + if (auto debugScope = findDebugScope(irFunc->getModule()->getModuleInst())) + { + IRBuilder builder(irFunc); + String cmdArgs = getDebugInfoCommandLineArgumentForEntryPoint(entryPointDecor); + emitOpDebugEntryPoint( + getSection(SpvLogicalSectionID::ConstantsAndTypes), + m_voidType, + getNonSemanticDebugInfoExtInst(), + funcDebugScope, + debugScope, + builder.getStringValue(toSlice("slangc")), + builder.getStringValue(cmdArgs.getUnownedSlice())); + } + } + } + // Once all the basic blocks have had instructions allocated // for them, we go through and fill them in with their bodies. // @@ -2993,6 +3004,97 @@ struct SPIRVEmitContext } } + SpvInst* emitDebugVarDeclaration(SpvInstParent* parent, IRDebugVar* debugVar) + { + // For every DebugVar, we will declare: + // - An OpDebugLocalVariable `spvDebugLocalVar` + // - An OpVariable `actualHelperVar` + // - An OpDebugDeclare to associate `spvDebugLocalVar` with `actualHelperVar` + // The `actualHelperVar` is used to update the actual value of the variable + // at each kIROp_DebugValue instruction. + // + auto scope = findDebugScope(debugVar); + if (!scope) + return nullptr; + + bool hasBackingVar = m_mapIRInstToSpvInst.containsKey(debugVar); + + IRBuilder builder(debugVar); + builder.setInsertBefore(debugVar); + + auto name = getName(debugVar); + auto varType = tryGetPointedToType(&builder, debugVar->getDataType()); + auto debugType = emitDebugType(varType); + + auto spvDebugLocalVar = emitOpDebugLocalVariable( + getSection(SpvLogicalSectionID::ConstantsAndTypes), + hasBackingVar ? nullptr : debugVar, + m_voidType, + getNonSemanticDebugInfoExtInst(), + name, + debugType, + debugVar->getSource(), + debugVar->getLine(), + debugVar->getCol(), + scope, + builder.getIntValue(builder.getUIntType(), 0), + debugVar->getArgIndex()); + + if (hasBackingVar) + { + emitOpDebugDeclare(parent, nullptr, m_voidType, getNonSemanticDebugInfoExtInst(), + spvDebugLocalVar, debugVar, getDwarfExpr(), List<SpvInst*>()); + } + + return spvDebugLocalVar; + } + + bool isLegalType(IRInst* type) + { + switch (type->getOp()) + { + case kIROp_UnsizedArrayType: + return false; + case kIROp_ArrayType: + return isLegalType(as<IRArrayType>(type)->getElementType()); + case kIROp_VectorType: + case kIROp_StructType: + case kIROp_MatrixType: + return true; + case kIROp_PtrType: + return as<IRPtrTypeBase>(type)->getAddressSpace() == AddressSpace::UserPointer; + default: + if (as<IRBasicType>(type)) + return true; + return false; + } + } + + SpvInst* emitDebugVarBackingLocalVarDeclaration(SpvInstParent* parent, IRDebugVar* debugVar) + { + auto scope = findDebugScope(debugVar); + if (!scope) + return nullptr; + + IRBuilder builder(debugVar); + builder.setInsertBefore(debugVar); + auto varType = tryGetPointedToType(&builder, debugVar->getDataType()); + + if (!isLegalType(varType)) + return nullptr; + + IRSizeAndAlignment sizeAlignment; + getNaturalSizeAndAlignment(this->m_targetRequest->getOptionSet(), varType, &sizeAlignment); + if (sizeAlignment.size != IRSizeAndAlignment::kIndeterminateSize) + { + auto debugVarPtrType = builder.getPtrType(varType, AddressSpace::Function); + auto actualHelperVar = emitOpVariable(parent, debugVar, debugVarPtrType, SpvStorageClassFunction); + maybeEmitPointerDecoration(actualHelperVar, debugVar); + return actualHelperVar; + } + return nullptr; + } + // The instructions that appear inside the basic blocks of // functions are what we will call "local" instructions. // @@ -3310,7 +3412,7 @@ struct SPIRVEmitContext result = emitDebugLine(parent, as<IRDebugLine>(inst)); break; case kIROp_DebugVar: - result = emitDebugVar(parent, as<IRDebugVar>(inst)); + result = emitDebugVarDeclaration(parent, as<IRDebugVar>(inst)); break; case kIROp_DebugValue: result = emitDebugValue(parent, as<IRDebugValue>(inst)); @@ -4803,7 +4905,8 @@ struct SPIRVEmitContext getSection(SpvLogicalSectionID::Annotations), nullptr, varInst, - (inst->getOp() == kIROp_GlobalVar || inst->getOp() == kIROp_Var ? SpvDecorationAliasedPointer : SpvDecorationAliased) + (inst->getOp() == kIROp_GlobalVar || inst->getOp() == kIROp_Var || inst->getOp() == kIROp_DebugVar + ? SpvDecorationAliasedPointer : SpvDecorationAliased) ); } } @@ -6188,21 +6291,6 @@ struct SPIRVEmitContext debugLine->getColEnd()); } - SpvInst* emitDebugVar(SpvInstParent* parent, IRDebugVar* debugVar) - { - SLANG_UNUSED(parent); - auto scope = findDebugScope(debugVar); - if (!scope) - return nullptr; - IRBuilder builder(debugVar); - auto name = getName(debugVar); - auto debugType = emitDebugType(debugVar->getDataType()); - auto spvLocalVar = emitOpDebugLocalVariable(getSection(SpvLogicalSectionID::ConstantsAndTypes), debugVar, m_voidType, getNonSemanticDebugInfoExtInst(), - name, debugType, debugVar->getSource(), debugVar->getLine(), debugVar->getCol(), scope, - builder.getIntValue(builder.getUIntType(), 0), debugVar->getArgIndex()); - return spvLocalVar; - } - SpvInst* getDwarfExpr() { if (m_nullDwarfExpr) @@ -6216,21 +6304,18 @@ struct SPIRVEmitContext return m_nullDwarfExpr; } - SpvInst* emitDebugValue(SpvInstParent* parent, IRDebugValue* debugValue) + bool translateIRAccessChain(IRBuilder& builder, IRInst* baseType, const List<IRInst*>& irAccessChain, List<SpvInst*>& spvAccessChain) { - IRBuilder builder(debugValue); - - List<SpvInst*> accessChain; - auto type = unwrapAttributedType(debugValue->getDebugVar()->getDataType()); - for (UInt i = 0; i < debugValue->getAccessChainCount(); i++) + auto type = baseType; + for (Index i = 0; i < irAccessChain.getCount(); i++) { - auto element = debugValue->getAccessChain(i); + auto element = irAccessChain[i]; if (element->getOp() == kIROp_StructKey) { auto key = as<IRStructKey>(element); auto structType = as<IRStructType>(type); if (!structType) - return nullptr; + return false; UInt fieldIndex = 0; for (auto field : structType->getFields()) { @@ -6241,7 +6326,7 @@ struct SPIRVEmitContext } fieldIndex++; } - accessChain.add(emitIntConstant(fieldIndex, builder.getIntType())); + spvAccessChain.add(emitIntConstant(fieldIndex, builder.getIntType())); } else { @@ -6252,12 +6337,66 @@ struct SPIRVEmitContext else if (auto matrixType = as<IRMatrixType>(type)) type = builder.getVectorType(matrixType->getElementType(), matrixType->getColumnCount()); else - return nullptr; - accessChain.add(ensureInst(element)); + return false; + spvAccessChain.add(ensureInst(element)); + } + } + return true; + } + + SpvInst* emitDebugValue(SpvInstParent* parent, IRDebugValue* debugValue) + { + // We are asked to update the value for a debug variable. + // A debug variable is already emited as a OpDebugVariable + + // OpVariable + OpDebugDeclare. We only need to store the new value + // into the associated OpVariable. The `debugValue->getDebugVar()` inst + // already maps to the `OpVariable` SpvInst, so we just need to emit + // code for a store into the subset of the OpVariable with the correct + // accesschain defined in the debug value inst. + // + IRBuilder builder(debugValue); + builder.setInsertBefore(debugValue); + + // First we need to check if the debug variable has a backing ordinary + // variable. If it doesn't, we can't emit a store. + // + List<IRInst*> irAccessChain; + auto rootVar = getRootAddr(debugValue->getDebugVar(), irAccessChain); + SpvInst* spvDebugVar = nullptr; + if (!m_mapIRInstToSpvInst.tryGetValue(rootVar, spvDebugVar)) + return nullptr; + if (!spvDebugVar) + return nullptr; + if (spvDebugVar->opcode != SpvOpVariable) + { + // If the root variable can't be represented by a normal variable, + // try to emit a DebugValue if possible. Usually this means that the variable + // represents a shader resource. + // + // SPIR-V requires the access chain specified in a DebugValue operation to + // be fully static. We will skip emitting the debug inst if the access chain + // isn't static. + // + auto type = unwrapAttributedType(debugValue->getDebugVar()->getDataType()); + List<SpvInst*> accessChain; + bool isConstAccessChain = translateIRAccessChain(builder, type, irAccessChain, accessChain); + + if (isConstAccessChain) + { + return emitOpDebugValue( + parent, debugValue, m_voidType, getNonSemanticDebugInfoExtInst(), + rootVar, debugValue->getValue(), getDwarfExpr(), accessChain); } + + // Fallback to not emit anything for now. + return nullptr; } - return emitOpDebugValue(parent, debugValue, m_voidType, getNonSemanticDebugInfoExtInst(), - debugValue->getDebugVar(), debugValue->getValue(), getDwarfExpr(), accessChain); + + // The ordinary case is the debug variable has a backing ordinary variable. + // We can simply emit a store into the backing variable for the DebugValue operation. + // + builder.setInsertBefore(debugValue); + return emitOpStore(parent, debugValue, debugValue->getDebugVar(), debugValue->getValue()); } IRInst* getName(IRInst* inst) diff --git a/source/slang/slang-ir-addr-inst-elimination.cpp b/source/slang/slang-ir-addr-inst-elimination.cpp index b55f6b93d..8297f0180 100644 --- a/source/slang/slang-ir-addr-inst-elimination.cpp +++ b/source/slang/slang-ir-addr-inst-elimination.cpp @@ -170,6 +170,7 @@ struct AddressInstEliminationContext case kIROp_GetElementPtr: case kIROp_FieldAddress: case kIROp_Unmodified: + case kIROp_DebugValue: break; default: sink->diagnose(use->getUser()->sourceLoc, Diagnostics::unsupportedUseOfLValueForAutoDiff); diff --git a/source/slang/slang-ir-insert-debug-value-store.cpp b/source/slang/slang-ir-insert-debug-value-store.cpp index ee343b263..af86cb6dd 100644 --- a/source/slang/slang-ir-insert-debug-value-store.cpp +++ b/source/slang/slang-ir-insert-debug-value-store.cpp @@ -136,8 +136,7 @@ namespace Slang paramVal = builder.emitLoad(param); if (paramVal) { - ArrayView<IRInst*> accessChain; - builder.emitDebugValue(debugVar, paramVal, accessChain); + builder.emitDebugValue(debugVar, paramVal); } paramIndex++; } @@ -172,36 +171,11 @@ namespace Slang // Helper func to insert debugValue updates. auto setDebugValue = [&]( - IRInst* debugVar, IRInst* rootVar, IRInst* newValue, - ArrayView<IRInst*> accessChain, ArrayView<IRInst*> types) + IRInst* debugVar, IRInst* newValue, + ArrayView<IRInst*> accessChain) { - // SPIRV does not allow dynamic indices in DebugValue, - // so we need to stop the access chain at the first dynamic index. - Index i = 0; - for (; i < accessChain.getCount(); i++) - { - if (as<IRStructKey>(accessChain[i])) - { - continue; - } - if (as<IRIntLit>(accessChain[i])) - { - continue; - } - break; - } - // If everything is static on the access chain, we can simply emit a DebugValue. - if (i == accessChain.getCount()) - { - builder.emitDebugValue(debugVar, newValue, accessChain); - return; - } - - // Otherwise we need to load the entire composite value starting at the dynamic index access chain - // and set it. - auto compositePtr = builder.emitElementAddress(rootVar, accessChain.head(i), types.head(i)); - auto compositeVal = builder.emitLoad(compositePtr); - builder.emitDebugValue(debugVar, compositeVal, accessChain.head(i)); + auto ptr = builder.emitElementAddress(debugVar, accessChain); + builder.emitDebugValue(ptr, newValue); }; for (auto block : func->getBlocks()) { @@ -213,26 +187,24 @@ namespace Slang if (auto storeInst = as<IRStore>(inst)) { List<IRInst*> accessChain; - List<IRInst*> types; - auto varInst = getRootAddr(storeInst->getPtr(), accessChain, &types); + auto varInst = getRootAddr(storeInst->getPtr(), accessChain); IRInst* debugVar = nullptr; if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) { builder.setInsertAfter(storeInst); - setDebugValue(debugVar, varInst, storeInst->getVal(), accessChain.getArrayView(), types.getArrayView()); + setDebugValue(debugVar, storeInst->getVal(), accessChain.getArrayView()); } } else if (auto swizzledStore = as<IRSwizzledStore>(inst)) { List<IRInst*> accessChain; - List<IRInst*> types; - auto varInst = getRootAddr(swizzledStore->getDest(), accessChain, &types); + auto varInst = getRootAddr(swizzledStore->getDest(), accessChain); IRInst* debugVar = nullptr; if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) { builder.setInsertAfter(swizzledStore); auto loadVal = builder.emitLoad(swizzledStore->getDest()); - setDebugValue(debugVar, varInst, loadVal, accessChain.getArrayView(), types.getArrayView()); + setDebugValue(debugVar, loadVal, accessChain.getArrayView()); } } else if (auto callInst = as<IRCall>(inst)) @@ -246,14 +218,13 @@ namespace Slang if (!as<IRPtrTypeBase>(arg->getDataType())) continue; List<IRInst*> accessChain; - List<IRInst*> types; - auto varInst = getRootAddr(arg, accessChain, &types); + auto varInst = getRootAddr(arg, accessChain); IRInst* debugVar = nullptr; if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) { builder.setInsertAfter(callInst); auto loadVal = builder.emitLoad(arg); - setDebugValue(debugVar, varInst, loadVal, accessChain.getArrayView(), types.getArrayView()); + setDebugValue(debugVar, loadVal, accessChain.getArrayView()); } } } diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index bfe6c27b5..ba96fedf6 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -3289,8 +3289,6 @@ struct IRDebugValue : IRInst IR_LEAF_ISA(DebugValue) IRInst* getDebugVar() { return getOperand(0); } IRInst* getValue() { return getOperand(1); } - UInt getAccessChainCount() { return getOperandCount() - 2; } - IRInst* getAccessChain(UInt index) { return getOperand(2 + index); } }; struct IRDebugLocationDecoration : IRDecoration @@ -3798,7 +3796,7 @@ public: IRInst* emitDebugSource(UnownedStringSlice fileName, UnownedStringSlice source); IRInst* emitDebugLine(IRInst* source, IRIntegerValue lineStart, IRIntegerValue lineEnd, IRIntegerValue colStart, IRIntegerValue colEnd); IRInst* emitDebugVar(IRType* type, IRInst* source, IRInst* line, IRInst* col, IRInst* argIndex = nullptr); - IRInst* emitDebugValue(IRInst* debugVar, IRInst* debugValue, ArrayView<IRInst*> accessChain); + IRInst* emitDebugValue(IRInst* debugVar, IRInst* debugValue); /// Emit an LiveRangeStart instruction indicating the referenced item is live following this instruction IRLiveRangeStart* emitLiveRangeStart(IRInst* referenced); diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp index fe8ee311d..d95b84700 100644 --- a/source/slang/slang-ir-legalize-types.cpp +++ b/source/slang/slang-ir-legalize-types.cpp @@ -886,19 +886,13 @@ static LegalVal legalizeDebugVar(IRTypeLegalizationContext* context, LegalType t static LegalVal legalizeDebugValue(IRTypeLegalizationContext* context, LegalVal debugVar, LegalVal debugValue, IRDebugValue* originalInst) { // For now we just discard any special part and keep the ordinary part. - ShortList<IRInst*> accessChain; - for (UInt i = 0; i < originalInst->getAccessChainCount(); i++) - { - accessChain.add(originalInst->getAccessChain(i)); - } switch (debugValue.flavor) { case LegalType::Flavor::simple: return LegalVal::simple( context->builder->emitDebugValue( debugVar.getSimple(), - debugValue.getSimple(), - accessChain.getArrayView().arrayView)); + debugValue.getSimple())); case LegalType::Flavor::none: return LegalVal(); case LegalType::Flavor::pair: diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 2fd090877..56e6e1676 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -3325,21 +3325,20 @@ namespace Slang if (argIndex) { IRInst* args[] = { source, line, col, argIndex }; - return emitIntrinsicInst(type, kIROp_DebugVar, 4, args); + return emitIntrinsicInst(getPtrType(type), kIROp_DebugVar, 4, args); } else { IRInst* args[] = { source, line, col }; - return emitIntrinsicInst(type, kIROp_DebugVar, 3, args); + return emitIntrinsicInst(getPtrType(type), kIROp_DebugVar, 3, args); } } - IRInst* IRBuilder::emitDebugValue(IRInst* debugVar, IRInst* debugValue, ArrayView<IRInst*> accessChain) + IRInst* IRBuilder::emitDebugValue(IRInst* debugVar, IRInst* debugValue) { List<IRInst*> args; args.add(debugVar); args.add(debugValue); - args.addRange(accessChain); return emitIntrinsicInst(getVoidType(), kIROp_DebugValue, (UInt)args.getCount(), args.getBuffer()); } diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index f5ec90d03..ecc06ebfd 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -2969,6 +2969,10 @@ Type* getThisParamTypeForCallable( return getThisParamTypeForContainer(context, parentDeclRef); } +struct StmtLoweringVisitor; + +void maybeEmitDebugLine(IRGenContext* context, StmtLoweringVisitor& visitor, Stmt* stmt, SourceLoc loc = SourceLoc()); + // When lowering something callable (most commonly a function declaration), // we need to construct an appropriate parameter list for the IR function // that folds in any contributions from both the declaration itself *and* @@ -5982,6 +5986,8 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor> // want to emit the expression for the loop condition: if (const auto condExpr = stmt->predicateExpression) { + maybeEmitDebugLine(context, *this, stmt, condExpr->loc); + auto irCondition = getSimpleVal(context, lowerRValueExpr(context, stmt->predicateExpression)); @@ -6031,6 +6037,7 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor> insertBlock(continueLabel); if (auto incrExpr = stmt->sideEffectExpression) { + maybeEmitDebugLine(context, *this, stmt, incrExpr->loc); lowerRValueExpr(context, incrExpr); } @@ -6082,6 +6089,8 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor> // want to emit the expression for the loop condition: if (auto condExpr = stmt->predicate) { + maybeEmitDebugLine(context, *this, stmt, condExpr->loc); + auto irCondition = getSimpleVal(context, lowerRValueExpr(context, condExpr)); @@ -6149,6 +6158,8 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor> // want to emit the expression for the loop condition: if (auto condExpr = stmt->predicate) { + maybeEmitDebugLine(context, *this, stmt, stmt->predicate->loc); + auto irCondition = getSimpleVal(context, lowerRValueExpr(context, condExpr)); @@ -6805,22 +6816,24 @@ IRInst* getOrEmitDebugSource(IRGenContext* context, PathInfo path) return debugSrcInst; } -void maybeEmitDebugLine(IRGenContext* context, StmtLoweringVisitor& visitor, Stmt* stmt) +void maybeEmitDebugLine(IRGenContext* context, StmtLoweringVisitor& visitor, Stmt* stmt, SourceLoc loc) { if (!context->includeDebugInfo) return; if (as<EmptyStmt>(stmt)) return; + if (!loc.isValid()) + loc = stmt->loc; auto sourceManager = context->getLinkage()->getSourceManager(); - auto sourceView = context->getLinkage()->getSourceManager()->findSourceView(stmt->loc); + auto sourceView = context->getLinkage()->getSourceManager()->findSourceView(loc); if (!sourceView) return; IRInst* debugSourceInst = nullptr; - auto humaneLoc = context->getLinkage()->getSourceManager()->getHumaneLoc(stmt->loc, SourceLocType::Emit); + auto humaneLoc = context->getLinkage()->getSourceManager()->getHumaneLoc(loc, SourceLocType::Emit); // Do a best-effort attempt to retrieve the nominal source file. - auto pathInfo = sourceView->getPathInfo(stmt->loc, SourceLocType::Emit); + auto pathInfo = sourceView->getPathInfo(loc, SourceLocType::Emit); // If the source file path correspond to an existing SourceFile in the source manager, use it. auto source = sourceManager->findSourceFileByPathRecursively(pathInfo.foundPath); @@ -6867,7 +6880,7 @@ void lowerStmt( try { - maybeEmitDebugLine(context, visitor, stmt); + maybeEmitDebugLine(context, visitor, stmt, stmt->loc); visitor.dispatch(stmt); } // Don't emit any context message for an explicit `AbortCompilationException` diff --git a/tests/spirv/debug-type-pointer-2.slang b/tests/spirv/debug-type-pointer-2.slang index 4112d4905..49ee9a48b 100644 --- a/tests/spirv/debug-type-pointer-2.slang +++ b/tests/spirv/debug-type-pointer-2.slang @@ -18,7 +18,7 @@ uniform Problem probs; RWStructuredBuffer<float4> outputBuffer; [shader("compute")] -float4 main() +void 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 f6add1735..62bd4fda1 100644 --- a/tests/spirv/debug-type-pointer.slang +++ b/tests/spirv/debug-type-pointer.slang @@ -32,7 +32,6 @@ struct LinkedNode float test(LinkedNode *pNode) { - //SPV: DebugValue %pNodeNext LinkedNode *pNodeNext = pNode->pNext; return *(pNode->pValue) + pNodeNext->value; } |
