Skip to content

Commit 233f7d1

Browse files
committedJan 6, 2025
DXIL Disassembly include DebugValue, DebugDeclare parsing
1 parent ab9db02 commit 233f7d1

File tree

4 files changed

+157
-102
lines changed

4 files changed

+157
-102
lines changed
 

‎renderdoc/driver/shaders/dxil/dxil_bytecode.h

+15
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ namespace DXIL
5454
static const rdcstr DXIL_FAKE_OUTPUT_STRUCT_NAME("_OUT");
5555
static const rdcstr DXIL_FAKE_INPUT_STRUCT_NAME("_IN");
5656

57+
struct DILocalVariable;
58+
5759
enum class FunctionFamily : uint8_t
5860
{
5961
Unknown,
@@ -1580,6 +1582,16 @@ struct ResourceReference
15801582
uint32_t resourceIndex;
15811583
};
15821584

1585+
struct SourceMappingInfo
1586+
{
1587+
const DILocalVariable *localVariable;
1588+
int32_t srcByteOffset;
1589+
int32_t srcCountBytes;
1590+
DXILDebug::Id dbgVarId;
1591+
rdcstr dbgVarName;
1592+
bool isDeclare;
1593+
};
1594+
15831595
class Program : public DXBC::IDebugInfo
15841596
{
15851597
friend DXILDebug::Debugger;
@@ -1652,6 +1664,9 @@ class Program : public DXBC::IDebugInfo
16521664
rdcstr GetDebugScopeFilePath(const DIBase *d) const;
16531665
uint64_t GetDebugScopeLine(const DIBase *d) const;
16541666
const Metadata *GetDebugScopeParent(const DIBase *d) const;
1667+
SourceMappingInfo ParseDbgOpValue(const DXIL::Instruction &inst) const;
1668+
SourceMappingInfo ParseDbgOpDeclare(const DXIL::Instruction &inst) const;
1669+
rdcpair<int32_t, int32_t> ParseDIExpressionMD(const Metadata *expressionMD) const;
16551670

16561671
rdcstr GetValueSymtabString(Value *v);
16571672
void SetValueSymtabString(Value *v, const rdcstr &s);

‎renderdoc/driver/shaders/dxil/dxil_debug.cpp

+16-99
Original file line numberDiff line numberDiff line change
@@ -6674,123 +6674,40 @@ const TypeData &Debugger::AddDebugType(const DXIL::Metadata *typeMD)
66746674
return m_DebugInfo.types[typeMD];
66756675
}
66766676

6677-
void Debugger::AddLocalVariable(const DXIL::Metadata *localVariableMD, uint32_t instructionIndex,
6678-
bool isDeclare, int32_t byteOffset, uint32_t countBytes,
6679-
Id debugVarSSAId, const rdcstr &debugVarSSAName)
6677+
void Debugger::AddLocalVariable(const DXIL::SourceMappingInfo &srcMapping, uint32_t instructionIndex)
66806678
{
6681-
RDCASSERT(localVariableMD);
6682-
RDCASSERTEQUAL(localVariableMD->dwarf->type, DIBase::Type::LocalVariable);
6683-
const DILocalVariable *localVariable = localVariableMD->dwarf->As<DILocalVariable>();
6679+
ScopedDebugData *scope = AddScopedDebugData(srcMapping.localVariable->scope);
66846680

6685-
ScopedDebugData *scope = AddScopedDebugData(localVariable->scope);
6686-
6687-
rdcstr sourceVarName = m_Program->GetDebugVarName(localVariable);
66886681
LocalMapping localMapping;
6689-
localMapping.variable = localVariable;
6690-
localMapping.sourceVarName = sourceVarName;
6691-
localMapping.debugVarSSAName = debugVarSSAName;
6692-
localMapping.debugVarSSAId = debugVarSSAId;
6693-
localMapping.byteOffset = byteOffset;
6694-
localMapping.countBytes = countBytes;
6682+
localMapping.sourceVarName = m_Program->GetDebugVarName(srcMapping.localVariable);
6683+
localMapping.variable = srcMapping.localVariable;
6684+
localMapping.debugVarSSAName = srcMapping.dbgVarName;
6685+
localMapping.debugVarSSAId = srcMapping.dbgVarId;
6686+
localMapping.byteOffset = srcMapping.srcByteOffset;
6687+
localMapping.countBytes = srcMapping.srcCountBytes;
6688+
localMapping.isDeclare = srcMapping.isDeclare;
66956689
localMapping.instIndex = instructionIndex;
6696-
localMapping.isDeclare = isDeclare;
66976690

66986691
scope->localMappings.push_back(localMapping);
66996692

6700-
const DXIL::Metadata *typeMD = localVariable->type;
6693+
const DXIL::Metadata *typeMD = srcMapping.localVariable->type;
67016694
if(m_DebugInfo.types.count(typeMD) == 0)
67026695
AddDebugType(typeMD);
67036696

6704-
if(m_DebugInfo.locals.count(localVariable) == 0)
6705-
m_DebugInfo.locals[localVariable] = localMapping;
6697+
if(m_DebugInfo.locals.count(srcMapping.localVariable) == 0)
6698+
m_DebugInfo.locals[srcMapping.localVariable] = localMapping;
67066699
}
67076700

