Skip to content

Commit

Permalink
Initial support NonSemantic.Kernel.DebugInfo.100
Browse files Browse the repository at this point in the history
This patch implements the initial support for the new debug
specification NonSemantic.Kernel.DebugInfo.100.
It also introduces support for the new debug instruction DISubrange.

Spec: KhronosGroup/SPIRV-Registry#186
  • Loading branch information
vmaksimo committed Feb 13, 2023
1 parent 9633373 commit bf51b6c
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 96 deletions.
6 changes: 5 additions & 1 deletion include/LLVMSPIRVOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ enum class BIsRepresentation : uint32_t { OpenCL12, OpenCL20, SPIRVFriendlyIR };

enum class FPContractMode : uint32_t { On, Off, Fast };

enum class DebugInfoEIS : uint32_t { SPIRV_Debug, OpenCL_DebugInfo_100 };
enum class DebugInfoEIS : uint32_t {
SPIRV_Debug,
OpenCL_DebugInfo_100,
NonSemantic_Kernel_DebugInfo_100
};

/// \brief Helper class to manage SPIR-V translation
class TranslatorOpts {
Expand Down
81 changes: 63 additions & 18 deletions lib/SPIRV/LLVMToSPIRVDbgTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) {
case dwarf::DW_TAG_array_type:
return transDbgArrayType(cast<DICompositeType>(DIEntry));

case dwarf::DW_TAG_subrange_type:
return transDbgSubrangeType(cast<DISubrange>(DIEntry));

case dwarf::DW_TAG_const_type:
case dwarf::DW_TAG_restrict_type:
case dwarf::DW_TAG_volatile_type:
Expand Down Expand Up @@ -560,8 +563,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) {
DINodeArray AR(AT->getElements());
// For N-dimensianal arrays AR.getNumElements() == N
const unsigned N = AR.size();
Ops.resize(ComponentCountIdx + N);
SPIRVWordVec LowerBounds(N);
Ops.resize(SubrangesIdx + N);
for (unsigned I = 0; I < N; ++I) {
DISubrange *SR = cast<DISubrange>(AR[I]);
ConstantInt *Count = SR->getCount().get<ConstantInt *>();
Expand All @@ -570,30 +572,73 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) {
Ops[ComponentCountIdx] = static_cast<SPIRVWord>(Count->getZExtValue());
return BM->addDebugInfo(SPIRVDebug::TypeVector, getVoidTy(), Ops);
}
if (Count) {
Ops[ComponentCountIdx + I] =
SPIRVWriter->transValue(Count, nullptr)->getId();
if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) {
Ops[SubrangesIdx + I] = transDbgEntry(SR)->getId();
} else {
if (auto *UpperBound = dyn_cast<MDNode>(SR->getRawUpperBound()))
Ops[ComponentCountIdx + I] = transDbgEntry(UpperBound)->getId();
// According to the OpenCL.DebugInfo.100 specification Count must be a
// Constant or DIVariable. No other operands must be preserved.
if (Count)
Ops[ComponentCountIdx + I] =
SPIRVWriter->transValue(Count, nullptr)->getId();
else if (auto *CountNode =
dyn_cast_or_null<MDNode>(SR->getRawCountNode()))
Ops[ComponentCountIdx + I] = transDbgEntry(CountNode)->getId();
else
Ops[ComponentCountIdx + I] = getDebugInfoNoneId();
}
if (auto *RawLB = SR->getRawLowerBound()) {
if (auto *DIExprLB = dyn_cast<MDNode>(RawLB))
LowerBounds[I] = transDbgEntry(DIExprLB)->getId();
else {
ConstantInt *ConstIntLB = SR->getLowerBound().get<ConstantInt *>();
LowerBounds[I] = SPIRVWriter->transValue(ConstIntLB, nullptr)->getId();
}
} else {
LowerBounds[I] = getDebugInfoNoneId();
}
}
Ops.insert(Ops.end(), LowerBounds.begin(), LowerBounds.end());
return BM->addDebugInfo(SPIRVDebug::TypeArray, getVoidTy(), Ops);
}

