Skip to content

Commit 8bf97a9

Browse files
authored
Merge pull request #1 from AMD-Lightning-Internal/amd/dev/epilking/diop-support-mainline-cps
[HeterogeneousDwarf] Support translation of DIOp-based DIExpressions
2 parents 2bf2d11 + 1338e5b commit 8bf97a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+416
-116
lines changed

lib/SPIRV/LLVMToSPIRVDbgTran.cpp

+85-4
Original file line numberDiff line numberDiff line change
@@ -1206,14 +1206,22 @@ LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) {
12061206
Ops.push_back(transDbgEntry(StaticMember)->getId());
12071207

12081208
// Check if Ops[VariableIdx] has no information
1209-
if (isNonSemanticDebugInfo() && Ops[VariableIdx] == getDebugInfoNoneId()) {
1209+
if (isNonSemanticDebugInfo()) {
12101210
// Check if GV has an associated GVE with a non-empty DIExpression.
12111211
// The non-empty DIExpression gives the initial value of the GV.
12121212
for (const DIGlobalVariableExpression *GVE : DIF.global_variables()) {
12131213
if ( // GVE matches GV
12141214
GVE->getVariable() == GV &&
12151215
// DIExpression is non-empty
12161216
GVE->getExpression()->getNumElements()) {
1217+
if (Ops[VariableIdx] != getDebugInfoNoneId()) {
1218+
if (GVE->getExpression()->holdsNewElements()) {
1219+
Ops.resize(MaxOperandCount, getDebugInfoNoneId());
1220+
Ops[DIOpBasedExprIdx] =
1221+
transDbgExpression(GVE->getExpression())->getId();
1222+
}
1223+
break;
1224+
}
12171225
// Repurpose VariableIdx operand to hold the initial value held in the
12181226
// GVE's DIExpression
12191227
Ops[VariableIdx] = transDbgExpression(GVE->getExpression())->getId();
@@ -1606,21 +1614,94 @@ LLVMToSPIRVDbgTran::transDbgLocalVariable(const DILocalVariable *Var) {
16061614

16071615
// DWARF Operations and expressions
16081616

1617+
template <>
1618+
void LLVMToSPIRVDbgTran::transDIOpOperand(SPIRVWordVec &Vec, unsigned Idx,
1619+
llvm::Type *Ty) {
1620+
Vec[Idx] = SPIRVWriter->transType(Ty)->getId();
1621+
}
1622+
1623+
template <>
1624+
void LLVMToSPIRVDbgTran::transDIOpOperand(SPIRVWordVec &Vec, unsigned Idx,
1625+
uint32_t UInt) {
1626+
Vec[Idx] = UInt;
1627+
if (isNonSemanticDebugInfo())
1628+
transformToConstant(Vec, {Idx});
1629+
}
1630+
1631+
template <>
1632+
void LLVMToSPIRVDbgTran::transDIOpOperand(SPIRVWordVec &Vec, unsigned Idx,
1633+
llvm::ConstantData *Data) {
1634+
Vec[Idx] = SPIRVWriter->transConstant(Data)->getId();
1635+
}
1636+
16091637
SPIRVEntry *LLVMToSPIRVDbgTran::transDbgExpression(const DIExpression *Expr) {
16101638
SPIRVWordVec Operations;
1639+
1640+
if (auto NewElems = Expr->getNewElementsRef()) {
1641+
if (!(BM->allowExtraDIExpressions() ||
1642+
BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200))
1643+
report_fatal_error(
1644+
llvm::Twine("unsupported DIOp-based opcode found in DIExpression"));
1645+
1646+
for (DIOp::Variant DIOp : *NewElems) {
1647+
using namespace SPIRVDebug::Operand::Operation;
1648+
1649+
unsigned BitcodeID = llvm::DIOp::getBitcodeID(DIOp);
1650+
SPIRVDebug::ExpressionOpCode OC =
1651+
SPIRV::DbgExpressionDIOpBasedOpCodeMap::map(BitcodeID);
1652+
if (OpCountMap.find(OC) == OpCountMap.end())
1653+
report_fatal_error(
1654+
llvm::Twine("unknown DIOp-based opcode found in DIExpression"));
1655+
1656+
unsigned OpCount = OpCountMap[OC];
1657+
SPIRVWordVec Op(OpCount);
1658+
Op[OpCodeIdx] = OC;
1659+
if (isNonSemanticDebugInfo())
1660+
transformToConstant(Op, {OpCodeIdx});
1661+
1662+
#define HANDLE_OP1(Name, OpType, OpName) \
1663+
case llvm::DIOp::Name::getBitcodeID(): \
1664+
assert(OpCount == 2); \
1665+
transDIOpOperand<OpType>(Op, 1, \
1666+
std::get<llvm::DIOp::Name>(DIOp).get##OpName()); \
1667+
break;
1668+
#define HANDLE_OP2(Name, OpType1, OpName1, OpType2, OpName2) \
1669+
case llvm::DIOp::Name::getBitcodeID(): \
1670+
assert(OpCount == 3); \
1671+
transDIOpOperand<OpType1>( \
1672+
Op, 1, std::get<llvm::DIOp::Name>(DIOp).get##OpName1()); \
1673+
transDIOpOperand<OpType2>( \
1674+
Op, 2, std::get<llvm::DIOp::Name>(DIOp).get##OpName2()); \
1675+
break;
1676+
1677+
switch (BitcodeID) {
1678+
#include "llvm/IR/DIExprOps.def"
1679+
default:
1680+
// This is the OP0 case.
1681+
assert(OpCount == 1);
1682+
break;
1683+
}
1684+
1685+
auto *Operation =
1686+
BM->addDebugInfo(SPIRVDebug::Operation, getVoidTy(), Op);
1687+
Operations.push_back(Operation->getId());
1688+
}
1689+
1690+
return BM->addDebugInfo(SPIRVDebug::Expression, getVoidTy(), Operations);
1691+
}
1692+
16111693
for (unsigned I = 0, N = Expr->getNumElements(); I < N; ++I) {
16121694
using namespace SPIRVDebug::Operand::Operation;
16131695
auto DWARFOpCode = static_cast<dwarf::LocationAtom>(Expr->getElement(I));
16141696

16151697
SPIRVDebug::ExpressionOpCode OC =
16161698
SPIRV::DbgExpressionOpCodeMap::map(DWARFOpCode);
16171699
if (OpCountMap.find(OC) == OpCountMap.end())
1618-
report_fatal_error(llvm::Twine("unknown opcode found in DIExpression"));
1700+
report_fatal_error("unknown opcode found in DIExpression");
16191701
if (OC > SPIRVDebug::Fragment &&
16201702
!(BM->allowExtraDIExpressions() ||
16211703
BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200))
1622-
report_fatal_error(
1623-
llvm::Twine("unsupported opcode found in DIExpression"));
1704+
report_fatal_error("unsupported opcode found in DIExpression");
16241705

16251706
unsigned OpCount = OpCountMap[OC];
16261707
SPIRVWordVec Op(OpCount);

lib/SPIRV/LLVMToSPIRVDbgTran.h

+3
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ class LLVMToSPIRVDbgTran {
159159
// DWARF expressions
160160
SPIRVEntry *transDbgExpression(const DIExpression *Expr);
161161

162+
template <class OperandTy>
163+
void transDIOpOperand(SPIRVWordVec &Vec, unsigned Idx, OperandTy Operand);
164+
162165
// Imported declarations and modules
163166
SPIRVEntry *transDbgImportedEntry(const DIImportedEntity *IE);
164167

lib/SPIRV/SPIRVToLLVMDbgTran.cpp

+106-8
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,8 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
11231123
StringRef LinkageName = getString(Ops[LinkageNameIdx]);
11241124

11251125
DIDerivedType *StaticMemberDecl = nullptr;
1126-
if (Ops.size() > MinOperandCount) {
1126+
if (Ops.size() > MinOperandCount &&
1127+
!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[StaticMemberDeclarationIdx])) {
11271128
StaticMemberDecl = transDebugInst<DIDerivedType>(
11281129
BM->get<SPIRVExtInst>(Ops[StaticMemberDeclarationIdx]));
11291130
}
@@ -1135,13 +1136,18 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
11351136
if (getDbgInst<SPIRVDebug::Expression>(Ops[VariableIdx]))
11361137
DIExpr =
11371138
transDebugInst<DIExpression>(BM->get<SPIRVExtInst>(Ops[VariableIdx]));
1139+
else if (Ops.size() > DIOpBasedExprIdx)
1140+
DIExpr = transDebugInst<DIExpression>(
1141+
BM->get<SPIRVExtInst>(Ops[DIOpBasedExprIdx]));
11381142

11391143
SPIRVWord Flags =
11401144
getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
11411145
bool IsLocal = Flags & SPIRVDebug::FlagIsLocal;
11421146
bool IsDefinition = Flags & SPIRVDebug::FlagIsDefinition;
11431147
MDNode *VarDecl = nullptr;
11441148
if (IsDefinition) {
1149+
if (DIExpr && DIExpr->holdsNewElements() && !DIExpr->isValid())
1150+
DIExpr = DIExpr->getPoisoned();
11451151
VarDecl = getDIBuilder(DebugInst).createGlobalVariableExpression(
11461152
Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, IsDefinition,
11471153
DIExpr, StaticMemberDecl);
@@ -1156,7 +1162,7 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
11561162

11571163
// Ops[VariableIdx] was not used to hold an Expression with the initial value
11581164
// for the GlobalVariable
1159-
if (!DIExpr) {
1165+
if (!DIExpr || Ops.size() > DIOpBasedExprIdx) {
11601166
// If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone.
11611167
// Otherwise Ops[VariableIdx] may be a global variable or a constant(C++
11621168
// static const).
@@ -1406,7 +1412,84 @@ DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) {
14061412
Scope, Name, ConfigMacros, IncludePath, ApiNotes, File, Line, IsDecl);
14071413
}
14081414

1415+
template <>
1416+
Type *SPIRVToLLVMDbgTran::transDIOpOperand(const SPIRVExtInst *DbgOpInst,
1417+
unsigned Idx) {
1418+
const SPIRVWordVec &Operands = DbgOpInst->getArguments();
1419+
SPIRVType *Ty = BM->get<SPIRVType>(Operands[Idx]);
1420+
return SPIRVReader->transType(Ty);
1421+
}
1422+
1423+
template <>
1424+
uint32_t SPIRVToLLVMDbgTran::transDIOpOperand(const SPIRVExtInst *DbgOpInst,
1425+
unsigned Idx) {
1426+
const SPIRVWordVec &Operands = DbgOpInst->getArguments();
1427+
return getConstantValueOrLiteral(Operands, Idx, DbgOpInst->getExtSetKind());
1428+
}
1429+
1430+
template <>
1431+
ConstantData *
1432+
SPIRVToLLVMDbgTran::transDIOpOperand(const SPIRVExtInst *DbgOpInst,
1433+
unsigned Idx) {
1434+
const SPIRVWordVec &Operands = DbgOpInst->getArguments();
1435+
SPIRVValue *Val = BM->get<SPIRVValue>(Operands[Idx]);
1436+
return cast<ConstantData>(SPIRVReader->transValue(Val, nullptr, nullptr));
1437+
}
1438+
1439+
MDNode *
1440+
SPIRVToLLVMDbgTran::tryTransDIOpDIExpression(const SPIRVExtInst *DebugInst) {
1441+
using namespace SPIRVDebug::Operand::Operation;
1442+
1443+
auto getOpcodeFromInst = [this](const SPIRVExtInst *OpInst) {
1444+
return static_cast<SPIRVDebug::ExpressionOpCode>(getConstantValueOrLiteral(
1445+
OpInst->getArguments(), OpCodeIdx, OpInst->getExtSetKind()));
1446+
};
1447+
1448+
const SPIRVWordVec &Args = DebugInst->getArguments();
1449+
1450+
// DIOp-based DIExpressions can't be empty.
1451+
if (Args.empty())
1452+
return nullptr;
1453+
const SPIRVExtInst *FirstOp = BM->get<SPIRVExtInst>(Args[0]);
1454+
// Check if this is a DW_OP-based expression.
1455+
if (getOpcodeFromInst(FirstOp) < SPIRVDebug::DIOp_Begin)
1456+
return nullptr;
1457+
1458+
std::vector<llvm::DIOp::Variant> DIOps;
1459+
for (SPIRVId A : Args) {
1460+
SPIRVExtInst *DbgOpInst = BM->get<SPIRVExtInst>(A);
1461+
auto Opcode = getOpcodeFromInst(DbgOpInst);
1462+
auto BitcodeID = SPIRV::DbgExpressionDIOpBasedOpCodeMap::rmap(Opcode);
1463+
1464+
#define HANDLE_OP0(Name) \
1465+
case DIOp::Name::getBitcodeID(): \
1466+
DIOps.push_back(DIOp::Name()); \
1467+
break;
1468+
#define HANDLE_OP1(Name, OpType, OpName) \
1469+
case DIOp::Name::getBitcodeID(): \
1470+
DIOps.push_back(DIOp::Name(transDIOpOperand<OpType>(DbgOpInst, 1))); \
1471+
break;
1472+
#define HANDLE_OP2(Name, OpType1, OpName1, OpType2, OpName2) \
1473+
case DIOp::Name::getBitcodeID(): { \
1474+
OpType1 First = transDIOpOperand<OpType1>(DbgOpInst, 1); \
1475+
OpType2 Second = transDIOpOperand<OpType2>(DbgOpInst, 2); \
1476+
DIOps.push_back(DIOp::Name(First, Second)); \
1477+
break; \
1478+
}
1479+
1480+
switch (BitcodeID) {
1481+
default:
1482+
llvm_unreachable("translating unknown DIOp!");
1483+
#include "llvm/IR/DIExprOps.def"
1484+
}
1485+
}
1486+
return DIExpression::get(M->getContext(), bool(), DIOps);
1487+
}
1488+
14091489
MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) {
1490+
if (MDNode *N = tryTransDIOpDIExpression(DebugInst))
1491+
return N;
1492+
14101493
const SPIRVWordVec &Args = DebugInst->getArguments();
14111494
std::vector<uint64_t> Ops;
14121495
for (SPIRVId A : Args) {
@@ -1563,6 +1646,17 @@ SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugInst,
15631646
auto GetExpression = [&](SPIRVId Id) -> DIExpression * {
15641647
return transDebugInst<DIExpression>(BM->get<SPIRVExtInst>(Id));
15651648
};
1649+
auto PoisonInvalidExpr = [&](DIExpression *Expr, DILocalVariable *Var,
1650+
Value *Op) {
1651+
if (!Expr->holdsNewElements())
1652+
return Expr;
1653+
DIExpressionEnv Env{Var, Op, BB->getParent()->getParent()->getDataLayout()};
1654+
// FIXME: The variadic expression handling for dbg.value below is broken,
1655+
// just poison.
1656+
if (Expr->getNewNumLocationOperands() > 1 || !Expr->isValid(Env))
1657+
return Expr->getPoisoned();
1658+
return Expr;
1659+
};
15661660
SPIRVWordVec Ops = DebugInst->getArguments();
15671661
switch (DebugInst->getExtOp()) {
15681662
case SPIRVDebug::Scope:
@@ -1584,21 +1678,25 @@ SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugInst,
15841678
auto *AI = new AllocaInst(Type::getInt8Ty(M->getContext()),
15851679
BB->getParent()->getParent()->getDataLayout().getAllocaAddrSpace(),
15861680
"tmp", BB);
1587-
DbgInstPtr DbgDeclare = DIB.insertDeclare(
1588-
AI, LocalVar.first, GetExpression(Ops[ExpressionIdx]),
1589-
LocalVar.second, BB);
1681+
auto *Expr = PoisonInvalidExpr(GetExpression(Ops[ExpressionIdx]),
1682+
LocalVar.first, AI);
1683+
DbgInstPtr DbgDeclare =
1684+
DIB.insertDeclare(AI, LocalVar.first, Expr, LocalVar.second, BB);
15901685
AI->eraseFromParent();
15911686
return DbgDeclare;
15921687
}
1593-
return DIB.insertDeclare(GetValue(Ops[VariableIdx]), LocalVar.first,
1594-
GetExpression(Ops[ExpressionIdx]), LocalVar.second,
1595-
BB);
1688+
1689+
Value *Val = GetValue(Ops[VariableIdx]);
1690+
auto *Expr = PoisonInvalidExpr(GetExpression(Ops[ExpressionIdx]),
1691+
LocalVar.first, Val);
1692+
return DIB.insertDeclare(Val, LocalVar.first, Expr, LocalVar.second, BB);
15961693
}
15971694
case SPIRVDebug::Value: {
15981695
using namespace SPIRVDebug::Operand::DebugValue;
15991696
auto LocalVar = GetLocalVar(Ops[DebugLocalVarIdx]);
16001697
Value *Val = GetValue(Ops[ValueIdx]);
16011698
DIExpression *Expr = GetExpression(Ops[ExpressionIdx]);
1699+
Expr = PoisonInvalidExpr(Expr, LocalVar.first, Val);
16021700
DbgInstPtr DbgValIntr = getDIBuilder(DebugInst).insertDbgValueIntrinsic(
16031701
Val, LocalVar.first, Expr, LocalVar.second, BB);
16041702

lib/SPIRV/SPIRVToLLVMDbgTran.h

+4
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ class SPIRVToLLVMDbgTran {
178178

179179
DINode *transModule(const SPIRVExtInst *DebugInst);
180180

181+
template <class OperTy>
182+
OperTy transDIOpOperand(const SPIRVExtInst *DbgOpInst, unsigned Idx);
183+
MDNode *tryTransDIOpDIExpression(const SPIRVExtInst *DebugInst);
184+
181185
MDNode *transExpression(const SPIRVExtInst *DebugInst);
182186

183187
SPIRVModule *BM;

lib/SPIRV/libSPIRV/SPIRV.debug.h

+30-1
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,15 @@ enum ExpressionOpCode {
287287
LLVMArg = 165,
288288
ImplicitPointerTag = 166,
289289
TagOffset = 167,
290+
291+
// AMD-specific debug operations, padded.
292+
Poisoned = 10000,
293+
294+
// DIOp-based debug operations
295+
DIOp_Begin,
296+
#define HANDLE_OP_NAME(Name) \
297+
DIOp##Name = DIOp_Begin + llvm::DIOp::Name::getBitcodeID(),
298+
#include "llvm/IR/DIExprOps.def"
290299
};
291300

292301
enum ImportedEntityTag {
@@ -587,7 +596,9 @@ enum {
587596
VariableIdx = 7,
588597
FlagsIdx = 8,
589598
StaticMemberDeclarationIdx = 9,
590-
MinOperandCount = 9
599+
MinOperandCount = 9,
600+
DIOpBasedExprIdx = 10,
601+
MaxOperandCount = 11,
591602
};
592603
}
593604

@@ -939,6 +950,13 @@ static std::unordered_map<ExpressionOpCode, unsigned> OpCountMap {
939950
{ LLVMArg, 2 },
940951
{ ImplicitPointerTag, 2 },
941952
{ TagOffset, 2 },
953+
954+
{ Poisoned, 1 },
955+
956+
#define HANDLE_OP0(NAME) { DIOp##NAME, 1 },
957+
#define HANDLE_OP1(NAME, T1, N1) { DIOp##NAME, 2 },
958+
#define HANDLE_OP2(NAME, T1, N1, T2, N2) { DIOp##NAME, 3 },
959+
#include "llvm/IR/DIExprOps.def"
942960
};
943961
}
944962

@@ -1431,6 +1449,17 @@ inline void DbgExpressionOpCodeMap::init() {
14311449
add(dwarf::DW_OP_LLVM_arg, SPIRVDebug::LLVMArg);
14321450
add(dwarf::DW_OP_LLVM_implicit_pointer, SPIRVDebug::ImplicitPointerTag);
14331451
add(dwarf::DW_OP_LLVM_tag_offset, SPIRVDebug::TagOffset);
1452+
1453+
add(dwarf::DW_OP_LLVM_poisoned, SPIRVDebug::Poisoned);
1454+
}
1455+
1456+
typedef SPIRVMap<unsigned, SPIRVDebug::ExpressionOpCode>
1457+
DbgExpressionDIOpBasedOpCodeMap;
1458+
template <>
1459+
inline void DbgExpressionDIOpBasedOpCodeMap::init() {
1460+
#define HANDLE_OP_NAME(NAME) \
1461+
add(llvm::DIOp::NAME::getBitcodeID(), SPIRVDebug::DIOp##NAME);
1462+
#include "llvm/IR/DIExprOps.def"
14341463
}
14351464

14361465
typedef SPIRVMap<dwarf::Tag, SPIRVDebug::ImportedEntityTag>

0 commit comments

Comments
 (0)