summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang')
-rwxr-xr-xsource/slang/slang-compiler.h2
-rw-r--r--source/slang/slang-emit-c-like.cpp2
-rw-r--r--source/slang/slang-emit-spirv-ops-debug-info-ext.h99
-rw-r--r--source/slang/slang-emit-spirv.cpp341
-rw-r--r--source/slang/slang-ir-autodiff-fwd.cpp3
-rw-r--r--source/slang/slang-ir-autodiff-rev.cpp28
-rw-r--r--source/slang/slang-ir-insert-debug-value-store.cpp116
-rw-r--r--source/slang/slang-ir-insert-debug-value-store.h10
-rw-r--r--source/slang/slang-ir-inst-defs.h6
-rw-r--r--source/slang/slang-ir-insts.h33
-rw-r--r--source/slang/slang-ir-legalize-types.cpp88
-rw-r--r--source/slang/slang-ir-spirv-legalize.h8
-rw-r--r--source/slang/slang-ir-util.cpp54
-rw-r--r--source/slang/slang-ir-util.h4
-rw-r--r--source/slang/slang-ir.cpp48
-rw-r--r--source/slang/slang-legalize-types.cpp7
-rw-r--r--source/slang/slang-lower-to-ir.cpp35
-rw-r--r--source/slang/slang.cpp2
18 files changed, 828 insertions, 58 deletions
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index ece552cec..4876026a0 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -531,7 +531,7 @@ namespace Slang
protected:
ComponentType(Linkage* linkage);
- private:
+ protected:
Linkage* m_linkage;
CompilerOptionSet m_optionSet;
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 1c01478ed..c7561e611 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -2661,6 +2661,8 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
case kIROp_DebugSource:
case kIROp_DebugLine:
+ case kIROp_DebugVar:
+ case kIROp_DebugValue:
break;
// Insts that needs to be emitted as code blocks.
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 d1ca9665a..3d2a10aab 100644
--- a/source/slang/slang-emit-spirv-ops-debug-info-ext.h
+++ b/source/slang/slang-emit-spirv-ops-debug-info-ext.h
@@ -24,5 +24,104 @@ SpvInst* emitOpDebugLine(SpvInstParent* parent, IRInst* inst, const T& idResultT
return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(103), source, lineStart, lineEnd, colStart, colEnd);
}
+// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugFunction
+template<typename T>
+SpvInst* emitOpDebugFunction(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* name, SpvInst* type, IRInst* source, IRInst* lineStart, IRInst* colStart, SpvInst* scope, IRInst* linkageName, IRInst* flag, IRInst* scopeLine)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(20), name, type, source, lineStart, colStart, scope, linkageName, flag, scopeLine);
+}
+
+template<typename T>
+SpvInst* emitOpDebugFunctionDefinition(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, SpvInst* debugFunc, SpvInst* spvFunc)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(101), debugFunc, spvFunc);
+}
+
+template<typename T, typename Ts>
+SpvInst* emitOpDebugTypeFunction(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* flags, SpvInst* returnType, const Ts& argTypes)
+{
+ static_assert(isSingular<T>);
+ static_assert(isPlural<Ts>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(8), flags, returnType, argTypes);
+}
+
+template<typename T, typename Ts>
+SpvInst* emitOpDebugTypeComposite(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, const Ts& members)
+{
+ static_assert(isSingular<T>);
+ static_assert(isPlural<Ts>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(10), name, tag, source, line, col, scope, linkageName, size, flags, members);
+}
+
+template<typename T>
+SpvInst* emitOpDebugTypeMember(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* name, SpvInst* type, IRInst* source, IRInst* line, IRInst* col, IRInst* offset, IRInst* size, IRInst* flags)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(11), name, type, source, line, col, offset, size, flags);
+}
+
+template<typename T>
+SpvInst* emitOpDebugTypeArray(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, SpvInst* baseType, IRInst* elementCount)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(5), baseType, elementCount);
+}
+
+template<typename T>
+SpvInst* emitOpDebugTypeBasic(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* name, IRInst* size, IRInst* encoding, IRInst* flags)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(2), name, size, encoding, flags);
+}
+
+template<typename T>
+SpvInst* emitOpDebugTypeVector(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, SpvInst* baseType, IRInst* elementCount)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(6), baseType, elementCount);
+}
+
+template<typename T>
+SpvInst* emitOpDebugTypeMatrix(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, SpvInst* vectorType, IRInst* vectorCount, IRInst* columnMajor)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(108), vectorType, vectorCount, columnMajor);
+}
+
+template<typename T>
+SpvInst* emitOpDebugScope(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, SpvInst* scope)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(23), scope);
+}
+
+template<typename T>
+SpvInst* emitOpDebugLocalVariable(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* name, SpvInst* type, IRInst* source, IRInst* line, IRInst* col, SpvInst* scope, IRInst* flags, IRInst* argIndex)
+{
+ static_assert(isSingular<T>);
+ if (argIndex)
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(26), name, type, source, line, col, scope, flags, argIndex);
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(26), name, type, source, line, col, scope, flags);
+}
+
+template<typename T, typename Ts>
+SpvInst* emitOpDebugValue(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* localVar, IRInst* value, SpvInst* expression, const Ts& indices)
+{
+ static_assert(isSingular<T>);
+ static_assert(isPlural<Ts>);
+
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(29), localVar, value, 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>);
+ static_assert(isPlural<Ts>);
+
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(31), operations);
+}
#endif // SLANG_IN_SPIRV_EMIT_CONTEXT
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 5761d3ec4..64ef469ef 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -478,6 +478,8 @@ struct SPIRVEmitContext
OrderedHashSet<IRPtrTypeBase*> m_forwardDeclaredPointers;
+ SpvInst* m_nullDwarfExpr = nullptr;
+
// A hash set to prevent redecorating the same spv inst.
HashSet<SpvId> m_decoratedSpvInsts;
@@ -601,6 +603,9 @@ struct SPIRVEmitContext
{
for (auto parent = inst; parent; parent = parent->getParent())
{
+ if (!as<IRFunc>(parent) && !as<IRModuleInst>(parent))
+ continue;
+
SpvInst* spvInst = nullptr;
if (m_mapIRInstToSpvDebugInst.tryGetValue(parent, spvInst))
return spvInst;
@@ -1259,6 +1264,8 @@ struct SPIRVEmitContext
);
}
+ IRInst* m_defaultDebugSource = nullptr;
+
Dictionary<UnownedStringSlice, SpvInst*> m_extensionInsts;
SpvInst* ensureExtensionDeclaration(UnownedStringSlice name)
{
@@ -1592,6 +1599,8 @@ struct SPIRVEmitContext
debugSource->getFileName(),
debugSource->getSource());
auto moduleInst = inst->getModule()->getModuleInst();
+ if (!m_defaultDebugSource)
+ m_defaultDebugSource = debugSource;
if (!m_mapIRInstToSpvDebugInst.containsKey(moduleInst))
{
IRBuilder builder(inst);
@@ -2219,6 +2228,7 @@ struct SPIRVEmitContext
// not possible for ordinary instructions within
// the blocks in the Slang IR)
//
+ SpvInst* funcDebugScope = nullptr;
for( auto irBlock : irFunc->getBlocks() )
{
auto spvBlock = emitOpLabel(spvFunc, irBlock);
@@ -2234,6 +2244,13 @@ struct SPIRVEmitContext
emitLocalInst(spvBlock, inst);
}
}
+ // DebugInfo.
+ funcDebugScope = emitDebugFunction(spvBlock, spvFunc, irFunc);
+ }
+
+ if (funcDebugScope)
+ {
+ emitOpDebugScope(spvBlock, nullptr, m_voidType, getNonSemanticDebugInfoExtInst(), funcDebugScope);
}
// In addition to normal basic blocks,
@@ -2546,6 +2563,10 @@ struct SPIRVEmitContext
return emitInst(parent, inst, SpvOpSelect, inst->getFullType(), kResultID, OperandsOf(inst));
case kIROp_DebugLine:
return emitDebugLine(parent, as<IRDebugLine>(inst));
+ case kIROp_DebugVar:
+ return emitDebugVar(parent, as<IRDebugVar>(inst));
+ case kIROp_DebugValue:
+ return emitDebugValue(parent, as<IRDebugValue>(inst));
case kIROp_GetStringHash:
return emitGetStringHash(inst);
case kIROp_undefined:
@@ -4826,6 +4847,326 @@ 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);
+ if (!name)
+ {
+ static uint32_t uid = 0;
+ uid++;
+ name = builder.getStringValue((String("unamed_local_var_") + String(uid)).getUnownedSlice());
+ }
+ 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), nullptr);
+ return spvLocalVar;
+ }
+
+ SpvInst* getDwarfExpr()
+ {
+ if (m_nullDwarfExpr)
+ return m_nullDwarfExpr;
+ m_nullDwarfExpr = emitOpDebugExpression(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ List<SpvInst*>());
+ return m_nullDwarfExpr;
+ }
+
+ SpvInst* emitDebugValue(SpvInstParent* parent, IRDebugValue* debugValue)
+ {
+ IRBuilder builder(debugValue);
+
+ List<SpvInst*> accessChain;
+ auto type = unwrapAttributedType(debugValue->getDebugVar()->getDataType());
+ for (UInt i = 0; i < debugValue->getAccessChainCount(); i++)
+ {
+ auto element = debugValue->getAccessChain(i);
+ if (element->getOp() == kIROp_StructKey)
+ {
+ auto key = as<IRStructKey>(element);
+ auto structType = as<IRStructType>(type);
+ if (!structType)
+ return nullptr;
+ UInt fieldIndex = 0;
+ for (auto field : structType->getFields())
+ {
+ if (field->getKey() == key)
+ {
+ type = unwrapAttributedType(field->getFieldType());
+ break;
+ }
+ fieldIndex++;
+ }
+ accessChain.add(emitIntConstant(fieldIndex, builder.getIntType()));
+ }
+ else
+ {
+ if (auto arrayType = as<IRArrayTypeBase>(type))
+ type = arrayType->getElementType();
+ else if (auto vectorType = as<IRVectorType>(type))
+ type = vectorType->getElementType();
+ else if (auto matrixType = as<IRMatrixType>(type))
+ type = builder.getVectorType(matrixType->getElementType(), matrixType->getColumnCount());
+ else
+ return nullptr;
+ accessChain.add(ensureInst(element));
+ }
+ }
+ return emitOpDebugValue(parent, debugValue, m_voidType, getNonSemanticDebugInfoExtInst(),
+ debugValue->getDebugVar(), debugValue->getValue(), getDwarfExpr(), accessChain);
+ }
+
+ IRInst* getName(IRInst* inst)
+ {
+ IRInst* nameOperand = nullptr;
+ for (auto decor : inst->getDecorations())
+ {
+ if (auto nameHint = as<IRNameHintDecoration>(decor))
+ return nameHint->getNameOperand();
+ if (auto linkage = as<IRLinkageDecoration>(decor))
+ nameOperand = linkage->getMangledNameOperand();
+ }
+ if (nameOperand)
+ return nameOperand;
+
+ IRBuilder builder(inst);
+ return builder.getStringValue(toSlice("unamed"));
+ }
+
+ Dictionary<IRType*, SpvInst*> m_mapTypeToDebugType;
+
+ SpvInst* emitDebugTypeImpl(IRType* type)
+ {
+ static const int kUnknownPhysicalLayout = 1 << 17;
+
+ auto scope = findDebugScope(type);
+ if (!scope)
+ return ensureInst(m_voidType);
+
+ IRBuilder builder(type);
+ if (auto funcType = as<IRFuncType>(type))
+ {
+ List<SpvInst*> argTypes;
+ return emitOpDebugTypeFunction(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ builder.getIntValue(builder.getUIntType(), 0),
+ ensureInst(m_voidType),
+ argTypes);
+ }
+
+ auto name = getName(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("unamed_type_") + String(uid)).getUnownedSlice());
+ }
+ IRSizeAndAlignment structSizeAlignment;
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), type, &structSizeAlignment);
+
+ List<SpvInst*> members;
+ for (auto field : structType->getFields())
+ {
+ IRIntegerValue offset = 0;
+ IRSizeAndAlignment sizeAlignment;
+ getNaturalOffset(m_targetProgram->getOptionSet(), field, &offset);
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), field->getFieldType(), &sizeAlignment);
+ auto memberType = emitOpDebugTypeMember(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ getName(field->getKey()),
+ emitDebugType(field->getFieldType()),
+ source,
+ line,
+ col,
+ builder.getIntValue(builder.getUIntType(), offset * 8),
+ builder.getIntValue(builder.getUIntType(), sizeAlignment.size * 8),
+ builder.getIntValue(builder.getUIntType(), 0));
+ members.add(memberType);
+ }
+ return emitOpDebugTypeComposite(
+ 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),
+ members);
+ }
+
+ if (auto arrayType = as<IRArrayTypeBase>(type))
+ {
+ auto sizedArrayType = as<IRArrayType>(arrayType);
+ return emitOpDebugTypeArray(getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ emitDebugType(arrayType->getElementType()),
+ sizedArrayType
+ ? builder.getIntValue(builder.getUIntType(), getIntVal(sizedArrayType->getElementCount()))
+ : builder.getIntValue(builder.getUIntType(), 0));
+ }
+ else if (auto vectorType = as<IRVectorType>(type))
+ {
+ auto elementType = emitDebugType(vectorType->getElementType());
+ return emitOpDebugTypeVector(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ elementType,
+ builder.getIntValue(builder.getUIntType(), getIntVal(vectorType->getElementCount())));
+ }
+ else if (auto matrixType = as<IRMatrixType>(type))
+ {
+ IRInst* count = nullptr;
+ bool isColumnMajor = false;
+ IRType* innerVectorType = nullptr;
+ if (getIntVal(matrixType->getLayout()) == kMatrixLayoutMode_ColumnMajor)
+ {
+ innerVectorType = builder.getVectorType(matrixType->getElementType(), matrixType->getRowCount());
+ isColumnMajor = true;
+ count = matrixType->getColumnCount();
+ }
+ else
+ {
+ innerVectorType = builder.getVectorType(matrixType->getElementType(), matrixType->getColumnCount());
+ count = matrixType->getRowCount();
+ }
+ auto elementType = emitDebugType(innerVectorType);
+ return emitOpDebugTypeMatrix(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ elementType,
+ builder.getIntValue(builder.getUIntType(), getIntVal(vectorType->getElementCount())),
+ builder.getBoolValue(isColumnMajor));
+ }
+ else if (auto basicType = as<IRBasicType>(type))
+ {
+ IRSizeAndAlignment sizeAlignment;
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), basicType, &sizeAlignment);
+ int spvEncoding = 0;
+ StringBuilder sbName;
+ getTypeNameHint(sbName, basicType);
+ switch (type->getOp())
+ {
+ case kIROp_IntType:
+ case kIROp_Int16Type:
+ case kIROp_Int64Type:
+ case kIROp_Int8Type:
+ case kIROp_IntPtrType:
+ spvEncoding = 4; // Signed
+ break;
+ case kIROp_UIntType:
+ case kIROp_UInt16Type:
+ case kIROp_UInt64Type:
+ case kIROp_UInt8Type:
+ case kIROp_UIntPtrType:
+ spvEncoding = 6; // Unsigned
+ break;
+ case kIROp_FloatType:
+ case kIROp_DoubleType:
+ case kIROp_HalfType:
+ spvEncoding = 3; // Float
+ break;
+ case kIROp_BoolType:
+ spvEncoding = 2; // boolean
+ break;
+ default:
+ spvEncoding = 0; // Unspecified.
+ break;
+ }
+ return emitOpDebugTypeBasic(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ builder.getStringValue(sbName.getUnownedSlice()),
+ builder.getIntValue(builder.getUIntType(), sizeAlignment.size * 8),
+ builder.getIntValue(builder.getUIntType(), spvEncoding),
+ builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
+ }
+ else if (as<IRPtrTypeBase>(type))
+ {
+ StringBuilder sbName;
+ getTypeNameHint(sbName, basicType);
+ return emitOpDebugTypeBasic(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ builder.getStringValue(sbName.getUnownedSlice()),
+ builder.getIntValue(builder.getUIntType(), 64),
+ builder.getIntValue(builder.getUIntType(), 0),
+ builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
+ }
+ return ensureInst(m_voidType);
+ }
+
+ SpvInst* emitDebugType(IRType* type)
+ {
+ if (auto debugType = m_mapTypeToDebugType.tryGetValue(type))
+ return *debugType;
+ auto result = emitDebugTypeImpl(type);
+ m_mapTypeToDebugType[type] = result;
+ return result;
+ }
+
+ SpvInst* emitDebugFunction(SpvInst* firstBlock, SpvInst* spvFunc, IRFunc* function)
+ {
+ auto scope = findDebugScope(function);
+ if (!scope)
+ return nullptr;
+ auto name = getName(function);
+ if (!name)
+ return nullptr;
+ auto debugLoc = function->findDecoration<IRDebugLocationDecoration>();
+ if (!debugLoc)
+ return nullptr;
+ auto debugType = emitDebugType(function->getDataType());
+ IRBuilder builder(function);
+ auto debugFunc = emitOpDebugFunction(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr, m_voidType, getNonSemanticDebugInfoExtInst(),
+ name, debugType, debugLoc->getSource(), debugLoc->getLine(), debugLoc->getCol(), scope, name,
+ builder.getIntValue(builder.getUIntType(), 0), debugLoc->getLine());
+ registerDebugInst(function, debugFunc);
+
+ emitOpDebugFunctionDefinition(firstBlock, nullptr, m_voidType, getNonSemanticDebugInfoExtInst(), debugFunc, spvFunc);
+
+ return debugFunc;
+ }
+
SpvInst* emitSPIRVAsm(SpvInstParent* parent, IRSPIRVAsm* inst)
{
SpvInst* last = nullptr;
diff --git a/source/slang/slang-ir-autodiff-fwd.cpp b/source/slang/slang-ir-autodiff-fwd.cpp
index 334d4e678..546d24a4d 100644
--- a/source/slang/slang-ir-autodiff-fwd.cpp
+++ b/source/slang/slang-ir-autodiff-fwd.cpp
@@ -1920,6 +1920,9 @@ InstPair ForwardDiffTranscriber::transcribeInstImpl(IRBuilder* builder, IRInst*
case kIROp_GetSequentialID:
case kIROp_GetStringHash:
case kIROp_SPIRVAsm:
+ case kIROp_DebugLine:
+ case kIROp_DebugVar:
+ case kIROp_DebugValue:
return transcribeNonDiffInst(builder, origInst);
// A call to createDynamicObject<T>(arbitraryData) cannot provide a diff value,
diff --git a/source/slang/slang-ir-autodiff-rev.cpp b/source/slang/slang-ir-autodiff-rev.cpp
index ed70862d1..9a69d9aa8 100644
--- a/source/slang/slang-ir-autodiff-rev.cpp
+++ b/source/slang/slang-ir-autodiff-rev.cpp
@@ -927,16 +927,16 @@ namespace Slang
{
// Create dOut param.
auto diffParam = builder->emitParam(diffType);
- copyNameHintDecoration(diffParam, fwdParam);
+ copyNameHintAndDebugDecorations(diffParam, fwdParam);
result.propagateFuncParams.add(diffParam);
primalRefReplacement = builder->emitParam(builder->getOutType(primalType));
- copyNameHintDecoration(primalRefReplacement, fwdParam);
+ copyNameHintAndDebugDecorations(primalRefReplacement, fwdParam);
// Create a local var for read access in pre-transpose code.
// This will the var from which we will fetch the final resulting derivative
// after transposition.
auto tempVar = nextBlockBuilder.emitVar(diffType);
- copyNameHintDecoration(tempVar, fwdParam);
+ copyNameHintAndDebugDecorations(tempVar, fwdParam);
result.propagateFuncSpecificPrimalInsts.add(tempVar);
// Initialize the var with input diff param at start.
@@ -953,13 +953,13 @@ namespace Slang
else
{
primalRefReplacement = builder->emitParam(outType);
- copyNameHintDecoration(primalRefReplacement, fwdParam);
+ copyNameHintAndDebugDecorations(primalRefReplacement, fwdParam);
}
result.primalFuncParams.add(primalRefReplacement);
// Create a local var for the out param for the primal part of the prop func.
auto tempPrimalVar = nextBlockBuilder.emitVar(outType->getValueType());
- copyNameHintDecoration(tempPrimalVar, fwdParam);
+ copyNameHintAndDebugDecorations(tempPrimalVar, fwdParam);
result.mapPrimalSpecificParamToReplacementInPropFunc[primalRefReplacement] = tempPrimalVar;
instsToRemove.add(fwdParam);
@@ -979,12 +979,12 @@ namespace Slang
// Create an in param for the prop func.
auto propParam = builder->emitParam(inoutType->getValueType());
- copyNameHintDecoration(propParam, fwdParam);
+ copyNameHintAndDebugDecorations(propParam, fwdParam);
result.propagateFuncParams.add(propParam);
// Create a local var for the out param for the primal part of the prop func.
auto tempPrimalVar = nextBlockBuilder.emitVar(inoutType->getValueType());
- copyNameHintDecoration(tempPrimalVar, fwdParam);
+ copyNameHintAndDebugDecorations(tempPrimalVar, fwdParam);
result.propagateFuncSpecificPrimalInsts.add(tempPrimalVar);
auto storeInst = nextBlockBuilder.emitStore(tempPrimalVar, propParam);
@@ -1013,11 +1013,11 @@ namespace Slang
// Create inout version.
auto inoutDiffPairType = builder->getInOutType(diffPairType);
primalRefReplacement = builder->emitParam(primalType);
- copyNameHintDecoration(primalRefReplacement, fwdParam);
+ copyNameHintAndDebugDecorations(primalRefReplacement, fwdParam);
result.primalFuncParams.add(primalRefReplacement);
auto propParam = builder->emitParam(inoutDiffPairType);
- copyNameHintDecoration(propParam, fwdParam);
+ copyNameHintAndDebugDecorations(propParam, fwdParam);
result.propagateFuncParams.add(propParam);
// A reference to this parameter from the diff blocks should be replaced with a load
@@ -1049,11 +1049,11 @@ namespace Slang
// Process differentiable inout parameters.
auto primalParam = builder->emitParam(builder->getInOutType(primalType));
- copyNameHintDecoration(primalParam, fwdParam);
+ copyNameHintAndDebugDecorations(primalParam, fwdParam);
result.primalFuncParams.add(primalParam);
auto diffParam = builder->emitParam(inoutType);
- copyNameHintDecoration(diffParam, fwdParam);
+ copyNameHintAndDebugDecorations(diffParam, fwdParam);
result.propagateFuncParams.add(diffParam);
// Primal references to this param is the new primal param.
@@ -1071,7 +1071,7 @@ namespace Slang
// Create a local var for diff read access.
auto diffVar = nextBlockBuilder.emitVar(diffType);
- copyNameHintDecoration(diffVar, fwdParam);
+ copyNameHintAndDebugDecorations(diffVar, fwdParam);
result.propagateFuncSpecificPrimalInsts.add(diffVar);
diffRefReplacement = diffVar;
@@ -1084,7 +1084,7 @@ namespace Slang
// Create a local var for diff write access.
auto diffWriteVar = nextBlockBuilder.emitVar(diffType);
result.propagateFuncSpecificPrimalInsts.add(diffWriteVar);
- copyNameHintDecoration(diffWriteVar, fwdParam);
+ copyNameHintAndDebugDecorations(diffWriteVar, fwdParam);
// Initialize write var to 0.
auto writeStore = nextBlockBuilder.emitStore(diffWriteVar, initDiff);
@@ -1094,7 +1094,7 @@ namespace Slang
// Create a local var for the primal logic in the propagate func.
auto primalVar = nextBlockBuilder.emitVar(primalType);
- copyNameHintDecoration(primalVar, fwdParam);
+ copyNameHintAndDebugDecorations(primalVar, fwdParam);
result.propagateFuncSpecificPrimalInsts.add(primalVar);
auto initPrimalVal = nextBlockBuilder.emitDifferentialPairGetPrimal(loadedParam);
diff --git a/source/slang/slang-ir-insert-debug-value-store.cpp b/source/slang/slang-ir-insert-debug-value-store.cpp
new file mode 100644
index 000000000..2fec61f55
--- /dev/null
+++ b/source/slang/slang-ir-insert-debug-value-store.cpp
@@ -0,0 +1,116 @@
+#include "slang-ir-insert-debug-value-store.h"
+
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
+
+namespace Slang
+{
+ void insertDebugValueStore(IRFunc* func)
+ {
+ IRBuilder builder(func);
+ Dictionary<IRInst*, IRInst*> mapVarToDebugVar;
+ auto firstBlock = func->getFirstBlock();
+ if (!firstBlock)
+ return;
+ auto funcDebugLoc = func->findDecoration<IRDebugLocationDecoration>();
+
+ List<IRInst*> params;
+ for (auto param : firstBlock->getParams())
+ {
+ params.add(param);
+ }
+
+ for (auto param : params)
+ {
+ builder.setInsertBefore(firstBlock->getFirstOrdinaryInst());
+ auto paramType = param->getDataType();
+ bool isRefParam = false;
+ if (auto outType = as<IROutTypeBase>(paramType))
+ {
+ isRefParam = true;
+ paramType = outType->getValueType();
+ }
+ auto debugVar = builder.emitDebugVar(
+ paramType,
+ funcDebugLoc->getSource(),
+ funcDebugLoc->getLine(),
+ funcDebugLoc->getCol());
+ copyNameHintAndDebugDecorations(debugVar, param);
+
+ mapVarToDebugVar[param] = debugVar;
+
+ // Store the initial value of the parameter into the debug var.
+ IRInst* paramVal = nullptr;
+ if (!isRefParam)
+ paramVal = param;
+ else if (as<IRInOutType>(param->getDataType()))
+ paramVal = builder.emitLoad(param);
+ if (paramVal)
+ {
+ ArrayView<IRInst*> accessChain;
+ builder.emitDebugValue(debugVar, paramVal, accessChain);
+ }
+ }
+
+ for (auto block : func->getBlocks())
+ {
+ IRInst* nextInst = nullptr;
+ for (auto inst = block->getFirstInst(); inst; inst = nextInst)
+ {
+ nextInst = inst->getNextInst();
+ if (auto varInst = as<IRVar>(inst))
+ {
+ if (auto debugLoc = varInst->findDecoration<IRDebugLocationDecoration>())
+ {
+ builder.setInsertBefore(varInst);
+ auto debugVar = builder.emitDebugVar(
+ tryGetPointedToType(&builder, varInst->getDataType()),
+ debugLoc->getSource(),
+ debugLoc->getLine(),
+ debugLoc->getCol());
+ copyNameHintAndDebugDecorations(debugVar, varInst);
+ mapVarToDebugVar[varInst] = debugVar;
+ }
+ }
+ }
+ }
+
+ // Collect all stores and insert debug value insts to update debug vars.
+ for (auto block : func->getBlocks())
+ {
+ for (auto inst = block->getFirstInst(); inst; inst = inst->getNextInst())
+ {
+ if (auto storeInst = as<IRStore>(inst))
+ {
+ List<IRInst*> accessChain;
+ auto varInst = getRootAddr(storeInst->getPtr(), accessChain);
+ IRInst* debugVar = nullptr;
+ if (mapVarToDebugVar.tryGetValue(varInst, debugVar))
+ {
+ builder.setInsertBefore(storeInst);
+ builder.emitDebugValue(debugVar, storeInst->getVal(), accessChain.getArrayView());
+ }
+ }
+ }
+ }
+ }
+
+ void insertDebugValueStore(IRModule* module)
+ {
+ for (auto globalInst : module->getGlobalInsts())
+ {
+ if (auto genericInst = as<IRGeneric>(globalInst))
+ {
+ if (auto func = as<IRFunc>(findGenericReturnVal(genericInst)))
+ {
+ insertDebugValueStore(func);
+ }
+ }
+ else if (auto func = as<IRFunc>(globalInst))
+ {
+ insertDebugValueStore(func);
+ }
+ }
+ }
+}
diff --git a/source/slang/slang-ir-insert-debug-value-store.h b/source/slang/slang-ir-insert-debug-value-store.h
new file mode 100644
index 000000000..ec51bba2b
--- /dev/null
+++ b/source/slang/slang-ir-insert-debug-value-store.h
@@ -0,0 +1,10 @@
+#ifndef SLANG_IR_INSERT_DEBUG_VALUE_STORE_H
+#define SLANG_IR_INSERT_DEBUG_VALUE_STORE_H
+
+namespace Slang
+{
+ struct IRModule;
+ void insertDebugValueStore(IRModule* module);
+}
+
+#endif // SLANG_IR_INSERT_DEBUG_VALUE_STORE_H
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index cb89b265b..5439a8d5b 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -964,10 +964,12 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
/// Recognized by SPIRV-emit pass so we can emit a SPIRV `BufferBlock` decoration.
INST(SPIRVBufferBlockDecoration, spvBufferBlock, 0, 0)
+ /// Decorates an inst with a debug source location (IRDebugSource, IRIntLit(line), IRIntLit(col)).
+ INST(DebugLocationDecoration, DebugLocation, 3, 0)
+
/// Recognized by SPIRV-emit pass so we can emit a SPIRV `Block` decoration.
INST(SPIRVBlockDecoration, spvBlock, 0, 0)
-
INST_RANGE(Decoration, HighLevelDeclDecoration, SPIRVBlockDecoration)
//
@@ -1111,6 +1113,8 @@ INST(DifferentiableTypeDictionaryItem, DifferentiableTypeDictionaryItem, 0, 0)
/* DebugInfo */
INST(DebugSource, DebugSource, 2, HOISTABLE)
INST(DebugLine, DebugLine, 5, 0)
+INST(DebugVar, DebugVar, 4, 0)
+INST(DebugValue, DebugValue, 2, 0)
/* Inline assembly */
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index f1160c9a6..114250bae 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -3006,6 +3006,32 @@ struct IRDebugLine : IRInst
IRInst* getColEnd() { return getOperand(4); }
};
+struct IRDebugVar : IRInst
+{
+ IR_LEAF_ISA(DebugVar)
+ IRInst* getSource() { return getOperand(0); }
+ IRInst* getLine() { return getOperand(1); }
+ IRInst* getCol() { return getOperand(2); }
+};
+
+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
+{
+ IRInst* getSource() { return getOperand(0); }
+ IRInst* getLine() { return getOperand(1); }
+ IRInst* getCol() { return getOperand(2); }
+
+ IR_LEAF_ISA(DebugLocationDecoration)
+};
+
struct IRSPIRVAsm;
struct IRSPIRVAsmOperand : IRInst
@@ -3441,6 +3467,8 @@ 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* emitDebugValue(IRInst* debugVar, IRInst* debugValue, ArrayView<IRInst*> accessChain);
/// Emit an LiveRangeStart instruction indicating the referenced item is live following this instruction
IRLiveRangeStart* emitLiveRangeStart(IRInst* referenced);
@@ -4367,6 +4395,11 @@ public:
addDecoration(value, kIROp_ExternCDecoration);
}
+ void addDebugLocationDecoration(IRInst* value, IRInst* debugSource, IRIntegerValue line, IRIntegerValue col)
+ {
+ addDecoration(value, kIROp_DebugLocationDecoration, debugSource, getIntValue(getUIntType(), line), getIntValue(getUIntType(), col));
+ }
+
void addForceInlineDecoration(IRInst* value)
{
addDecoration(value, kIROp_ForceInlineDecoration);
diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp
index 6c5ab1223..93715bc36 100644
--- a/source/slang/slang-ir-legalize-types.cpp
+++ b/source/slang/slang-ir-legalize-types.cpp
@@ -814,6 +814,87 @@ static LegalVal legalizeLoad(
}
}
+static LegalVal legalizeDebugVar(IRTypeLegalizationContext* context, LegalType type, IRDebugVar* originalInst)
+{
+ // For now we just discard any special part and keep the ordinary part.
+
+ switch (type.flavor)
+ {
+ case LegalType::Flavor::simple:
+ {
+ auto legalVal = context->builder->emitDebugVar(
+ type.getSimple(),
+ originalInst->getSource(),
+ originalInst->getLine(),
+ originalInst->getCol());
+ copyNameHintAndDebugDecorations(legalVal, originalInst);
+ return LegalVal::simple(legalVal);
+ }
+ case LegalType::Flavor::none:
+ return LegalVal();
+ case LegalType::Flavor::pair:
+ {
+ auto pairType = type.getPair();
+ auto ordinaryVal = legalizeDebugVar(context, pairType->ordinaryType, originalInst);
+ return ordinaryVal;
+ }
+ case LegalType::Flavor::tuple:
+ {
+ auto tupleType = type.getTuple();
+ for (auto ee : tupleType->elements)
+ {
+ auto innerResult = legalizeDebugVar(context, ee.type, originalInst);
+ if (innerResult.flavor != LegalVal::Flavor::none)
+ return innerResult;
+ }
+ return LegalVal();
+ }
+ default:
+ return LegalVal();
+ }
+}
+
+static LegalVal legalizeDebugValue(IRTypeLegalizationContext* context, LegalVal debugVar, LegalVal debugValue, IRDebugValue* originalInst)
+{
+ // For now we just discard any special part and keep the ordinary part.
+ List<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()));
+ case LegalType::Flavor::none:
+ return LegalVal();
+ case LegalType::Flavor::pair:
+ {
+ auto ordinaryVal = legalizeDebugValue(context, debugVar, debugValue.getPair()->ordinaryVal, originalInst);
+ return ordinaryVal;
+ }
+ case LegalType::Flavor::tuple:
+ {
+ auto tupleVar = debugVar.getTuple();
+ UInt index = 0;
+ for (auto ee : tupleVar->elements)
+ {
+ auto innerResult = legalizeDebugValue(context, debugVar, debugValue.getTuple()->elements[index].val, originalInst);
+ if (innerResult.flavor != LegalVal::Flavor::none)
+ return innerResult;
+ index++;
+ }
+ return LegalVal();
+ }
+ default:
+ return LegalVal();
+ }
+}
+
static LegalVal legalizeStore(
IRTypeLegalizationContext* context,
LegalVal legalPtrVal,
@@ -1921,6 +2002,12 @@ static LegalVal legalizeInst(
return legalizeCall(context, (IRCall*)inst);
case kIROp_Return:
return legalizeRetVal(context, args[0], (IRReturn*)inst);
+
+ case kIROp_DebugVar:
+ return legalizeDebugVar(context, type, (IRDebugVar*)inst);
+ case kIROp_DebugValue:
+ return legalizeDebugValue(context, args[0], args[1], (IRDebugValue*)inst);
+
case kIROp_MakeStruct:
return legalizeMakeStruct(
context,
@@ -1939,6 +2026,7 @@ static LegalVal legalizeInst(
return legalizeDefaultConstruct(
context,
type);
+
case kIROp_unconditionalBranch:
case kIROp_loop:
return legalizeUnconditionalBranch(context, args, (IRUnconditionalBranch*)inst);
diff --git a/source/slang/slang-ir-spirv-legalize.h b/source/slang/slang-ir-spirv-legalize.h
index 1064e5aa0..431c9627d 100644
--- a/source/slang/slang-ir-spirv-legalize.h
+++ b/source/slang/slang-ir-spirv-legalize.h
@@ -24,13 +24,19 @@ struct SPIRVEmitSharedContext
DiagnosticSink* m_sink;
const SPIRVCoreGrammarInfo* m_grammarInfo;
+ IRInst* m_voidType;
+
SPIRVEmitSharedContext(IRModule* module, TargetProgram* program, DiagnosticSink* sink)
: m_irModule(module),
m_targetProgram(program),
m_targetRequest(program->getTargetReq()),
m_sink(sink),
m_grammarInfo(&module->getSession()->getSPIRVCoreGrammarInfo())
- {}
+ {
+ IRBuilder builder(module);
+ builder.setInsertInto(module);
+ m_voidType = builder.getVoidType();
+ }
SpvSnippet* getParsedSpvSnippet(IRTargetIntrinsicDecoration* intrinsic);
};
diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp
index f514fea1d..8b39e8b45 100644
--- a/source/slang/slang-ir-util.cpp
+++ b/source/slang/slang-ir-util.cpp
@@ -266,12 +266,38 @@ String dumpIRToString(IRInst* root, IRDumpOptions options)
return sb.toString();
}
-void copyNameHintDecoration(IRInst* dest, IRInst* src)
+void copyNameHintAndDebugDecorations(IRInst* dest, IRInst* src)
{
- auto decor = src->findDecoration<IRNameHintDecoration>();
- if (decor)
+ IRDecoration* nameHintDecoration = nullptr;
+ IRDecoration* linkageDecoration = nullptr;
+ IRDecoration* debugLocationDecoration = nullptr;
+ for (auto decor = src->getFirstDecoration(); decor; decor = decor->getNextDecoration())
{
- cloneDecoration(decor, dest);
+ switch (decor->getOp())
+ {
+ case kIROp_NameHintDecoration:
+ nameHintDecoration = decor;
+ break;
+ case kIROp_ImportDecoration:
+ case kIROp_ExportDecoration:
+ linkageDecoration = decor;
+ break;
+ case kIROp_DebugLocationDecoration:
+ debugLocationDecoration = decor;
+ break;
+ }
+ }
+ if (nameHintDecoration)
+ {
+ cloneDecoration(nameHintDecoration, dest);
+ }
+ if (linkageDecoration)
+ {
+ cloneDecoration(linkageDecoration, dest);
+ }
+ if (debugLocationDecoration)
+ {
+ cloneDecoration(debugLocationDecoration, dest);
}
}
@@ -557,6 +583,26 @@ IRInst* getRootAddr(IRInst* addr)
return addr;
}
+IRInst* getRootAddr(IRInst* addr, List<IRInst*>& outAccessChain)
+{
+ for (;;)
+ {
+ switch (addr->getOp())
+ {
+ case kIROp_GetElementPtr:
+ case kIROp_FieldAddress:
+ outAccessChain.add(addr->getOperand(1));
+ addr = addr->getOperand(0);
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ outAccessChain.reverse();
+ return addr;
+}
+
// A simple and conservative address aliasing check.
bool canAddressesPotentiallyAlias(IRGlobalValueWithCode* func, IRInst* addr1, IRInst* addr2)
{
diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h
index c290f9392..648ba3531 100644
--- a/source/slang/slang-ir-util.h
+++ b/source/slang/slang-ir-util.h
@@ -167,8 +167,10 @@ inline IRInst* unwrapAttributedType(IRInst* type)
IRType* dropNormAttributes(IRType* const t);
void getTypeNameHint(StringBuilder& sb, IRInst* type);
-void copyNameHintDecoration(IRInst* dest, IRInst* src);
+void copyNameHintAndDebugDecorations(IRInst* dest, IRInst* src);
IRInst* getRootAddr(IRInst* addrInst);
+IRInst* getRootAddr(IRInst* addrInst, List<IRInst*>& outAccessChain);
+
bool canAddressesPotentiallyAlias(IRGlobalValueWithCode* func, IRInst* addr1, IRInst* addr2);
String dumpIRToString(
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index a016679e7..3f10e3d3e 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -3214,13 +3214,28 @@ namespace Slang
IRInst* args[] =
{
source,
- getIntValue(getIntType(), lineStart),
- getIntValue(getIntType(), lineEnd),
- getIntValue(getIntType(), colStart),
- getIntValue(getIntType(), colEnd)
+ getIntValue(getUIntType(), lineStart),
+ getIntValue(getUIntType(), lineEnd),
+ getIntValue(getUIntType(), colStart),
+ getIntValue(getUIntType(), colEnd)
};
return emitIntrinsicInst(getVoidType(), kIROp_DebugLine, 5, args);
}
+ IRInst* IRBuilder::emitDebugVar(IRType* type, IRInst* source, IRInst* line, IRInst* col)
+ {
+ IRInst* args[] = { source, line, col };
+ return emitIntrinsicInst(type, kIROp_DebugVar, 3, args);
+ }
+
+ IRInst* IRBuilder::emitDebugValue(IRInst* debugVar, IRInst* debugValue, ArrayView<IRInst*> accessChain)
+ {
+ List<IRInst*> args;
+ args.add(debugVar);
+ args.add(debugValue);
+ args.addRange(accessChain);
+ return emitIntrinsicInst(getVoidType(), kIROp_DebugValue, (UInt)args.getCount(), args.getBuffer());
+ }
+
IRLiveRangeStart* IRBuilder::emitLiveRangeStart(IRInst* referenced)
{
// This instruction doesn't produce any result,
@@ -8242,28 +8257,7 @@ namespace Slang
bool isDefinition(
IRInst* inVal)
{
- IRInst* val = inVal;
- // unwrap any generic declarations to see
- // the value they return.
- for(;;)
- {
- // An instruciton marked `[import(...)]` cannot
- // be a definition, since it is claiming that
- // the actual body comes from another module.
- //
- if(val->findDecoration<IRImportDecoration>())
- return false;
-
- auto genericInst = as<IRGeneric>(val);
- if(!genericInst)
- break;
-
- auto returnVal = findGenericReturnVal(genericInst);
- if(!returnVal)
- break;
-
- val = returnVal;
- }
+ IRInst* val = getResolvedInstForDecorations(inVal);
// Some cases of instructions have structural
// rules about when they are considered to have
@@ -8272,7 +8266,6 @@ namespace Slang
switch (val->getOp())
{
case kIROp_Func:
- case kIROp_Generic:
return val->getFirstChild() != nullptr;
case kIROp_GlobalConstant:
@@ -8285,7 +8278,6 @@ namespace Slang
// In all other cases, if we have an instruciton
// that has *not* been marked for import, then
// we consider it to be a definition.
-
return true;
}
diff --git a/source/slang/slang-legalize-types.cpp b/source/slang/slang-legalize-types.cpp
index 8ed5a12b7..c8a840ce9 100644
--- a/source/slang/slang-legalize-types.cpp
+++ b/source/slang/slang-legalize-types.cpp
@@ -2,6 +2,7 @@
#include "slang-legalize-types.h"
#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
#include "slang-mangle.h"
namespace Slang
@@ -447,11 +448,7 @@ struct TupleTypeBuilder
IRBuilder* builder = context->getBuilder();
IRStructType* ordinaryStructType = builder->createStructType();
ordinaryStructType->sourceLoc = originalStructType->sourceLoc;
-
- if(auto nameHintDecoration = originalStructType->findDecoration<IRNameHintDecoration>())
- {
- builder->addNameHintDecoration(ordinaryStructType, nameHintDecoration->getNameOperand());
- }
+ copyNameHintAndDebugDecorations(ordinaryStructType, originalStructType);
// The new struct type will appear right after the original in the IR,
// so that we can be sure any instruction that could reference the
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 8b9a3c377..cb9c8fc40 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -17,6 +17,7 @@
#include "slang-ir-autodiff.h"
#include "slang-ir-inline.h"
#include "slang-ir-insts.h"
+#include "slang-ir-insert-debug-value-store.h"
#include "slang-ir-check-differentiability.h"
#include "slang-ir-missing-return.h"
#include "slang-ir-sccp.h"
@@ -6298,6 +6299,22 @@ void maybeEmitDebugLine(IRGenContext* context, Stmt* stmt)
}
}
+void maybeAddDebugLocationDecoration(IRGenContext* context, IRInst* inst)
+{
+ if (!context->includeDebugInfo)
+ return;
+ auto sourceView = context->getLinkage()->getSourceManager()->findSourceView(inst->sourceLoc);
+ if (!sourceView)
+ return;
+ auto source = sourceView->getSourceFile();
+ IRInst* debugSourceInst = nullptr;
+ if (context->shared->mapSourceFileToDebugSourceInst.tryGetValue(source, debugSourceInst))
+ {
+ auto humaneLoc = context->getLinkage()->getSourceManager()->getHumaneLoc(inst->sourceLoc, SourceLocType::Emit);
+ context->irBuilder->addDebugLocationDecoration(inst, debugSourceInst, humaneLoc.line, humaneLoc.column);
+ }
+}
+
void lowerStmt(
IRGenContext* context,
Stmt* stmt)
@@ -7777,6 +7794,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
LoweredValInfo varVal = createVar(context, varType, decl);
+ maybeAddDebugLocationDecoration(context, varVal.val);
if( auto initExpr = decl->initExpr )
{
@@ -8150,6 +8168,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
getSink()->diagnose(decl->loc, Diagnostics::unimplemented, "lower unknown AggType to IR");
return LoweredValInfo::simple(subBuilder->getVoidType());
}
+
+ maybeAddDebugLocationDecoration(context, irAggType);
auto finalFinishedVal = finishOuterGenerics(subBuilder, irAggType, outerGeneric);
@@ -9043,7 +9063,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
IRFunc* irFunc = subBuilder->createFunc();
addNameHint(subContext, irFunc, decl);
addLinkageDecoration(subContext, irFunc, decl);
-
+ maybeAddDebugLocationDecoration(subContext, irFunc);
+
// Register the value now, to avoid any possible infinite recursion when lowering the body or attributes.
context->setGlobalValue(decl, LoweredValInfo::simple(findOuterMostGeneric(irFunc)));
@@ -10339,6 +10360,13 @@ RefPtr<IRModule> generateIRForTranslationUnit(
// normal `call` + `ifElse`, etc.
lowerErrorHandling(module, compileRequest->getSink());
+ // Generate DebugValue insts to store values into debug variables,
+ // if debug symbols are enabled.
+ if (compileRequest->getLinkage()->m_optionSet.getEnumOption<DebugInfoLevel>(CompilerOptionName::DebugInformation) != DebugInfoLevel::None)
+ {
+ insertDebugValueStore(module);
+ }
+
// Next, attempt to promote local variables to SSA
// temporaries and do basic simplifications.
//
@@ -10516,11 +10544,12 @@ struct SpecializedComponentTypeIRGenContext : ComponentTypeVisitor
linkage = componentType->getLinkage();
session = linkage->getSessionImpl();
-
+ auto option = linkage->m_optionSet;
+ option.overrideWith(componentType->getOptionSet());
SharedIRGenContext sharedContextStorage(
session,
sink,
- linkage->m_optionSet.shouldObfuscateCode(),
+ option.shouldObfuscateCode(),
nullptr,
linkage
);
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 9a653aded..4b11a5216 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -4728,6 +4728,8 @@ SpecializedComponentType::SpecializedComponentType(
, m_specializationInfo(specializationInfo)
, m_specializationArgs(specializationArgs)
{
+ m_optionSet.overrideWith(base->getOptionSet());
+
m_irModule = generateIRForSpecializedComponentType(this, sink);
// We need to account for the fact that a specialized