DXIL support for LLVM lifetime, invariant LLVM intrinsics

Treated as nops by the debugger and disassembler

Extended Function call classification to support LLVM intrinsics
Renamed enum LLVMDbgOp -> LLVMIntrinsicOp
Extended the enum to handle LLVM intrinsics:
* llvm.lifetime.start
* llvm.lifetime.end
* llvm.invariant.start
* llvm.invariant.end
This commit is contained in:
Jake Turner
2024-11-21 06:32:09 +00:00
parent 8019491356
commit 7136385bb1
5 changed files with 88 additions and 27 deletions
+11 -5
View File
@@ -60,13 +60,18 @@ enum class FunctionFamily : uint8_t
LLVM,
DXOp,
LLVMDbg,
LLVMInstrinsic,
};
enum class LLVMDbgOp : uint8_t
enum class LLVMIntrinsicOp : uint8_t
{
Unknown = 0,
Declare,
Value,
DbgDeclare,
DbgValue,
LifetimeStart,
LifetimeEnd,
InvariantStart,
InvariantEnd,
};
struct BumpAllocator
@@ -1397,7 +1402,7 @@ struct Function : public Value
AttachedMetadata attachedMeta;
FunctionFamily family = FunctionFamily::Unknown;
LLVMDbgOp llvmDbgOp = LLVMDbgOp::Unknown;
LLVMIntrinsicOp llvmIntrinsicOp = LLVMIntrinsicOp::Unknown;
};
class LLVMOrderAccumulator
@@ -1745,6 +1750,7 @@ bool IsSSA(const Value *dxilValue);
DXILDebug::Id GetSSAId(const DXIL::Value *value);
bool IsDXCNop(const Instruction &inst);
bool IsLLVMDebugCall(const Instruction &inst);
bool IsLLVMIntrinsicCall(const Instruction &inst);
bool isUndef(const Value *v);
@@ -1759,7 +1765,7 @@ DECLARE_STRINGISE_TYPE(DXIL::Operation);
DECLARE_STRINGISE_TYPE(DXIL::DXOp);
DECLARE_STRINGISE_TYPE(DXIL::Type::TypeKind);
DECLARE_STRINGISE_TYPE(DXIL::Type::ScalarKind);
DECLARE_STRINGISE_TYPE(DXIL::LLVMDbgOp);
DECLARE_STRINGISE_TYPE(DXIL::LLVMIntrinsicOp);
DECLARE_STRINGISE_TYPE(DXIL::DIBase::Type);
DECLARE_STRINGISE_TYPE(DXIL::ValueKind);
DECLARE_STRINGISE_TYPE(DXIL::BarrierMode);
+8 -7
View File
@@ -1534,6 +1534,8 @@ bool IsNopInstruction(const Instruction &inst)
const Function *callFunc = inst.getFuncCall();
if(callFunc->family == FunctionFamily::LLVMDbg)
return true;
if(callFunc->family == FunctionFamily::LLVMInstrinsic)
return true;
}
if(IsDXCNop(inst))
@@ -5320,13 +5322,12 @@ void Debugger::ParseDebugData()
}
const Function *dbgFunc = inst.getFuncCall();
switch(dbgFunc->llvmDbgOp)
switch(dbgFunc->llvmIntrinsicOp)
{
case LLVMDbgOp::Declare: ParseDbgOpDeclare(inst, activeInstructionIndex); break;
case LLVMDbgOp::Value: ParseDbgOpValue(inst, activeInstructionIndex); break;
case LLVMDbgOp::Unknown:
RDCASSERT("Unsupported LLVM debug operation", dbgFunc->llvmDbgOp);
break;
case LLVMIntrinsicOp::DbgDeclare: ParseDbgOpDeclare(inst, activeInstructionIndex); break;
case LLVMIntrinsicOp::DbgValue: ParseDbgOpValue(inst, activeInstructionIndex); break;
case LLVMIntrinsicOp::Unknown:
default: RDCASSERT("Unsupported LLVM debug operation", dbgFunc->llvmIntrinsicOp); break;
};
}
}
@@ -6151,7 +6152,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
for(uint32_t i = 0; i < countInstructions; ++i)
{
const Instruction &inst = *(f->instructions[i]);
if(DXIL::IsDXCNop(inst) || DXIL::IsLLVMDebugCall(inst))
if(DXIL::IsDXCNop(inst) || IsLLVMDebugCall(inst) || DXIL::IsLLVMIntrinsicCall(inst))
continue;
// Stack allocations last until the end of the function
@@ -105,6 +105,12 @@ bool DXIL::IsLLVMDebugCall(const Instruction &inst)
return ((inst.op == Operation::Call) && (inst.getFuncCall()->family == FunctionFamily::LLVMDbg));
}
bool DXIL::IsLLVMIntrinsicCall(const Instruction &inst)
{
return ((inst.op == Operation::Call) &&
(inst.getFuncCall()->family == FunctionFamily::LLVMInstrinsic));
}
// true if the Value is an SSA value i.e. from an instruction, not a constant etc.
bool DXIL::IsSSA(const Value *dxilValue)
{
@@ -1160,18 +1166,50 @@ void Program::SettleIDs()
RDCASSERT(funcCallName.beginsWith(dxOpFunctionNames[(uint32_t)dxOpCode]));
callFunc->family = FunctionFamily::DXOp;
}
else if(funcCallName.beginsWith("llvm.dbg."))
else if(funcCallName.beginsWith("llvm."))
{
LLVMDbgOp dbgOpCode = LLVMDbgOp::Unknown;
if(funcCallName == "llvm.dbg.declare")
dbgOpCode = LLVMDbgOp::Declare;
else if(funcCallName == "llvm.dbg.value")
dbgOpCode = LLVMDbgOp::Value;
else
RDCERR("Unknown llv.dbg call: ", funcCallName.c_str());
LLVMIntrinsicOp intrinsicOp = LLVMIntrinsicOp::Unknown;
FunctionFamily family = FunctionFamily::Unknown;
callFunc->family = FunctionFamily::LLVMDbg;
callFunc->llvmDbgOp = dbgOpCode;
if(funcCallName.beginsWith("llvm.dbg."))
{
family = FunctionFamily::LLVMDbg;
if(funcCallName == "llvm.dbg.declare")
intrinsicOp = LLVMIntrinsicOp::DbgDeclare;
else if(funcCallName == "llvm.dbg.value")
intrinsicOp = LLVMIntrinsicOp::DbgValue;
else
RDCERR("Unknown llvm.dbg call: ", funcCallName.c_str());
}
else if(funcCallName.beginsWith("llvm.lifetime."))
{
family = FunctionFamily::LLVMInstrinsic;
if(funcCallName == "llvm.lifetime.start")
intrinsicOp = LLVMIntrinsicOp::LifetimeStart;
else if(funcCallName == "llvm.lifetime.end")
intrinsicOp = LLVMIntrinsicOp::LifetimeEnd;
else
RDCERR("Unknown llvm.lifetime call: ", funcCallName.c_str());
}
else if(funcCallName.beginsWith("llvm.invariant"))
{
family = FunctionFamily::LLVMInstrinsic;
if(funcCallName == "llvm.invariant.start")
intrinsicOp = LLVMIntrinsicOp::InvariantStart;
else if(funcCallName == "llvm.invariant.end")
intrinsicOp = LLVMIntrinsicOp::InvariantEnd;
else
RDCERR("Unknown llvm.invariant call: ", funcCallName.c_str());
}
else
{
RDCERR("Unknown llvm. call: ", funcCallName.c_str());
}
callFunc->family = family;
callFunc->llvmIntrinsicOp = intrinsicOp;
}
}
}
@@ -4128,6 +4166,9 @@ void Program::MakeRDDisassemblyString(const DXBC::Reflection *reflection)
else if(callFunc->family == FunctionFamily::LLVMDbg)
{
}
else if(callFunc->family == FunctionFamily::LLVMInstrinsic)
{
}
else
{
lineStr += escapeStringIfNeeded(callFunc->name);
+10 -1
View File
@@ -1772,7 +1772,8 @@ rdcstr Program::GetDebugStatus()
// Only support "dx.op" external functions
if(f.external)
{
if(!f.name.beginsWith("dx.op.") && !f.name.beginsWith("llvm.dbg."))
if(!f.name.beginsWith("dx.op.") && !f.name.beginsWith("llvm.dbg.") &&
!f.name.beginsWith("llvm.lifetime.") && !f.name.beginsWith("llvm.invariant."))
return StringFormat::Fmt("Unsupported external function '%s'", f.name.c_str());
}
@@ -1983,6 +1984,14 @@ rdcstr Program::GetDebugStatus()
{
break;
}
else if(funcCallName.beginsWith("llvm.lifetime."))
{
break;
}
else if(funcCallName.beginsWith("llvm.invariant."))
{
break;
}
else
{
return StringFormat::Fmt("Unsupported function call '%s'", ToStr(callFunc->name).c_str());
@@ -524,13 +524,17 @@ rdcstr DoStringise(const DXIL::Type::ScalarKind &el)
}
template <>
rdcstr DoStringise(const DXIL::LLVMDbgOp &el)
rdcstr DoStringise(const DXIL::LLVMIntrinsicOp &el)
{
BEGIN_ENUM_STRINGISE(DXIL::LLVMDbgOp);
BEGIN_ENUM_STRINGISE(DXIL::LLVMIntrinsicOp);
{
STRINGISE_ENUM_CLASS(Declare);
STRINGISE_ENUM_CLASS(Value);
STRINGISE_ENUM_CLASS(Unknown);
STRINGISE_ENUM_CLASS(DbgDeclare);
STRINGISE_ENUM_CLASS(DbgValue);
STRINGISE_ENUM_CLASS(LifetimeStart);
STRINGISE_ENUM_CLASS(LifetimeEnd);
STRINGISE_ENUM_CLASS(InvariantStart);
STRINGISE_ENUM_CLASS(InvariantEnd);
}
END_ENUM_STRINGISE();
}