diff options
| author | Copilot <198982749+Copilot@users.noreply.github.com> | 2025-07-18 11:24:06 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-18 18:24:06 +0000 |
| commit | 70273599e2bb8a8e2b0f7b5e7ad47fe2f00b2b40 (patch) | |
| tree | 29d18f4b20c00bfbe684978d35d02da77713a4ae /source | |
| parent | c901338e3b443be4c72308f4f473892404b73268 (diff) | |
Fix debug info generation for let variables in SPIR-V output (#7743)
* Initial plan
* Fix debug info for let variables
Co-authored-by: csyonghe <2652293+csyonghe@users.noreply.github.com>
* Fix parameter count for emitDebugVar function call
Fixed regression where let variable debug info generation was missing the optional argIndex parameter in emitDebugVar call.
Co-authored-by: csyonghe <2652293+csyonghe@users.noreply.github.com>
* Add location validity check for debug info generation
Co-authored-by: csyonghe <2652293+csyonghe@users.noreply.github.com>
* Don't insert debug value for nondebuggable types.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: csyonghe <2652293+csyonghe@users.noreply.github.com>
Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-ir-insert-debug-value-store.cpp | 353 | ||||
| -rw-r--r-- | source/slang/slang-ir-insert-debug-value-store.h | 16 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 43 |
3 files changed, 231 insertions, 181 deletions
diff --git a/source/slang/slang-ir-insert-debug-value-store.cpp b/source/slang/slang-ir-insert-debug-value-store.cpp index b5486e891..86ad377a2 100644 --- a/source/slang/slang-ir-insert-debug-value-store.cpp +++ b/source/slang/slang-ir-insert-debug-value-store.cpp @@ -6,236 +6,231 @@ namespace Slang { -struct DebugValueStoreContext +bool DebugValueStoreContext::isTypeKind(IRInst* inst) { - Dictionary<IRType*, bool> m_mapTypeToDebugability; - bool isTypeKind(IRInst* inst) + if (!inst) + return true; + switch (inst->getOp()) { - if (!inst) - return true; - switch (inst->getOp()) - { - case kIROp_TypeKind: - case kIROp_TypeType: - return true; - default: - return false; - } + case kIROp_TypeKind: + case kIROp_TypeType: + return true; + default: + return false; } - bool isDebuggableType(IRType* type) - { - if (bool* result = m_mapTypeToDebugability.tryGetValue(type)) - return *result; +} +bool DebugValueStoreContext::isDebuggableType(IRType* type) +{ + if (bool* result = m_mapTypeToDebugability.tryGetValue(type)) + return *result; - bool debuggable = false; - switch (type->getOp()) + bool debuggable = false; + switch (type->getOp()) + { + case kIROp_VoidType: + break; + case kIROp_StructType: { - case kIROp_VoidType: - break; - case kIROp_StructType: + auto structType = static_cast<IRStructType*>(type); + bool structDebuggable = true; + for (auto field : structType->getFields()) { - auto structType = static_cast<IRStructType*>(type); - bool structDebuggable = true; - for (auto field : structType->getFields()) + if (!isDebuggableType(field->getFieldType())) { - if (!isDebuggableType(field->getFieldType())) - { - structDebuggable = false; - break; - } + structDebuggable = false; + break; } - debuggable = structDebuggable; - break; - } - case kIROp_ArrayType: - case kIROp_UnsizedArrayType: - { - auto arrayType = static_cast<IRArrayTypeBase*>(type); - debuggable = isDebuggableType(arrayType->getElementType()); - break; } - case kIROp_VectorType: - case kIROp_MatrixType: - case kIROp_PtrType: - debuggable = true; + debuggable = structDebuggable; break; - case kIROp_Param: - // Assume generic parameters are debuggable. - debuggable = true; + } + case kIROp_ArrayType: + case kIROp_UnsizedArrayType: + { + auto arrayType = static_cast<IRArrayTypeBase*>(type); + debuggable = isDebuggableType(arrayType->getElementType()); break; - case kIROp_Specialize: + } + case kIROp_VectorType: + case kIROp_MatrixType: + case kIROp_PtrType: + debuggable = true; + break; + case kIROp_Param: + // Assume generic parameters are debuggable. + debuggable = true; + break; + case kIROp_Specialize: + { + auto specType = as<IRSpecialize>(type); + auto specTypeDebuggable = + isDebuggableType((IRType*)getResolvedInstForDecorations(specType)); + if (!specTypeDebuggable) + break; + for (UInt i = 0; i < specType->getArgCount(); i++) { - auto specType = as<IRSpecialize>(type); - auto specTypeDebuggable = - isDebuggableType((IRType*)getResolvedInstForDecorations(specType)); - if (!specTypeDebuggable) - break; - for (UInt i = 0; i < specType->getArgCount(); i++) + auto arg = specType->getArg(i); + if (isTypeKind(arg->getDataType()) && + !isDebuggableType((IRType*)specType->getArg(i))) { - auto arg = specType->getArg(i); - if (isTypeKind(arg->getDataType()) && - !isDebuggableType((IRType*)specType->getArg(i))) - { - specTypeDebuggable = false; - break; - } + specTypeDebuggable = false; + break; } - debuggable = false; // specTypeDebuggable; - break; } - default: - if (as<IRBasicType>(type)) - debuggable = true; + debuggable = false; // specTypeDebuggable; break; } - m_mapTypeToDebugability[type] = debuggable; - return debuggable; + default: + if (as<IRBasicType>(type)) + debuggable = true; + break; } + m_mapTypeToDebugability[type] = debuggable; + return debuggable; +} - void insertDebugValueStore(IRFunc* func) +void DebugValueStoreContext::insertDebugValueStore(IRFunc* func) +{ + IRBuilder builder(func); + Dictionary<IRInst*, IRInst*> mapVarToDebugVar; + auto firstBlock = func->getFirstBlock(); + if (!firstBlock) + return; + auto funcDebugLoc = func->findDecoration<IRDebugLocationDecoration>(); + if (!funcDebugLoc) + return; + List<IRInst*> params; + for (auto param : firstBlock->getParams()) { - IRBuilder builder(func); - Dictionary<IRInst*, IRInst*> mapVarToDebugVar; - auto firstBlock = func->getFirstBlock(); - if (!firstBlock) - return; - auto funcDebugLoc = func->findDecoration<IRDebugLocationDecoration>(); - if (!funcDebugLoc) - return; - List<IRInst*> params; - for (auto param : firstBlock->getParams()) + params.add(param); + } + Index paramIndex = 0; + for (auto param : params) + { + builder.setInsertBefore(firstBlock->getFirstOrdinaryInst()); + auto paramType = param->getDataType(); + bool isRefParam = false; + if (auto outType = as<IROutTypeBase>(paramType)) { - params.add(param); + isRefParam = true; + paramType = outType->getValueType(); } - Index paramIndex = 0; - 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(); - } - if (!isDebuggableType(paramType)) - continue; - auto debugVar = builder.emitDebugVar( - paramType, - funcDebugLoc->getSource(), - funcDebugLoc->getLine(), - funcDebugLoc->getCol(), - builder.getIntValue(builder.getUIntType(), paramIndex)); - copyNameHintAndDebugDecorations(debugVar, param); + if (!isDebuggableType(paramType)) + continue; + auto debugVar = builder.emitDebugVar( + paramType, + funcDebugLoc->getSource(), + funcDebugLoc->getLine(), + funcDebugLoc->getCol(), + builder.getIntValue(builder.getUIntType(), paramIndex)); + copyNameHintAndDebugDecorations(debugVar, param); - mapVarToDebugVar[param] = debugVar; + 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) - { - builder.emitDebugValue(debugVar, paramVal); - } - paramIndex++; + // 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) + { + builder.emitDebugValue(debugVar, paramVal); } + paramIndex++; + } - for (auto block : func->getBlocks()) + for (auto block : func->getBlocks()) + { + IRInst* nextInst = nullptr; + for (auto inst = block->getFirstInst(); inst; inst = nextInst) { - IRInst* nextInst = nullptr; - for (auto inst = block->getFirstInst(); inst; inst = nextInst) + nextInst = inst->getNextInst(); + if (auto varInst = as<IRVar>(inst)) { - nextInst = inst->getNextInst(); - if (auto varInst = as<IRVar>(inst)) + if (auto debugLoc = varInst->findDecoration<IRDebugLocationDecoration>()) { - if (auto debugLoc = varInst->findDecoration<IRDebugLocationDecoration>()) - { - auto varType = tryGetPointedToType(&builder, varInst->getDataType()); - builder.setInsertBefore(varInst); - if (!isDebuggableType(varType)) - continue; - auto debugVar = builder.emitDebugVar( - varType, - debugLoc->getSource(), - debugLoc->getLine(), - debugLoc->getCol()); - copyNameHintAndDebugDecorations(debugVar, varInst); - mapVarToDebugVar[varInst] = debugVar; - } + auto varType = tryGetPointedToType(&builder, varInst->getDataType()); + builder.setInsertBefore(varInst); + if (!isDebuggableType(varType)) + continue; + auto debugVar = builder.emitDebugVar( + varType, + debugLoc->getSource(), + debugLoc->getLine(), + debugLoc->getCol()); + copyNameHintAndDebugDecorations(debugVar, varInst); + mapVarToDebugVar[varInst] = debugVar; } } } + } - // Collect all stores and insert debug value insts to update debug vars. + // Collect all stores and insert debug value insts to update debug vars. - // Helper func to insert debugValue updates. - auto setDebugValue = [&](IRInst* debugVar, IRInst* newValue, ArrayView<IRInst*> accessChain) - { - auto ptr = builder.emitElementAddress(debugVar, accessChain); - builder.emitDebugValue(ptr, newValue); - }; - for (auto block : func->getBlocks()) + // Helper func to insert debugValue updates. + auto setDebugValue = [&](IRInst* debugVar, IRInst* newValue, ArrayView<IRInst*> accessChain) + { + auto ptr = builder.emitElementAddress(debugVar, accessChain); + builder.emitDebugValue(ptr, newValue); + }; + for (auto block : func->getBlocks()) + { + IRInst* nextInst = nullptr; + for (auto inst = block->getFirstInst(); inst; inst = nextInst) { - IRInst* nextInst = nullptr; - for (auto inst = block->getFirstInst(); inst; inst = nextInst) - { - nextInst = inst->getNextInst(); + nextInst = inst->getNextInst(); - if (auto storeInst = as<IRStore>(inst)) + if (auto storeInst = as<IRStore>(inst)) + { + List<IRInst*> accessChain; + auto varInst = getRootAddr(storeInst->getPtr(), accessChain); + IRInst* debugVar = nullptr; + if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) { - List<IRInst*> accessChain; - auto varInst = getRootAddr(storeInst->getPtr(), accessChain); - IRInst* debugVar = nullptr; - if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) - { - builder.setInsertAfter(storeInst); - setDebugValue(debugVar, storeInst->getVal(), accessChain.getArrayView()); - } + builder.setInsertAfter(storeInst); + setDebugValue(debugVar, storeInst->getVal(), accessChain.getArrayView()); + } + } + else if (auto swizzledStore = as<IRSwizzledStore>(inst)) + { + List<IRInst*> accessChain; + 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, loadVal, accessChain.getArrayView()); } - else if (auto swizzledStore = as<IRSwizzledStore>(inst)) + } + else if (auto callInst = as<IRCall>(inst)) + { + auto funcValue = getResolvedInstForDecorations(callInst->getCallee()); + if (!funcValue) + continue; + for (UInt i = 0; i < callInst->getArgCount(); i++) { + auto arg = callInst->getArg(i); + if (!as<IRPtrTypeBase>(arg->getDataType())) + continue; List<IRInst*> accessChain; - auto varInst = getRootAddr(swizzledStore->getDest(), accessChain); + auto varInst = getRootAddr(arg, accessChain); IRInst* debugVar = nullptr; if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) { - builder.setInsertAfter(swizzledStore); - auto loadVal = builder.emitLoad(swizzledStore->getDest()); + builder.setInsertAfter(callInst); + auto loadVal = builder.emitLoad(arg); setDebugValue(debugVar, loadVal, accessChain.getArrayView()); } } - else if (auto callInst = as<IRCall>(inst)) - { - auto funcValue = getResolvedInstForDecorations(callInst->getCallee()); - if (!funcValue) - continue; - for (UInt i = 0; i < callInst->getArgCount(); i++) - { - auto arg = callInst->getArg(i); - if (!as<IRPtrTypeBase>(arg->getDataType())) - continue; - List<IRInst*> accessChain; - auto varInst = getRootAddr(arg, accessChain); - IRInst* debugVar = nullptr; - if (mapVarToDebugVar.tryGetValue(varInst, debugVar)) - { - builder.setInsertAfter(callInst); - auto loadVal = builder.emitLoad(arg); - setDebugValue(debugVar, loadVal, accessChain.getArrayView()); - } - } - } } } } -}; +} -void insertDebugValueStore(IRModule* module) +void insertDebugValueStore(DebugValueStoreContext& context, IRModule* module) { - DebugValueStoreContext context; for (auto globalInst : module->getGlobalInsts()) { if (auto genericInst = as<IRGeneric>(globalInst)) diff --git a/source/slang/slang-ir-insert-debug-value-store.h b/source/slang/slang-ir-insert-debug-value-store.h index 3067c8cdd..0dc289b2e 100644 --- a/source/slang/slang-ir-insert-debug-value-store.h +++ b/source/slang/slang-ir-insert-debug-value-store.h @@ -1,10 +1,24 @@ #ifndef SLANG_IR_INSERT_DEBUG_VALUE_STORE_H #define SLANG_IR_INSERT_DEBUG_VALUE_STORE_H +#include "core/slang-basic.h" + namespace Slang { struct IRModule; -void insertDebugValueStore(IRModule* module); +struct IRType; +struct IRFunc; +struct IRInst; + +struct DebugValueStoreContext +{ + Dictionary<IRType*, bool> m_mapTypeToDebugability; + bool isDebuggableType(IRType* type); + void insertDebugValueStore(IRFunc* func); + bool isTypeKind(IRInst* inst); +}; +void insertDebugValueStore(DebugValueStoreContext& context, IRModule* module); + } // namespace Slang #endif // SLANG_IR_INSERT_DEBUG_VALUE_STORE_H diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index ab9f85b21..526e2f952 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -535,6 +535,8 @@ struct SharedIRGenContext // in the source code. // List<IRInst*> m_stringLiterals; + + DebugValueStoreContext debugValueContext; }; struct IRGenContext; @@ -9155,6 +9157,45 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> { auto initVal = lowerRValueExpr(context, initExpr); initVal = LoweredValInfo::simple(getSimpleVal(context, initVal)); + + // For debug builds, still create debug information for let variables + // even though we're not creating an actual variable + if (context->includeDebugInfo && decl->loc.isValid() && + context->shared->debugValueContext.isDebuggableType(initVal.val->getDataType())) + { + // Create a debug variable for this let declaration + auto builder = context->irBuilder; + auto humaneLoc = context->getLinkage()->getSourceManager()->getHumaneLoc( + decl->loc, + SourceLocType::Emit); + + // Find the debug source for this file + auto sourceView = + context->getLinkage()->getSourceManager()->findSourceView(decl->loc); + if (sourceView) + { + auto source = sourceView->getSourceFile(); + IRInst* debugSourceInst = nullptr; + if (context->shared->mapSourceFileToDebugSourceInst.tryGetValue( + source, + debugSourceInst)) + { + auto debugVar = builder->emitDebugVar( + varType, + debugSourceInst, + builder->getIntValue(builder->getUIntType(), humaneLoc.line), + builder->getIntValue(builder->getUIntType(), humaneLoc.column), + nullptr); + + // Copy name hint from the declaration + addNameHint(context, debugVar, decl); + + // Emit debug value to associate the constant with the debug variable + builder->emitDebugValue(debugVar, initVal.val); + } + } + } + context->setGlobalValue(decl, initVal); return initVal; } @@ -12152,7 +12193,7 @@ RefPtr<IRModule> generateIRForTranslationUnit( // if debug symbols are enabled. if (context->includeDebugInfo) { - insertDebugValueStore(module); + insertDebugValueStore(context->shared->debugValueContext, module); } |
