summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-emit-spirv-ops-debug-info-ext.h8
-rw-r--r--source/slang/slang-emit-spirv.cpp245
-rw-r--r--source/slang/slang-ir-addr-inst-elimination.cpp1
-rw-r--r--source/slang/slang-ir-insert-debug-value-store.cpp51
-rw-r--r--source/slang/slang-ir-insts.h4
-rw-r--r--source/slang/slang-ir-legalize-types.cpp8
-rw-r--r--source/slang/slang-ir.cpp7
-rw-r--r--source/slang/slang-lower-to-ir.cpp23
-rw-r--r--tests/spirv/debug-type-pointer-2.slang2
-rw-r--r--tests/spirv/debug-type-pointer.slang1
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;
}