summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-emit-spirv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-emit-spirv.cpp')
-rw-r--r--source/slang/slang-emit-spirv.cpp341
1 files changed, 341 insertions, 0 deletions
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;