67086701
void Debugger::ParseDbgOpDeclare(const DXIL::Instruction &inst, uint32_t instructionIndex)
67096702
{
6710-
// arg 0 contains the SSA Id of the alloca result which represents the local variable (a pointer)
6711-
const Metadata *allocaInstMD = cast<Metadata>(inst.args[0]);
6712-
RDCASSERT(allocaInstMD);
6713-
const Instruction *allocaInst = cast<Instruction>(allocaInstMD->value);
6714-
RDCASSERT(allocaInst);
6715-
RDCASSERTEQUAL(allocaInst->op, Operation::Alloca);
6716-
Id resultId = Program::GetResultSSAId(*allocaInst);
6717-
rdcstr resultName;
6718-
Program::MakeResultId(*allocaInst, resultName);
6719-
int32_t byteOffset = 0;
6720-
6721-
// arg 1 is DILocalVariable metadata
6722-
const Metadata *localVariableMD = cast<Metadata>(inst.args[1]);
6723-
6724-
// arg 2 is DIExpression metadata
6725-
const Metadata *expressionMD = cast<Metadata>(inst.args[2]);
6726-
uint32_t countBytes = 0;
6727-
if(expressionMD)
6728-
{
6729-
if(expressionMD->dwarf->type == DIBase::Type::Expression)
6730-
{
6731-
const DIExpression *expression = expressionMD->dwarf->As<DXIL::DIExpression>();
6732-
switch(expression->op)
6733-
{
6734-
case DXIL::DW_OP::DW_OP_bit_piece:
6735-
byteOffset += (uint32_t)(expression->evaluated.bit_piece.offset / 8);
6736-
countBytes = (uint32_t)(expression->evaluated.bit_piece.size / 8);
6737-
break;
6738-
case DXIL::DW_OP::DW_OP_none: break;
6739-
case DXIL::DW_OP::DW_OP_nop: break;
6740-
default: RDCERR("Unhandled DIExpression op %s", ToStr(expression->op).c_str()); break;
6741-
}
6742-
}
6743-
else
6744-
{
6745-
RDCERR("Unhandled Expression Metadata %s", ToStr(expressionMD->dwarf->type).c_str());
6746-
}
6747-
}
6748-
6749-
AddLocalVariable(localVariableMD, instructionIndex, true, byteOffset, countBytes, resultId,
6750-
resultName);
6703+
DXIL::SourceMappingInfo sourceMappingInfo = m_Program->ParseDbgOpDeclare(inst);
6704+
AddLocalVariable(sourceMappingInfo, instructionIndex);
67516705
}
67526706

67536707
void Debugger::ParseDbgOpValue(const DXIL::Instruction &inst, uint32_t instructionIndex)
67546708
{
6755-
// arg 0 is metadata containing the new value
6756-
const Metadata *valueMD = cast<Metadata>(inst.args[0]);
6757-
Id resultId = GetSSAId(valueMD->value);
6758-
rdcstr resultName = m_Program->GetArgumentName(valueMD->value);
6759-
// arg 1 is i64 byte offset in the source variable where the new value is written
6760-
int64_t value = 0;
6761-
RDCASSERT(getival<int64_t>(inst.args[1], value));
6762-
int32_t byteOffset = (int32_t)(value);
6763-
6764-
// arg 2 is DILocalVariable metadata
6765-
const Metadata *localVariableMD = cast<Metadata>(inst.args[2]);
6766-
6767-
// arg 3 is DIExpression metadata
6768-
uint32_t countBytes = 0;
6769-
const Metadata *expressionMD = cast<Metadata>(inst.args[3]);
6770-
if(expressionMD)
6771-
{
6772-
if(expressionMD->dwarf->type == DIBase::Type::Expression)
6773-
{
6774-
const DIExpression *expression = expressionMD->dwarf->As<DXIL::DIExpression>();
6775-
switch(expression->op)
6776-
{
6777-
case DXIL::DW_OP::DW_OP_bit_piece:
6778-
byteOffset += (uint32_t)(expression->evaluated.bit_piece.offset / 8);
6779-
countBytes = (uint32_t)(expression->evaluated.bit_piece.size / 8);
6780-
break;
6781-
case DXIL::DW_OP::DW_OP_none: break;
6782-
case DXIL::DW_OP::DW_OP_nop: break;
6783-
default: RDCERR("Unhandled DIExpression op %s", ToStr(expression->op).c_str()); break;
6784-
}
6785-
}
6786-
else
6787-
{
6788-
RDCERR("Unhandled Expression Metadata %s", ToStr(expressionMD->dwarf->type).c_str());
6789-
}
6790-
}
6791-
6792-
AddLocalVariable(localVariableMD, instructionIndex, false, byteOffset, countBytes, resultId,
6793-
resultName);
6709+
DXIL::SourceMappingInfo sourceMappingInfo = m_Program->ParseDbgOpValue(inst);
6710+
AddLocalVariable(sourceMappingInfo, instructionIndex);
67946711
}
67956712