SPIRVEntry *LLVMToSPIRVDbgTran::transDbgSubrangeType(const DISubrange *ST) {
using namespace SPIRVDebug::Operand::TypeSubrange;
SPIRVWordVec Ops(OperandCount);
auto transOperand = [&Ops, this, ST](int Idx) -> void {
Metadata *RawNode = nullptr;
switch (Idx) {
case LowerBoundIdx:
RawNode = ST->getRawLowerBound();
break;
case UpperBoundIdx:
RawNode = ST->getRawUpperBound();
break;
case CountIdx:
RawNode = ST->getRawCountNode();
break;
case StrideIdx:
RawNode = ST->getRawStride();
break;
}
if (!RawNode) {
Ops[Idx] = getDebugInfoNoneId();
return;
} else if (auto *Node = dyn_cast<MDNode>(RawNode)) {
Ops[Idx] = transDbgEntry(Node)->getId();
} else {
ConstantInt *IntNode = nullptr;
switch (Idx) {
case LowerBoundIdx:
IntNode = ST->getLowerBound().get<ConstantInt *>();
break;
case UpperBoundIdx:
IntNode = ST->getUpperBound().get<ConstantInt *>();
break;
case CountIdx:
IntNode = ST->getCount().get<ConstantInt *>();
break;
case StrideIdx:
IntNode = ST->getStride().get<ConstantInt *>();
break;
}
Ops[Idx] = IntNode ? SPIRVWriter->transValue(IntNode, nullptr)->getId()
: getDebugInfoNoneId();
}
};
for (int Idx = CountIdx; Idx < OperandCount; ++Idx)
transOperand(Idx);
return BM->addDebugInfo(SPIRVDebug::TypeSubrange, getVoidTy(), Ops);
}

SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTypeDef(const DIDerivedType *DT) {
using namespace SPIRVDebug::Operand::Typedef;
SPIRVWordVec Ops(OperandCount);
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/LLVMToSPIRVDbgTran.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class LLVMToSPIRVDbgTran {
SPIRVEntry *transDbgPointerType(const DIDerivedType *PT);
SPIRVEntry *transDbgQualifiedType(const DIDerivedType *QT);
SPIRVEntry *transDbgArrayType(const DICompositeType *AT);
SPIRVEntry *transDbgSubrangeType(const DISubrange *ST);
SPIRVEntry *transDbgTypeDef(const DIDerivedType *D);
SPIRVEntry *transDbgSubroutineType(const DISubroutineType *FT);
SPIRVEntry *transDbgEnumType(const DICompositeType *ET);
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2298,6 +2298,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
return mapValue(BV, transOCLBuiltinFromExtInst(ExtInst, BB));
case SPIRVEIS_Debug:
case SPIRVEIS_OpenCL_DebugInfo_100:
case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100:
return mapValue(BV, DbgTran->transDebugIntrinsic(ExtInst, BB));
default:
llvm_unreachable("Unknown extended instruction set!");
Expand Down
97 changes: 62 additions & 35 deletions lib/SPIRV/SPIRVToLLVMDbgTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ SPIRVExtInst *SPIRVToLLVMDbgTran::getDbgInst(const SPIRVId Id) {
if (isa<OpExtInst>(E)) {
SPIRVExtInst *EI = static_cast<SPIRVExtInst *>(E);
if (EI->getExtSetKind() == SPIRV::SPIRVEIS_Debug ||
EI->getExtSetKind() == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100)
EI->getExtSetKind() == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100 ||
EI->getExtSetKind() == SPIRV::SPIRVEIS_NonSemantic_Kernel_DebugInfo_100)
return EI;
}
return nullptr;
Expand Down Expand Up @@ -199,46 +200,37 @@ SPIRVToLLVMDbgTran::transTypeArray(const SPIRVExtInst *DebugInst) {
transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[BaseTypeIdx]));
size_t TotalCount = 1;
SmallVector<llvm::Metadata *, 8> Subscripts;
// Ops looks like: { BaseType, count1|upperBound1, count2|upperBound2, ...,
// countN|upperBoundN, lowerBound1, lowerBound2, ..., lowerBoundN }
for (size_t I = ComponentCountIdx, E = Ops.size() / 2 + 1; I < E; ++I) {
if (auto *LocalVar = getDbgInst<SPIRVDebug::LocalVariable>(Ops[I])) {
auto *UpperBound = transDebugInst<DILocalVariable>(LocalVar);
SPIRVConstant *C = BM->get<SPIRVConstant>(Ops[Ops.size() / 2 + I]);
int64_t ConstantAsInt = static_cast<int64_t>(C->getZExtIntValue());
auto *LowerBound = ConstantAsMetadata::get(
ConstantInt::get(M->getContext(), APInt(64, ConstantAsInt)));
Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound,
UpperBound, nullptr));
continue;
if (DebugInst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100,
SPIRVDebug::TypeArray)) {
for (size_t I = SubrangesIdx; I < Ops.size(); ++I) {
auto *SR = transDebugInst<DISubrange>(BM->get<SPIRVExtInst>(Ops[I]));
if (auto *Count = SR->getCount().get<ConstantInt *>())
TotalCount *= Count->getZExtValue() > 0 ? Count->getZExtValue() : 0;
Subscripts.push_back(SR);
}
if (auto *ExprUB = getDbgInst<SPIRVDebug::Expression>(Ops[I])) {
auto *UpperBound = transDebugInst<DIExpression>(ExprUB);
auto *ExprLB =
getDbgInst<SPIRVDebug::Expression>(Ops[Ops.size() / 2 + I]);
auto *LowerBound = transDebugInst<DIExpression>(ExprLB);
Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound,
UpperBound, nullptr));
continue;
}
if (!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[I])) {
SPIRVConstant *C = BM->get<SPIRVConstant>(Ops[I]);
int64_t Count = static_cast<int64_t>(C->getZExtIntValue());
// If the SPIR-V file was generated by an older version of the translator,
// Ops may not contain the LowerBound
if (Ops.size() / 2 + I < Ops.size()) {
C = BM->get<SPIRVConstant>(Ops[Ops.size() / 2 + I]);
int64_t LowerBound = static_cast<int64_t>(C->getZExtIntValue());
Subscripts.push_back(Builder.getOrCreateSubrange(LowerBound, Count));
} else {
} else {
for (size_t I = ComponentCountIdx, E = Ops.size(); I < E; ++I) {
// Otherwise Count could be a constant or DIVariable
if (auto *LocalVarCount = getDbgInst<SPIRVDebug::LocalVariable>(Ops[I])) {
auto *DILocalVarCount = transDebugInst<DILocalVariable>(LocalVarCount);
Subscripts.push_back(Builder.getOrCreateSubrange(
DILocalVarCount, nullptr, nullptr, nullptr));
} else if (auto *GlobalVarCount =
getDbgInst<SPIRVDebug::GlobalVariable>(Ops[I])) {
auto *DIGlobalVarCount =
transDebugInst<DIGlobalVariable>(GlobalVarCount);
Subscripts.push_back(Builder.getOrCreateSubrange(
DIGlobalVarCount, nullptr, nullptr, nullptr));
} else if (!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[I])) {
SPIRVConstant *C = BM->get<SPIRVConstant>(Ops[I]);
int64_t Count = static_cast<int64_t>(C->getZExtIntValue());
// Count = -1 means that the array is empty
TotalCount *= Count > 0 ? Count : 0;
auto *CountAsMD = ConstantAsMetadata::get(
ConstantInt::get(M->getContext(), APInt(64, Count)));
Subscripts.push_back(
Builder.getOrCreateSubrange(CountAsMD, nullptr, nullptr, nullptr));
}
// Count = -1 means that the array is empty
TotalCount *= Count > 0 ? static_cast<size_t>(Count) : 0;
continue;
}
}
DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts);
Expand Down Expand Up @@ -286,6 +278,8 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) {
SPIRVEntry *SizeEntry = BM->getEntry(Ops[SizeIdx]);
if (!(SizeEntry->isExtInst(SPIRVEIS_Debug, SPIRVDebug::DebugInfoNone) ||
SizeEntry->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100,
SPIRVDebug::DebugInfoNone) ||
SizeEntry->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100,
SPIRVDebug::DebugInfoNone))) {
Size = BM->get<SPIRVConstant>(Ops[SizeIdx])->getZExtIntValue();
}
Expand Down Expand Up @@ -341,6 +335,36 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) {
return CT;
}