67966713
void Debugger::ParseDebugData()

‎renderdoc/driver/shaders/dxil/dxil_debug.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -538,9 +538,7 @@ class Debugger : public DXBCContainerDebugger
538538
ScopedDebugData *AddScopedDebugData(const DXIL::Metadata *scopeMD);
539539
ScopedDebugData *FindScopedDebugData(const DXIL::Metadata *md) const;
540540
const TypeData &AddDebugType(const DXIL::Metadata *typeMD);
541-
void AddLocalVariable(const DXIL::Metadata *localVariableMD, uint32_t instructionIndex,
542-
bool isDeclare, int32_t byteOffset, uint32_t countBytes, Id debugSSAId,
543-
const rdcstr &debugVarSSAName);
541+
void AddLocalVariable(const DXIL::SourceMappingInfo &srcMapping, uint32_t instructionIndex);
544542
void ParseDebugData();
545543

546544
rdcarray<ThreadState> m_Workgroups;

‎renderdoc/driver/shaders/dxil/dxil_disassemble.cpp

+125
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
#include <algorithm>
2828
#include "common/formatting.h"
2929
#include "maths/half_convert.h"
30+
#include "strings/string_utils.h"
3031
#include "dxil_bytecode.h"
3132
#include "dxil_common.h"
33+
#include "dxil_debuginfo.h"
3234

3335
#if ENABLED(DXC_COMPATIBLE_DISASM) && ENABLED(RDOC_RELEASE)
3436

@@ -4343,6 +4345,40 @@ void Program::MakeRDDisassemblyString(const DXBC::Reflection *reflection)
43434345
}
43444346
else if(callFunc->family == FunctionFamily::LLVMDbg)
43454347
{
4348+
SourceMappingInfo sourceMappingInfo;
4349+
switch(callFunc->llvmIntrinsicOp)
4350+
{
4351+
case LLVMIntrinsicOp::DbgDeclare:
4352+
lineStr = "DbgDeclare";
4353+
sourceMappingInfo = ParseDbgOpDeclare(inst);
4354+
break;
4355+
case LLVMIntrinsicOp::DbgValue:
4356+
lineStr = "DbgValue";
4357+
sourceMappingInfo = ParseDbgOpValue(inst);
4358+
break;
4359+
default: break;
4360+
}
4361+
if(sourceMappingInfo.localVariable)
4362+
{
4363+
rdcstr sourceVarName = GetDebugVarName(sourceMappingInfo.localVariable);
4364+
rdcstr functionName = GetFunctionScopeName(sourceMappingInfo.localVariable);
4365+
4366+
commentStr += StringFormat::Fmt(
4367+
"Function '%s' Variable '%s' Offset %u Count %u bytes maps to %s",
4368+
functionName.c_str(), sourceVarName.c_str(), sourceMappingInfo.srcByteOffset,
4369+
sourceMappingInfo.srcCountBytes, sourceMappingInfo.dbgVarName.c_str());
4370+
4371+
uint32_t dbgLoc = inst.debugLoc;
4372+
if(dbgLoc != ~0U)
4373+
{
4374+
const DebugLocation &debugLoc = m_DebugLocations[dbgLoc];
4375+
4376+
rdcstr shaderFilePath = standardise_directory_separator(
4377+
GetDebugScopeFilePath(sourceMappingInfo.localVariable));
4378+
commentStr += StringFormat::Fmt(
4379+
" ; File:%s Line:%u", get_basename(shaderFilePath).c_str(), debugLoc.line);
4380+
}
4381+
}
43464382
}
43474383
else if(callFunc->family == FunctionFamily::LLVMInstrinsic)
43484384
{
@@ -6130,4 +6166,93 @@ void Program::MakeResultId(const DXIL::Instruction &inst, rdcstr &resultId)
61306166
resultId = StringFormat::Fmt("%c%s", '_', ToStr(inst.slot).c_str());
61316167
}
61326168

6169+
rdcpair<int32_t, int32_t> Program::ParseDIExpressionMD(const Metadata *expressionMD) const
6170+
{
6171+
rdcpair<int32_t, int32_t> ret;
6172+
ret.first = 0;
6173+
ret.second = 0;
6174+
6175+
if(expressionMD)
6176+
{
6177+
if(expressionMD->dwarf->type == DIBase::Type::Expression)
6178+
{
6179+
const DIExpression *expression = expressionMD->dwarf->As<DXIL::DIExpression>();
6180+
switch(expression->op)
6181+
{
6182+
case DXIL::DW_OP::DW_OP_bit_piece:
6183+
ret.first = (uint32_t)(expression->evaluated.bit_piece.offset / 8);
6184+
ret.second = (uint32_t)(expression->evaluated.bit_piece.size / 8);
6185+
break;
6186+
case DXIL::DW_OP::DW_OP_none: break;
6187+
case DXIL::DW_OP::DW_OP_nop: break;
6188+
default: RDCERR("Unhandled DIExpression op %s", ToStr(expression->op).c_str()); break;
6189+
}
6190+
}
6191+
else
6192+
{
6193+
RDCERR("Unhandled Expression Metadata %s", ToStr(expressionMD->dwarf->type).c_str());
6194+
}
6195+
}
6196+
return ret;
6197+
}
6198+
6199+
SourceMappingInfo Program::ParseDbgOpValue(const DXIL::Instruction &inst) const
6200+
{
6201+
SourceMappingInfo ret;
6202+
ret.isDeclare = false;
6203+
6204+
// arg 0 is metadata containing the new value
6205+
const Metadata *valueMD = cast<Metadata>(inst.args[0]);
6206+
ret.dbgVarId = GetSSAId(valueMD->value);
6207+
ret.dbgVarName = GetArgumentName(valueMD->value);
6208+
6209+
// arg 1 is i64 byte offset in the source variable where the new value is written
6210+
int64_t value = 0;
6211+
RDCASSERT(getival<int64_t>(inst.args[1], value));
6212+
ret.srcByteOffset = (int32_t)(value);
6213+
6214+
// arg 2 is DILocalVariable metadata
6215+
const Metadata *localVariableMD = cast<Metadata>(inst.args[2]);
6216+
RDCASSERT(localVariableMD);
6217+
RDCASSERTEQUAL(localVariableMD->dwarf->type, DIBase::Type::LocalVariable);
6218+
ret.localVariable = localVariableMD->dwarf->As<DILocalVariable>();
6219+
6220+
// arg 3 is DIExpression metadata
6221+
const Metadata *expressionMD = cast<Metadata>(inst.args[3]);
6222+
rdcpair<int32_t, int32_t> srcMapping = ParseDIExpressionMD(expressionMD);
6223+
ret.srcByteOffset += srcMapping.first;
6224+
ret.srcCountBytes = srcMapping.second;
6225+
6226+
return ret;
6227+
}
6228+
6229+
SourceMappingInfo Program::ParseDbgOpDeclare(const DXIL::Instruction &inst) const
6230+
{
6231+
SourceMappingInfo ret;
6232+
ret.isDeclare = true;
6233+
6234+
// arg 0 contains the SSA Id of the alloca result which represents the local variable (a pointer)
6235+
const Metadata *allocaInstMD = cast<Metadata>(inst.args[0]);
6236+
RDCASSERT(allocaInstMD);
6237+
const Instruction *allocaInst = cast<Instruction>(allocaInstMD->value);
6238+
RDCASSERT(allocaInst);
6239+
RDCASSERTEQUAL(allocaInst->op, Operation::Alloca);
6240+
ret.dbgVarId = Program::GetResultSSAId(*allocaInst);
6241+
Program::MakeResultId(*allocaInst, ret.dbgVarName);
6242+
6243+
// arg 1 is DILocalVariable metadata
6244+
const Metadata *localVariableMD = cast<Metadata>(inst.args[1]);
6245+
RDCASSERT(localVariableMD);
6246+
RDCASSERTEQUAL(localVariableMD->dwarf->type, DIBase::Type::LocalVariable);
6247+
ret.localVariable = localVariableMD->dwarf->As<DILocalVariable>();
6248+
6249+
// arg 2 is DIExpression metadata
6250+
const Metadata *expressionMD = cast<Metadata>(inst.args[2]);
6251+
rdcpair<int32_t, int32_t> srcMapping = ParseDIExpressionMD(expressionMD);
6252+
ret.srcByteOffset = srcMapping.first;
6253+
ret.srcCountBytes = srcMapping.second;
6254+
6255+
return ret;
6256+
}
6257+
61336258
}; // namespace DXIL

0 commit comments

Comments
 (0)