DISubrange *
SPIRVToLLVMDbgTran::transTypeSubrange(const SPIRVExtInst *DebugInst) {
using namespace SPIRVDebug::Operand::TypeSubrange;
const SPIRVWordVec &Ops = DebugInst->getArguments();
assert(Ops.size() == OperandCount && "Invalid number of operands");
std::vector<Metadata *> TranslatedOps(OperandCount, nullptr);
auto transOperand = [&Ops, &TranslatedOps, this](int Idx) -> void {
if (!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[Idx])) {
if (auto *GlobalVar = getDbgInst<SPIRVDebug::GlobalVariable>(Ops[Idx])) {
TranslatedOps[Idx] =
cast<Metadata>(transDebugInst<DIGlobalVariable>(GlobalVar));
} else if (auto *LocalVar =
getDbgInst<SPIRVDebug::LocalVariable>(Ops[Idx])) {
TranslatedOps[Idx] =
cast<Metadata>(transDebugInst<DILocalVariable>(LocalVar));
} else if (auto *Expr = getDbgInst<SPIRVDebug::Expression>(Ops[Idx])) {
TranslatedOps[Idx] = cast<Metadata>(transDebugInst<DIExpression>(Expr));
} else if (auto *Const = BM->get<SPIRVConstant>(Ops[Idx])) {
int64_t ConstantAsInt = static_cast<int64_t>(Const->getZExtIntValue());
TranslatedOps[Idx] = cast<Metadata>(ConstantAsMetadata::get(
ConstantInt::get(M->getContext(), APInt(64, ConstantAsInt))));
}
}
};
for (int Idx = CountIdx; Idx < OperandCount; ++Idx)
transOperand(Idx);
return Builder.getOrCreateSubrange(TranslatedOps[0], TranslatedOps[1],
TranslatedOps[2], TranslatedOps[3]);
}

DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) {
using namespace SPIRVDebug::Operand::TypeMember;
const SPIRVWordVec &Ops = DebugInst->getArguments();
Expand Down Expand Up @@ -887,6 +911,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) {
case SPIRVDebug::TypeArray:
return transTypeArray(DebugInst);

case SPIRVDebug::TypeSubrange:
return transTypeSubrange(DebugInst);

case SPIRVDebug::TypeVector:
return transTypeVector(DebugInst);

Expand Down
6 changes: 5 additions & 1 deletion lib/SPIRV/SPIRVToLLVMDbgTran.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ class SPIRVToLLVMDbgTran {
template <typename T = MDNode>
T *transDebugInst(const SPIRVExtInst *DebugInst) {
assert((DebugInst->getExtSetKind() == SPIRVEIS_Debug ||
DebugInst->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100) &&
DebugInst->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100 ||
DebugInst->getExtSetKind() ==
SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) &&
"Unexpected extended instruction set");
auto It = DebugInstCache.find(DebugInst);
if (It != DebugInstCache.end())
Expand Down Expand Up @@ -113,6 +115,8 @@ class SPIRVToLLVMDbgTran {

DICompositeType *transTypeComposite(const SPIRVExtInst *DebugInst);

DISubrange *transTypeSubrange(const SPIRVExtInst *DebugInst);

DINode *transTypeMember(const SPIRVExtInst *DebugInst);

DINode *transTypeEnum(const SPIRVExtInst *DebugInst);
Expand Down
14 changes: 13 additions & 1 deletion lib/SPIRV/libSPIRV/SPIRV.debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ enum Instruction {
ImportedEntity = 34,
Source = 35,
ModuleINTEL = 36,
InstCount = 37
InstCount = 37,
TypeSubrange = 107
};

enum Flag {
Expand Down Expand Up @@ -323,12 +324,23 @@ namespace TypeArray {
enum {
BaseTypeIdx = 0,
ComponentCountIdx = 1,
SubrangesIdx = 1,
MinOperandCount = 2
};
}

namespace TypeVector = TypeArray;

namespace TypeSubrange {
enum {
CountIdx = 0,
LowerBoundIdx = 1,
UpperBoundIdx = 2,
StrideIdx = 3,
OperandCount = 4
};
}

namespace Typedef {
enum {
NameIdx = 0,
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ enum SPIRVExtInstSetKind {
SPIRVEIS_OpenCL,
SPIRVEIS_Debug,
SPIRVEIS_OpenCL_DebugInfo_100,
SPIRVEIS_NonSemantic_Kernel_DebugInfo_100,
SPIRVEIS_Count,
};

Expand Down Expand Up @@ -129,6 +130,8 @@ template <> inline void SPIRVMap<SPIRVExtInstSetKind, std::string>::init() {
add(SPIRVEIS_OpenCL, "OpenCL.std");
add(SPIRVEIS_Debug, "SPIRV.debug");
add(SPIRVEIS_OpenCL_DebugInfo_100, "OpenCL.DebugInfo.100");
add(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100,
"NonSemantic.Kernel.DebugInfo.100");
}
typedef SPIRVMap<SPIRVExtInstSetKind, std::string> SPIRVBuiltinSetNameMap;

Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/libSPIRV/SPIRVExtInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ template <> inline void SPIRVMap<SPIRVDebugExtOpKind, std::string>::init() {
"DebugTemplateTemplateParameter");
add(SPIRVDebug::TypeTemplate, "DebugTemplate");
add(SPIRVDebug::TypePtrToMember, "DebugTypePtrToMember,");
add(SPIRVDebug::TypeSubrange, "DebugTypeSubrange");
add(SPIRVDebug::Inheritance, "DebugInheritance");
add(SPIRVDebug::Function, "DebugFunction");
add(SPIRVDebug::FunctionDecl, "DebugFunctionDecl");
Expand Down
6 changes: 5 additions & 1 deletion lib/SPIRV/libSPIRV/SPIRVFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,14 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) {
Module->add(Inst);
} else {
if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::Scope) ||
Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope)) {
Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope) ||
Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100,
SPIRVDebug::Scope)) {
DebugScope = Inst;
} else if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::NoScope) ||
Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100,
SPIRVDebug::NoScope) ||
Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100,
SPIRVDebug::NoScope)) {
DebugScope = nullptr;
} else {
Expand Down
5 changes: 4 additions & 1 deletion lib/SPIRV/libSPIRV/SPIRVInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1761,7 +1761,8 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
assert(Module && "Invalid module");
ExtSetKind = Module->getBuiltinSet(ExtSetId);
assert((ExtSetKind == SPIRVEIS_OpenCL || ExtSetKind == SPIRVEIS_Debug ||
ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100) &&
ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100 ||
ExtSetKind == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) &&
"not supported");
}
void encode(spv_ostream &O) const override {
Expand All @@ -1772,6 +1773,7 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
break;
case SPIRVEIS_Debug:
case SPIRVEIS_OpenCL_DebugInfo_100:
case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100:
getEncoder(O) << ExtOpDebug;
break;
default:
Expand All @@ -1789,6 +1791,7 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
break;
case SPIRVEIS_Debug:
case SPIRVEIS_OpenCL_DebugInfo_100:
case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100:
getDecoder(I) >> ExtOpDebug;
break;
default:
Expand Down
Loading

0 comments on commit bf51b6c

Please sign in to comment.