[llvm] [SPIR-V] Implementation of DebugLine for DI (PR #113541)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 5 05:03:52 PST 2024
https://github.com/bwlodarcz updated https://github.com/llvm/llvm-project/pull/113541
>From 7f9351b85932f7d6d852f46ec4542b519e3dd072 Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Thu, 24 Oct 2024 11:56:28 +0200
Subject: [PATCH 1/7] [SPIR-V] Implementation of DebugLine for DI
---
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 677 ++++++++++++------
.../SPIRV/debug-info/debug-type-pointer.ll | 32 +-
2 files changed, 473 insertions(+), 236 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index d3e323efaee91b..b0ae0abe4928fa 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -5,17 +5,15 @@
#include "SPIRVRegisterInfo.h"
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
-#include "llvm/ADT/SmallPtrSet.h"
+
#include "llvm/ADT/SmallString.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/IR/DebugInfoMetadata.h"
@@ -28,9 +26,9 @@
#define DEBUG_TYPE "spirv-nonsemantic-debug-info"
namespace llvm {
-struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
+struct SPIRVEmitNonSemanticDI : MachineFunctionPass {
static char ID;
- SPIRVTargetMachine *TM;
+ SPIRVTargetMachine *TM = nullptr;
SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM);
SPIRVEmitNonSemanticDI();
@@ -38,7 +36,8 @@ struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
private:
bool IsGlobalDIEmitted = false;
- bool emitGlobalDI(MachineFunction &MF);
+ bool emitGlobalDI(MachineFunction &MF, const Module *M) const;
+ //bool emitLineDI(MachineFunction &MF);
};
} // namespace llvm
@@ -63,6 +62,9 @@ SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
}
+
+namespace {
+
enum BaseTypeAttributeEncoding {
Unspecified = 0,
Address = 1,
@@ -90,149 +92,315 @@ enum SourceLanguage {
Zig = 12
};
-bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
- // If this MachineFunction doesn't have any BB repeat procedure
- // for the next
- if (MF.begin() == MF.end()) {
- IsGlobalDIEmitted = false;
- return false;
+enum TypesMapping {
+ Null = 0,
+ PrimitiveIntArray,
+ PrimitiveStringArray,
+ DebugSourceArray,
+ DebugCompilationUnitArray,
+ DebugTypeBasicArray,
+ DebugTypePointerArray,
+ DebugInfoNoneArray,
+ DebugLineArray
+};
+
+struct DebugSource {
+ size_t FileId;
+
+ explicit constexpr DebugSource(const size_t FileId) noexcept
+ : FileId(FileId) {}
+
+ explicit constexpr DebugSource(const ArrayRef<size_t> AR) : FileId(AR[0]) {}
+
+ friend bool operator==(const DebugSource &Lhs, const DebugSource &Rhs) {
+ return Lhs.FileId == Rhs.FileId;
}
+};
- // Required variables to get from metadata search
- LLVMContext *Context;
- SmallVector<SmallString<128>> FilePaths;
- SmallVector<int64_t> LLVMSourceLanguages;
- int64_t DwarfVersion = 0;
- int64_t DebugInfoVersion = 0;
- SmallPtrSet<DIBasicType *, 12> BasicTypes;
- SmallPtrSet<DIDerivedType *, 12> PointerDerivedTypes;
- // Searching through the Module metadata to find nescessary
- // information like DwarfVersion or SourceLanguage
- {
- const MachineModuleInfo &MMI =
- getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
- const Module *M = MMI.getModule();
- Context = &M->getContext();
- const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
- if (!DbgCu)
- return false;
- for (const auto *Op : DbgCu->operands()) {
- if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
- DIFile *File = CompileUnit->getFile();
- FilePaths.emplace_back();
- sys::path::append(FilePaths.back(), File->getDirectory(),
- File->getFilename());
- LLVMSourceLanguages.push_back(CompileUnit->getSourceLanguage());
- }
- }
- const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
- for (const auto *Op : ModuleFlags->operands()) {
- const MDOperand &MaybeStrOp = Op->getOperand(1);
- if (MaybeStrOp.equalsStr("Dwarf Version"))
- DwarfVersion =
- cast<ConstantInt>(
- cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
- ->getSExtValue();
- else if (MaybeStrOp.equalsStr("Debug Info Version"))
- DebugInfoVersion =
- cast<ConstantInt>(
- cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
- ->getSExtValue();
- }
+struct DebugCompilationUnit {
+ size_t DebugInfoVersionId;
+ size_t DwarfVersionId;
+ size_t DebugSourceId;
+ size_t LanguageId;
+
+ constexpr DebugCompilationUnit(const size_t DebugInfoVersionId,
+ const size_t DwarfVersionId,
+ const size_t DebugSourceId,
+ const size_t LanguageId) noexcept
+ : DebugInfoVersionId(DebugInfoVersionId), DwarfVersionId(DwarfVersionId),
+ DebugSourceId(DebugSourceId), LanguageId(LanguageId) {}
+
+ explicit constexpr DebugCompilationUnit(const ArrayRef<size_t> AR) noexcept
+ : DebugInfoVersionId(AR[0]), DwarfVersionId(AR[1]), DebugSourceId(AR[2]),
+ LanguageId(AR[3]) {}
+
+ friend bool operator==(const DebugCompilationUnit &Lhs,
+ const DebugCompilationUnit &Rhs) {
+ return Lhs.DebugInfoVersionId == Rhs.DebugInfoVersionId &
+ Lhs.DwarfVersionId == Rhs.DwarfVersionId &
+ Lhs.DebugSourceId == Rhs.DebugSourceId &
+ Lhs.LanguageId == Rhs.LanguageId;
+ }
+};
- // This traversal is the only supported way to access
- // instruction related DI metadata like DIBasicType
- for (auto &F : *M) {
- for (auto &BB : F) {
- for (auto &I : BB) {
- for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
- DILocalVariable *LocalVariable = DVR.getVariable();
- if (auto *BasicType =
- dyn_cast<DIBasicType>(LocalVariable->getType())) {
- BasicTypes.insert(BasicType);
- } else if (auto *DerivedType =
- dyn_cast<DIDerivedType>(LocalVariable->getType())) {
- if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
- PointerDerivedTypes.insert(DerivedType);
- // DIBasicType can be unreachable from DbgRecord and only
- // pointed on from other DI types
- // DerivedType->getBaseType is null when pointer
- // is representing a void type
- if (DerivedType->getBaseType())
- BasicTypes.insert(
- cast<DIBasicType>(DerivedType->getBaseType()));
- }
- }
- }
- }
- }
+struct DebugTypeBasic {
+ size_t NameId;
+ size_t SizeId;
+ size_t BaseTypeEncodingId;
+ size_t FlagsId;
+
+ explicit constexpr DebugTypeBasic(const ArrayRef<size_t> AR)
+ : NameId(AR[0]), SizeId(AR[1]), BaseTypeEncodingId(AR[2]),
+ FlagsId(AR[3]) {}
+
+ friend bool operator==(const DebugTypeBasic &Lhs, const DebugTypeBasic &Rhs) {
+ return Lhs.NameId == Rhs.NameId && Lhs.SizeId == Rhs.SizeId &&
+ Lhs.BaseTypeEncodingId == Rhs.BaseTypeEncodingId &&
+ Lhs.FlagsId == Rhs.FlagsId;
+ }
+};
+
+struct DebugTypePointer {
+ size_t BaseTypeId;
+ size_t StorageClassId;
+ size_t FlagsId;
+
+ DebugTypePointer(const size_t BaseTypeId, const size_t StorageClassId,
+ const size_t FlagsId) noexcept
+ : BaseTypeId(BaseTypeId), StorageClassId(StorageClassId),
+ FlagsId(FlagsId) {}
+
+ explicit DebugTypePointer(const ArrayRef<size_t> AR) noexcept
+ : BaseTypeId(AR[0]), StorageClassId(AR[1]), FlagsId(AR[2]) {}
+
+ friend bool operator==(const DebugTypePointer &Lhs,
+ const DebugTypePointer &Rhs) {
+ return Lhs.BaseTypeId == Rhs.BaseTypeId &&
+ Lhs.StorageClassId == Rhs.StorageClassId &&
+ Lhs.FlagsId == Rhs.FlagsId;
+ }
+};
+
+struct DebugLine {
+ size_t DebugSourceId;
+ size_t LineStartId;
+ size_t LineEndId;
+ size_t ColumnStartId;
+ size_t ColumnEndId;
+};
+
+struct DebugInfoNone;
+
+template <typename T> struct DebugTypeContainer;
+
+template <> struct DebugTypeContainer<int64_t> {
+ static constexpr TypesMapping TM = PrimitiveIntArray;
+ static SmallVector<int64_t> Value;
+ static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<StringRef> {
+ static constexpr TypesMapping TM = PrimitiveStringArray;
+ static SmallVector<StringRef> Value;
+ static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugSource> {
+ static constexpr TypesMapping TM = DebugSourceArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugSource;
+ static SmallVector<DebugSource> Value;
+ static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugCompilationUnit> {
+ static constexpr TypesMapping TM = DebugCompilationUnitArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugCompilationUnit;
+ static SmallVector<DebugCompilationUnit> Value;
+ static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugTypeBasic> {
+ static constexpr TypesMapping TM = DebugTypeBasicArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugTypeBasic;
+ static SmallVector<DebugTypeBasic> Value;
+ static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugTypePointer> {
+ static constexpr TypesMapping TM = DebugTypePointerArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugTypePointer;
+ static SmallVector<DebugTypePointer> Value;
+ static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugInfoNone> {
+ static constexpr TypesMapping TM = DebugInfoNoneArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugInfoNone;
+};
+
+SmallVector<int64_t> DebugTypeContainer<int64_t>::Value;
+SmallVector<StringRef> DebugTypeContainer<StringRef>::Value;
+SmallVector<DebugSource> DebugTypeContainer<DebugSource>::Value;
+SmallVector<DebugCompilationUnit>
+ DebugTypeContainer<DebugCompilationUnit>::Value;
+SmallVector<DebugTypeBasic> DebugTypeContainer<DebugTypeBasic>::Value;
+SmallVector<DebugTypePointer> DebugTypeContainer<DebugTypePointer>::Value;
+
+SmallVector<size_t> DebugTypeContainer<int64_t>::Back;
+SmallVector<size_t> DebugTypeContainer<StringRef>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugSource>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugCompilationUnit>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugTypeBasic>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugTypePointer>::Back;
+
+SmallVector<Register> Registers;
+SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
+
+Register emitOpString(const StringRef SR, MachineIRBuilder &MIRBuilder) {
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+ const Register StrReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+ MRI->setType(StrReg, LLT::scalar(32));
+ MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
+ MIB.addDef(StrReg);
+ addStringImm(SR, MIB);
+ return StrReg;
+}
+
+Register emitDIInstruction(SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
+ const ArrayRef<size_t> Ids,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *const TM) {
+ const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
+ const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
+ const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
+ SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+ const SPIRVType *VoidTy = GR->getOrCreateSPIRVType(
+ Type::getVoidTy(MIRBuilder.getContext()), MIRBuilder);
+ const Register InstReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+ MRI->setType(InstReg, LLT::scalar(32));
+ MachineInstrBuilder MIB =
+ MIRBuilder.buildInstr(SPIRV::OpExtInst)
+ .addDef(InstReg)
+ .addUse(GR->getSPIRVTypeID(VoidTy))
+ .addImm(SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)
+ .addImm(Inst);
+ for (auto Id : Ids) {
+ MIB.addUse(Registers[Id]);
+ }
+ MIB.constrainAllUses(*TII, *TRI, *RBI);
+ GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MIRBuilder.getMF());
+ return InstReg;
+}
+
+template <typename T>
+std::pair<size_t, bool> helper(T Val, SmallVectorImpl<T> &SV) {
+ for (unsigned Idx = 0; Idx < SV.size(); ++Idx) {
+ if (Val == SV[Idx]) {
+ return {Idx, true};
}
}
- // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
- {
- // Required LLVM variables for emitting logic
- const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
- const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
- const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
- SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
- MachineRegisterInfo &MRI = MF.getRegInfo();
- MachineBasicBlock &MBB = *MF.begin();
-
- // To correct placement of a OpLabel instruction during SPIRVAsmPrinter
- // emission all new instructions needs to be placed after OpFunction
- // and before first terminator
- MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
-
- const auto EmitOpString = [&](StringRef SR) {
- const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
- MRI.setType(StrReg, LLT::scalar(32));
- MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
- MIB.addDef(StrReg);
- addStringImm(SR, MIB);
- return StrReg;
- };
-
- const SPIRVType *VoidTy =
- GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder);
-
- const auto EmitDIInstruction =
- [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
- std::initializer_list<Register> Registers) {
- const Register InstReg =
- MRI.createVirtualRegister(&SPIRV::IDRegClass);
- MRI.setType(InstReg, LLT::scalar(32));
- MachineInstrBuilder MIB =
- MIRBuilder.buildInstr(SPIRV::OpExtInst)
- .addDef(InstReg)
- .addUse(GR->getSPIRVTypeID(VoidTy))
- .addImm(static_cast<int64_t>(
- SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
- .addImm(Inst);
- for (auto Reg : Registers) {
- MIB.addUse(Reg);
- }
- MIB.constrainAllUses(*TII, *TRI, *RBI);
- GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
- return InstReg;
- };
+ SV.emplace_back(Val);
+ return {SV.size() - 1, false};
+}
+
+size_t push(const int64_t Val, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ auto &SV = DebugTypeContainer<int64_t>::Value;
+ const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+ if (IsDuplicate) {
+ return DebugTypeContainer<int64_t>::Back[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<int64_t>::TM, ConcreteIdx);
+ SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
+ const SPIRVType *I32Ty = GR->getOrCreateSPIRVType(
+ Type::getInt32Ty(MIRBuilder.getContext()), MIRBuilder);
+ Registers.emplace_back(GR->buildConstantInt(Val, MIRBuilder, I32Ty, false));
+ DebugTypeContainer<int64_t>::Back.emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+}
+
+size_t push(const StringRef Val, MachineIRBuilder &MIRBuilder) {
+ auto &SV = DebugTypeContainer<StringRef>::Value;
+ const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+ if (IsDuplicate) {
+ return DebugTypeContainer<StringRef>::Back[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<StringRef>::TM, ConcreteIdx);
+ Registers.emplace_back(emitOpString(Val, MIRBuilder));
+ DebugTypeContainer<StringRef>::Back.emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+}
- const SPIRVType *I32Ty =
- GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
+template <typename T>
+constexpr size_t push(ArrayRef<size_t> Args, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ auto &SV = DebugTypeContainer<T>::Value;
+ const auto [ConcreteIdx, IsDuplicate] = helper(T(Args), SV);
+ if (IsDuplicate) {
+ return DebugTypeContainer<T>::Back[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<T>::TM, ConcreteIdx);
+ Registers.emplace_back(
+ emitDIInstruction(DebugTypeContainer<T>::Inst, Args, MIRBuilder, TM));
+ DebugTypeContainer<T>::Back.emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+}
- const Register DwarfVersionReg =
- GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
+template <>
+size_t push<DebugInfoNone>(ArrayRef<size_t>, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ static std::optional<size_t> DebugInfoNoneIdx = std::nullopt;
+ if (!DebugInfoNoneIdx.has_value()) {
+ Instructions.emplace_back(DebugTypeContainer<DebugInfoNone>::TM, 0);
+ Registers.emplace_back(emitDIInstruction(
+ DebugTypeContainer<DebugInfoNone>::Inst, {}, MIRBuilder, TM));
+ DebugInfoNoneIdx.emplace(Instructions.size() - 1);
+ }
+ return DebugInfoNoneIdx.value();
+}
- const Register DebugInfoVersionReg =
- GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
+size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ // TODO: Initialize assholes
+ std::optional<size_t> DwarfVersionId = std::nullopt;
+ std::optional<size_t> DebugInfoVersionId = std::nullopt;
+ const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
+ for (const auto *Op : ModuleFlags->operands()) {
+ const MDOperand &MaybeStrOp = Op->getOperand(1);
+ if (MaybeStrOp.equalsStr("Dwarf Version")) {
+ const int64_t DwarfVersion =
+ cast<ConstantInt>(
+ cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+ ->getSExtValue();
+ DwarfVersionId = push(DwarfVersion, MIRBuilder, TM);
+ } else if (MaybeStrOp.equalsStr("Debug Info Version")) {
+ const int64_t DebugInfoVersion =
+ cast<ConstantInt>(
+ cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+ ->getSExtValue();
+ DebugInfoVersionId = push(DebugInfoVersion, MIRBuilder, TM);
+ }
+ }
- for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {
- const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);
+ const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
+ for (const auto *Op : DbgCu->operands()) {
+ if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
+ const DIFile *File = CompileUnit->getFile();
+ SmallString<128> FilePath;
+ sys::path::append(FilePath, File->getDirectory(), File->getFilename());
- const Register DebugSourceResIdReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
+ const size_t FilePathId = push(StringRef(FilePath.c_str()), MIRBuilder);
+ const size_t DebugSourceId =
+ push<DebugSource>({FilePathId}, MIRBuilder, TM);
- SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
- switch (LLVMSourceLanguages[Idx]) {
+ SourceLanguage SpirvSourceLanguage;
+ switch (CompileUnit->getSourceLanguage()) {
case dwarf::DW_LANG_OpenCL:
SpirvSourceLanguage = SourceLanguage::OpenCL_C;
break;
@@ -253,99 +421,141 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
break;
case dwarf::DW_LANG_Zig:
SpirvSourceLanguage = SourceLanguage::Zig;
+ break;
+ default:
+ SpirvSourceLanguage = SourceLanguage::Unknown;
}
- const Register SourceLanguageReg =
- GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false);
-
- [[maybe_unused]]
- const Register DebugCompUnitResIdReg =
- EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
- {DebugInfoVersionReg, DwarfVersionReg,
- DebugSourceResIdReg, SourceLanguageReg});
+ size_t SpirvSourceLanguageId = push(SpirvSourceLanguage, MIRBuilder, TM);
+ push<DebugCompilationUnit>({DebugInfoVersionId.value(), DwarfVersionId.value(),
+ DebugSourceId, SpirvSourceLanguageId},
+ MIRBuilder, TM);
}
+ }
+ return 0;
+}
- // We aren't extracting any DebugInfoFlags now so we
- // emitting zero to use as <id>Flags argument for DebugBasicType
- const Register I32ZeroReg =
- GR->buildConstantInt(0, MIRBuilder, I32Ty, false);
-
- // We need to store pairs because further instructions reference
- // the DIBasicTypes and size will be always small so there isn't
- // need for any kind of map
- SmallVector<std::pair<const DIBasicType *const, const Register>, 12>
- BasicTypeRegPairs;
- for (auto *BasicType : BasicTypes) {
- const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
-
- const Register ConstIntBitwidthReg = GR->buildConstantInt(
- BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
-
- uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
- switch (BasicType->getEncoding()) {
- case dwarf::DW_ATE_signed:
- AttributeEncoding = BaseTypeAttributeEncoding::Signed;
- break;
- case dwarf::DW_ATE_unsigned:
- AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
- break;
- case dwarf::DW_ATE_unsigned_char:
- AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
- break;
- case dwarf::DW_ATE_signed_char:
- AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
- break;
- case dwarf::DW_ATE_float:
- AttributeEncoding = BaseTypeAttributeEncoding::Float;
- break;
- case dwarf::DW_ATE_boolean:
- AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
- break;
- case dwarf::DW_ATE_address:
- AttributeEncoding = BaseTypeAttributeEncoding::Address;
- }
+size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+
+ const size_t BasicTypeStrId = push(BT->getName(), MIRBuilder);
+
+ const size_t ConstIntBitWidthId = push(BT->getSizeInBits(), MIRBuilder, TM);
+
+ uint64_t AttributeEncoding;
+ switch (BT->getEncoding()) {
+ case dwarf::DW_ATE_signed:
+ AttributeEncoding = BaseTypeAttributeEncoding::Signed;
+ break;
+ case dwarf::DW_ATE_unsigned:
+ AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
+ break;
+ case dwarf::DW_ATE_unsigned_char:
+ AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
+ break;
+ case dwarf::DW_ATE_signed_char:
+ AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
+ break;
+ case dwarf::DW_ATE_float:
+ AttributeEncoding = BaseTypeAttributeEncoding::Float;
+ break;
+ case dwarf::DW_ATE_boolean:
+ AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
+ break;
+ case dwarf::DW_ATE_address:
+ AttributeEncoding = BaseTypeAttributeEncoding::Address;
+ break;
+ default:
+ AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
+ }
- const Register AttributeEncodingReg =
- GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
+ const size_t AttributeEncodingId = push(AttributeEncoding, MIRBuilder, TM);
- const Register BasicTypeReg =
- EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
- {BasicTypeStrReg, ConstIntBitwidthReg,
- AttributeEncodingReg, I32ZeroReg});
- BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);
- }
+ return push<DebugTypeBasic>(
+ {BasicTypeStrId, ConstIntBitWidthId, AttributeEncodingId, I32ZeroIdx},
+ MIRBuilder, TM);
+}
+
+size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t BasicTypeIdx,
+ const size_t I32ZeroIdx,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ assert(DT->getDWARFAddressSpace().has_value());
+
+ size_t StorageClassIdx =
+ push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+ *TM->getSubtargetImpl()),
+ MIRBuilder, TM);
+
+ return push<DebugTypePointer>({BasicTypeIdx, StorageClassIdx, I32ZeroIdx},
+ MIRBuilder, TM);
+}
- if (PointerDerivedTypes.size()) {
- for (const auto *PointerDerivedType : PointerDerivedTypes) {
-
- assert(PointerDerivedType->getDWARFAddressSpace().has_value());
- const Register StorageClassReg = GR->buildConstantInt(
- addressSpaceToStorageClass(
- PointerDerivedType->getDWARFAddressSpace().value(),
- *TM->getSubtargetImpl()),
- MIRBuilder, I32Ty, false);
-
- // If the Pointer is representing a void type it's getBaseType
- // is a nullptr
- const auto *MaybeNestedBasicType =
- cast_or_null<DIBasicType>(PointerDerivedType->getBaseType());
- if (MaybeNestedBasicType) {
- for (const auto &BasicTypeRegPair : BasicTypeRegPairs) {
- const auto &[DefinedBasicType, BasicTypeReg] = BasicTypeRegPair;
- if (DefinedBasicType == MaybeNestedBasicType) {
- [[maybe_unused]]
- const Register DebugPointerTypeReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugTypePointer,
- {BasicTypeReg, StorageClassReg, I32ZeroReg});
+size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t I32ZeroIdx,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ assert(DT->getDWARFAddressSpace().has_value());
+
+ size_t StorageClassIdx =
+ push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+ *TM->getSubtargetImpl()),
+ MIRBuilder, TM);
+
+ // If the Pointer is representing a void type it's getBaseType
+ // is a nullptr
+ size_t DebugInfoNoneIdx = push<DebugInfoNone>({}, MIRBuilder, TM);
+ return push<DebugTypePointer>({DebugInfoNoneIdx, StorageClassIdx, I32ZeroIdx},
+ MIRBuilder, TM);
+}
+} // namespace
+
+bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
+ const Module *M) const {
+ MachineBasicBlock &MBB = *MF.begin();
+
+ // To correct placement of a OpLabel instruction during SPIRVAsmPrinter
+ // emission all new instructions needs to be placed after OpFunction
+ // and before first terminator
+ MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
+
+ emitDebugCompilationUnits(M, MIRBuilder, TM);
+
+ for (auto &F : *M) {
+ for (auto &BB : F) {
+ for (auto &I : BB) {
+ for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
+ const DILocalVariable *LocalVariable = DVR.getVariable();
+ if (const auto *BasicType =
+ dyn_cast<DIBasicType>(LocalVariable->getType())) {
+ // We aren't extracting any DebugInfoFlags now so we're
+ // emitting zero to use as <id>Flags argument for DebugBasicType
+ const size_t I32ZeroIdx = push(0, MIRBuilder, TM);
+ emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM);
+ continue;
+ }
+ // Beware else if here. Types from previous scopes are
+ // counterintuitively still visible for the next ifs scopes.
+ if (const auto *DerivedType =
+ dyn_cast<DIDerivedType>(LocalVariable->getType())) {
+ if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
+ const size_t I32ZeroIdx = push(0, MIRBuilder, TM);
+ // DIBasicType can be unreachable from DbgRecord and only
+ // pointed on from other DI types
+ // DerivedType->getBaseType is null when pointer
+ // is representing a void type
+ if (DerivedType->getBaseType()) {
+ const auto *BasicType =
+ cast<DIBasicType>(DerivedType->getBaseType());
+ const size_t BTIdx =
+ emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM);
+ emitDebugTypePointer(DerivedType, BTIdx, I32ZeroIdx, MIRBuilder,
+ TM);
+ } else {
+ emitDebugTypePointer(DerivedType, I32ZeroIdx, MIRBuilder, TM);
+ }
}
}
- } else {
- const Register DebugInfoNoneReg =
- EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});
- [[maybe_unused]]
- const Register DebugPointerTypeReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugTypePointer,
- {DebugInfoNoneReg, StorageClassReg, I32ZeroReg});
}
}
}
@@ -353,13 +563,34 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
return true;
}
+// bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
+// for (auto &MBB : MF) {
+// for (auto &MI : MBB) {
+// if (MI.isDebugValue()) {
+// DebugLoc DL = MI.getDebugLoc();
+// }
+// }
+// }
+// return false;
+// }
+
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
bool Res = false;
// emitGlobalDI needs to be executed only once to avoid
// emitting duplicates
if (!IsGlobalDIEmitted) {
+ if (MF.begin() == MF.end()) {
+ return false;
+ }
IsGlobalDIEmitted = true;
- Res = emitGlobalDI(MF);
+ const MachineModuleInfo &MMI =
+ getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+ const Module *M = MMI.getModule();
+ const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
+ if (!DbgCu)
+ return false;
+ Res = emitGlobalDI(MF, M);
}
+ // Res |= emitLineDI(MF);
return Res;
}
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
index b7e6e95f366cf7..d9ef3f59da3577 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
@@ -28,19 +28,22 @@
; CHECK-MIR-DAG: [[float:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_float]], [[i32_0]]
; CHECK-MIR-DAG: [[double:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_64]], [[enc_float]], [[i32_0]]
; CHECK-MIR-DAG: [[int:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_signed]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[bool]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[short]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[char]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[long]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_int]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_short]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_char]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_long]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[float]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[double]], [[i32_8]], [[i32_0]]
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[int]], [[i32_5]], [[i32_0]]
-; CHECK-MIR: [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 0
-; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[bool]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[short]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[char]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[long]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_int]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_short]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_char]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_long]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[float]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[double]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[int]], [[i32_5]], [[i32_0]]
+; CHECK-MIR-DAG: [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 0
+; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]]
+
+; Duplicates check
+; CHECK-MIR-NOT: OpExtInst [[void_type]], 3, 3
; CHECK-SPIRV: [[i32type:%[0-9]+]] = OpTypeInt 32 0
; CHECK-SPIRV-DAG: [[i32_8:%[0-9]+]] = OpConstant [[i32type]] 8
@@ -79,6 +82,9 @@
; CHECK-SPIRV-DAG: [[debug_info_none:%[0-9]+]] = OpExtInst {{%[0-9]+ %[0-9]+}} DebugInfoNone
; CHECK-SPIRV-DAG: OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypePointer [[debug_info_none]] [[i32_5]] [[i32_0]]
+; Duplicates check
+; CHECK-SPIRV-NOT: OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypePointer
+
; CHECK-OPTION-NOT: DebugTypePointer
@gi0 = dso_local addrspace(1) global ptr addrspace(4) null, align 4, !dbg !0
>From 5982e57046e99dfb6b8fcd06c33994391cce4cd5 Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Thu, 24 Oct 2024 15:48:52 +0200
Subject: [PATCH 2/7] Support for DebugLine
---
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 80 ++++++++++++++++---
1 file changed, 67 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index b0ae0abe4928fa..0fa698592f57d1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -37,7 +37,7 @@ struct SPIRVEmitNonSemanticDI : MachineFunctionPass {
private:
bool IsGlobalDIEmitted = false;
bool emitGlobalDI(MachineFunction &MF, const Module *M) const;
- //bool emitLineDI(MachineFunction &MF);
+ bool emitLineDI(MachineFunction &MF);
};
} // namespace llvm
@@ -187,6 +187,19 @@ struct DebugLine {
size_t LineEndId;
size_t ColumnStartId;
size_t ColumnEndId;
+
+ DebugLine(const ArrayRef<size_t> AR)
+ : DebugSourceId(AR[0]), LineStartId(AR[1]),
+ LineEndId(AR[2]), ColumnStartId(AR[3]),
+ ColumnEndId(AR[4]) {}
+
+ friend bool operator==(const DebugLine &Lhs, const DebugLine &Rhs) {
+ return Lhs.DebugSourceId == Rhs.DebugSourceId &&
+ Lhs.LineStartId == Rhs.LineStartId &&
+ Lhs.LineEndId == Rhs.LineEndId &&
+ Lhs.ColumnStartId == Rhs.ColumnStartId &&
+ Lhs.ColumnEndId == Rhs.ColumnEndId;
+ }
};
struct DebugInfoNone;
@@ -243,6 +256,14 @@ template <> struct DebugTypeContainer<DebugInfoNone> {
SPIRV::NonSemanticExtInst::DebugInfoNone;
};
+template <> struct DebugTypeContainer<DebugLine> {
+ static constexpr TypesMapping TM = DebugLineArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugLine;
+ static SmallVector<DebugLine> Value;
+ static SmallVector<size_t> Back;
+};
+
SmallVector<int64_t> DebugTypeContainer<int64_t>::Value;
SmallVector<StringRef> DebugTypeContainer<StringRef>::Value;
SmallVector<DebugSource> DebugTypeContainer<DebugSource>::Value;
@@ -250,6 +271,7 @@ SmallVector<DebugCompilationUnit>
DebugTypeContainer<DebugCompilationUnit>::Value;
SmallVector<DebugTypeBasic> DebugTypeContainer<DebugTypeBasic>::Value;
SmallVector<DebugTypePointer> DebugTypeContainer<DebugTypePointer>::Value;
+SmallVector<DebugLine> DebugTypeContainer<DebugLine>::Value;
SmallVector<size_t> DebugTypeContainer<int64_t>::Back;
SmallVector<size_t> DebugTypeContainer<StringRef>::Back;
@@ -257,6 +279,7 @@ SmallVector<size_t> DebugTypeContainer<DebugSource>::Back;
SmallVector<size_t> DebugTypeContainer<DebugCompilationUnit>::Back;
SmallVector<size_t> DebugTypeContainer<DebugTypeBasic>::Back;
SmallVector<size_t> DebugTypeContainer<DebugTypePointer>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugLine>::Back;
SmallVector<Register> Registers;
SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
@@ -365,9 +388,33 @@ size_t push<DebugInfoNone>(ArrayRef<size_t>, MachineIRBuilder &MIRBuilder,
return DebugInfoNoneIdx.value();
}
+void cleanup() {
+ DebugTypeContainer<int64_t>::Value.clear();
+ DebugTypeContainer<StringRef>::Value.clear();
+ DebugTypeContainer<DebugSource>::Value.clear();
+ DebugTypeContainer<DebugCompilationUnit>::Value.clear();
+ DebugTypeContainer<DebugTypeBasic>::Value.clear();
+ DebugTypeContainer<DebugTypePointer>::Value.clear();
+ DebugTypeContainer<DebugLine>::Value.clear();
+
+ DebugTypeContainer<int64_t>::Back.clear();
+ DebugTypeContainer<StringRef>::Back.clear();
+ DebugTypeContainer<DebugSource>::Back.clear();
+ DebugTypeContainer<DebugCompilationUnit>::Back.clear();
+ DebugTypeContainer<DebugTypeBasic>::Back.clear();
+ DebugTypeContainer<DebugTypePointer>::Back.clear();
+ DebugTypeContainer<DebugLine>::Back.clear();
+}
+
+size_t emitDebugSource(const DIFile *File, MachineIRBuilder &MIRBuilder, SPIRVTargetMachine *TM) {
+ SmallString<128> FilePath;
+ sys::path::append(FilePath, File->getDirectory(), File->getFilename());
+ const size_t FilePathId = push(StringRef(FilePath.c_str()), MIRBuilder);
+ return push<DebugSource>({FilePathId}, MIRBuilder, TM);
+}
+
size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
const SPIRVTargetMachine *TM) {
- // TODO: Initialize assholes
std::optional<size_t> DwarfVersionId = std::nullopt;
std::optional<size_t> DebugInfoVersionId = std::nullopt;
const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
@@ -563,16 +610,22 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
return true;
}
-// bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
-// for (auto &MBB : MF) {
-// for (auto &MI : MBB) {
-// if (MI.isDebugValue()) {
-// DebugLoc DL = MI.getDebugLoc();
-// }
-// }
-// }
-// return false;
-// }
+bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
+ for (auto &MBB : MF) {
+ for (auto &MI : MBB) {
+ if (MI.isDebugValue()) {
+ MachineIRBuilder MIRBuilder(MBB, MI);
+ DebugLoc DL = MI.getDebugLoc();
+ const auto *File = cast<DISubprogram>(DL.getScope())->getFile();
+ const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM);
+ const size_t LineIdx = push(DL.getLine(), MIRBuilder, TM);
+ const size_t ColIdx = push(DL.getLine(), MIRBuilder, TM);
+ push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx}, MIRBuilder, TM);
+ }
+ }
+ }
+ return false;
+}
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
bool Res = false;
@@ -591,6 +644,7 @@ bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
return false;
Res = emitGlobalDI(MF, M);
}
- // Res |= emitLineDI(MF);
+ Res |= emitLineDI(MF);
+ cleanup();
return Res;
}
>From 2af47fbb3f26b5009bdb0f36bf51af13380c6eff Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Mon, 28 Oct 2024 12:15:13 +0100
Subject: [PATCH 3/7] Addedd LiveRepository class
---
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 463 +++++++++---------
1 file changed, 239 insertions(+), 224 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index 0fa698592f57d1..0e9cd7a8ee511d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -25,45 +25,8 @@
#define DEBUG_TYPE "spirv-nonsemantic-debug-info"
-namespace llvm {
-struct SPIRVEmitNonSemanticDI : MachineFunctionPass {
- static char ID;
- SPIRVTargetMachine *TM = nullptr;
- SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM);
- SPIRVEmitNonSemanticDI();
-
- bool runOnMachineFunction(MachineFunction &MF) override;
-
-private:
- bool IsGlobalDIEmitted = false;
- bool emitGlobalDI(MachineFunction &MF, const Module *M) const;
- bool emitLineDI(MachineFunction &MF);
-};
-} // namespace llvm
-
-using namespace llvm;
-
-INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE,
- "SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false)
-
-char SPIRVEmitNonSemanticDI::ID = 0;
-
-MachineFunctionPass *
-llvm::createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) {
- return new SPIRVEmitNonSemanticDI(TM);
-}
-
-SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM)
- : MachineFunctionPass(ID), TM(TM) {
- initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
-}
-
-SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
- initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
-}
-
-
namespace {
+using namespace llvm;
enum BaseTypeAttributeEncoding {
Unspecified = 0,
@@ -93,7 +56,6 @@ enum SourceLanguage {
};
enum TypesMapping {
- Null = 0,
PrimitiveIntArray,
PrimitiveStringArray,
DebugSourceArray,
@@ -188,10 +150,9 @@ struct DebugLine {
size_t ColumnStartId;
size_t ColumnEndId;
- DebugLine(const ArrayRef<size_t> AR)
- : DebugSourceId(AR[0]), LineStartId(AR[1]),
- LineEndId(AR[2]), ColumnStartId(AR[3]),
- ColumnEndId(AR[4]) {}
+ explicit DebugLine(const ArrayRef<size_t> AR)
+ : DebugSourceId(AR[0]), LineStartId(AR[1]), LineEndId(AR[2]),
+ ColumnStartId(AR[3]), ColumnEndId(AR[4]) {}
friend bool operator==(const DebugLine &Lhs, const DebugLine &Rhs) {
return Lhs.DebugSourceId == Rhs.DebugSourceId &&
@@ -208,46 +169,34 @@ template <typename T> struct DebugTypeContainer;
template <> struct DebugTypeContainer<int64_t> {
static constexpr TypesMapping TM = PrimitiveIntArray;
- static SmallVector<int64_t> Value;
- static SmallVector<size_t> Back;
};
template <> struct DebugTypeContainer<StringRef> {
static constexpr TypesMapping TM = PrimitiveStringArray;
- static SmallVector<StringRef> Value;
- static SmallVector<size_t> Back;
};
template <> struct DebugTypeContainer<DebugSource> {
static constexpr TypesMapping TM = DebugSourceArray;
static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
SPIRV::NonSemanticExtInst::DebugSource;
- static SmallVector<DebugSource> Value;
- static SmallVector<size_t> Back;
};
template <> struct DebugTypeContainer<DebugCompilationUnit> {
static constexpr TypesMapping TM = DebugCompilationUnitArray;
static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
SPIRV::NonSemanticExtInst::DebugCompilationUnit;
- static SmallVector<DebugCompilationUnit> Value;
- static SmallVector<size_t> Back;
};
template <> struct DebugTypeContainer<DebugTypeBasic> {
static constexpr TypesMapping TM = DebugTypeBasicArray;
static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
SPIRV::NonSemanticExtInst::DebugTypeBasic;
- static SmallVector<DebugTypeBasic> Value;
- static SmallVector<size_t> Back;
};
template <> struct DebugTypeContainer<DebugTypePointer> {
static constexpr TypesMapping TM = DebugTypePointerArray;
static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
SPIRV::NonSemanticExtInst::DebugTypePointer;
- static SmallVector<DebugTypePointer> Value;
- static SmallVector<size_t> Back;
};
template <> struct DebugTypeContainer<DebugInfoNone> {
@@ -260,124 +209,161 @@ template <> struct DebugTypeContainer<DebugLine> {
static constexpr TypesMapping TM = DebugLineArray;
static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
SPIRV::NonSemanticExtInst::DebugLine;
- static SmallVector<DebugLine> Value;
- static SmallVector<size_t> Back;
};
-SmallVector<int64_t> DebugTypeContainer<int64_t>::Value;
-SmallVector<StringRef> DebugTypeContainer<StringRef>::Value;
-SmallVector<DebugSource> DebugTypeContainer<DebugSource>::Value;
-SmallVector<DebugCompilationUnit>
- DebugTypeContainer<DebugCompilationUnit>::Value;
-SmallVector<DebugTypeBasic> DebugTypeContainer<DebugTypeBasic>::Value;
-SmallVector<DebugTypePointer> DebugTypeContainer<DebugTypePointer>::Value;
-SmallVector<DebugLine> DebugTypeContainer<DebugLine>::Value;
-
-SmallVector<size_t> DebugTypeContainer<int64_t>::Back;
-SmallVector<size_t> DebugTypeContainer<StringRef>::Back;
-SmallVector<size_t> DebugTypeContainer<DebugSource>::Back;
-SmallVector<size_t> DebugTypeContainer<DebugCompilationUnit>::Back;
-SmallVector<size_t> DebugTypeContainer<DebugTypeBasic>::Back;
-SmallVector<size_t> DebugTypeContainer<DebugTypePointer>::Back;
-SmallVector<size_t> DebugTypeContainer<DebugLine>::Back;
-
-SmallVector<Register> Registers;
-SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
-
-Register emitOpString(const StringRef SR, MachineIRBuilder &MIRBuilder) {
- MachineRegisterInfo *MRI = MIRBuilder.getMRI();
- const Register StrReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
- MRI->setType(StrReg, LLT::scalar(32));
- MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
- MIB.addDef(StrReg);
- addStringImm(SR, MIB);
- return StrReg;
-}
+template <typename T> struct DebugLiveContainer {
+ SmallVector<T> Value;
+ SmallVector<size_t> Back;
+};
-Register emitDIInstruction(SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
- const ArrayRef<size_t> Ids,
- MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *const TM) {
- const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
- const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
- const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
- SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
- MachineRegisterInfo *MRI = MIRBuilder.getMRI();
- const SPIRVType *VoidTy = GR->getOrCreateSPIRVType(
- Type::getVoidTy(MIRBuilder.getContext()), MIRBuilder);
- const Register InstReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
- MRI->setType(InstReg, LLT::scalar(32));
- MachineInstrBuilder MIB =
- MIRBuilder.buildInstr(SPIRV::OpExtInst)
- .addDef(InstReg)
- .addUse(GR->getSPIRVTypeID(VoidTy))
- .addImm(SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)
- .addImm(Inst);
- for (auto Id : Ids) {
- MIB.addUse(Registers[Id]);
+class LiveRepository {
+ DebugLiveContainer<int64_t> PrimitiveInts;
+ DebugLiveContainer<StringRef> PrimitiveStrings;
+ DebugLiveContainer<DebugSource> DebugSources;
+ DebugLiveContainer<DebugLine> DebugLines;
+ DebugLiveContainer<DebugCompilationUnit> DebugCompilationUnits;
+ DebugLiveContainer<DebugTypeBasic> DebugTypeBasics;
+ DebugLiveContainer<DebugTypePointer> DebugTypePointers;
+
+ SmallVector<Register> Registers;
+ SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
+
+ template <typename T> constexpr SmallVector<T> &value() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return PrimitiveInts.Value;
+ } else if constexpr (std::is_same_v<T, StringRef>) {
+ return PrimitiveStrings.Value;
+ } else if constexpr (std::is_same_v<T, DebugLine>) {
+ return DebugLines.Value;
+ } else if constexpr (std::is_same_v<T, DebugSource>) {
+ return DebugSources.Value;
+ } else if constexpr (std::is_same_v<T, DebugCompilationUnit>) {
+ return DebugCompilationUnits.Value;
+ } else if constexpr (std::is_same_v<T, DebugTypeBasic>) {
+ return DebugTypeBasics.Value;
+ } else if constexpr (std::is_same_v<T, DebugTypePointer>) {
+ return DebugTypePointers.Value;
+ }
+ llvm_unreachable("unreachable");
}
- MIB.constrainAllUses(*TII, *TRI, *RBI);
- GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MIRBuilder.getMF());
- return InstReg;
-}
-template <typename T>
-std::pair<size_t, bool> helper(T Val, SmallVectorImpl<T> &SV) {
- for (unsigned Idx = 0; Idx < SV.size(); ++Idx) {
- if (Val == SV[Idx]) {
- return {Idx, true};
+ template <typename T> constexpr SmallVector<size_t> &back() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return PrimitiveInts.Back;
+ } else if constexpr (std::is_same_v<T, StringRef>) {
+ return PrimitiveStrings.Back;
+ } else if constexpr (std::is_same_v<T, DebugLine>) {
+ return DebugLines.Back;
+ } else if constexpr (std::is_same_v<T, DebugSource>) {
+ return DebugSources.Back;
+ } else if constexpr (std::is_same_v<T, DebugCompilationUnit>) {
+ return DebugCompilationUnits.Back;
+ } else if constexpr (std::is_same_v<T, DebugTypeBasic>) {
+ return DebugTypeBasics.Back;
+ } else if constexpr (std::is_same_v<T, DebugTypePointer>) {
+ return DebugTypePointers.Back;
}
+ llvm_unreachable("unreachable");
}
- SV.emplace_back(Val);
- return {SV.size() - 1, false};
-}
-size_t push(const int64_t Val, MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
- auto &SV = DebugTypeContainer<int64_t>::Value;
- const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
- if (IsDuplicate) {
- return DebugTypeContainer<int64_t>::Back[ConcreteIdx];
+ template <typename T>
+ static std::pair<size_t, bool> helper(T Val, SmallVectorImpl<T> &SV) {
+ for (unsigned Idx = 0; Idx < SV.size(); ++Idx) {
+ if (Val == SV[Idx]) {
+ return {Idx, true};
+ }
+ }
+ SV.emplace_back(Val);
+ return {SV.size() - 1, false};
}
- Instructions.emplace_back(DebugTypeContainer<int64_t>::TM, ConcreteIdx);
- SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
- const SPIRVType *I32Ty = GR->getOrCreateSPIRVType(
- Type::getInt32Ty(MIRBuilder.getContext()), MIRBuilder);
- Registers.emplace_back(GR->buildConstantInt(Val, MIRBuilder, I32Ty, false));
- DebugTypeContainer<int64_t>::Back.emplace_back(Instructions.size() - 1);
- return Instructions.size() - 1;
-}
-size_t push(const StringRef Val, MachineIRBuilder &MIRBuilder) {
- auto &SV = DebugTypeContainer<StringRef>::Value;
- const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
- if (IsDuplicate) {
- return DebugTypeContainer<StringRef>::Back[ConcreteIdx];
+ static Register emitOpString(const StringRef SR,
+ MachineIRBuilder &MIRBuilder) {
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+ const Register StrReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+ MRI->setType(StrReg, LLT::scalar(32));
+ MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
+ MIB.addDef(StrReg);
+ addStringImm(SR, MIB);
+ return StrReg;
}
- Instructions.emplace_back(DebugTypeContainer<StringRef>::TM, ConcreteIdx);
- Registers.emplace_back(emitOpString(Val, MIRBuilder));
- DebugTypeContainer<StringRef>::Back.emplace_back(Instructions.size() - 1);
- return Instructions.size() - 1;
-}
-template <typename T>
-constexpr size_t push(ArrayRef<size_t> Args, MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
- auto &SV = DebugTypeContainer<T>::Value;
- const auto [ConcreteIdx, IsDuplicate] = helper(T(Args), SV);
- if (IsDuplicate) {
- return DebugTypeContainer<T>::Back[ConcreteIdx];
+ Register emitDIInstruction(SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
+ const ArrayRef<size_t> Ids,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *const TM) {
+ const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
+ const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
+ const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
+ SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+ const SPIRVType *VoidTy = GR->getOrCreateSPIRVType(
+ Type::getVoidTy(MIRBuilder.getContext()), MIRBuilder);
+ const Register InstReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+ MRI->setType(InstReg, LLT::scalar(32));
+ MachineInstrBuilder MIB =
+ MIRBuilder.buildInstr(SPIRV::OpExtInst)
+ .addDef(InstReg)
+ .addUse(GR->getSPIRVTypeID(VoidTy))
+ .addImm(SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)
+ .addImm(Inst);
+ for (const auto Idx : Ids) {
+ MIB.addUse(Registers[Idx]);
+ }
+ MIB.constrainAllUses(*TII, *TRI, *RBI);
+ GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MIRBuilder.getMF());
+ return InstReg;
}
- Instructions.emplace_back(DebugTypeContainer<T>::TM, ConcreteIdx);
- Registers.emplace_back(
- emitDIInstruction(DebugTypeContainer<T>::Inst, Args, MIRBuilder, TM));
- DebugTypeContainer<T>::Back.emplace_back(Instructions.size() - 1);
- return Instructions.size() - 1;
-}
+
+public:
+ size_t push(const int64_t Val, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ auto &SV = value<int64_t>();
+ const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+ if (IsDuplicate) {
+ return back<int64_t>()[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<int64_t>::TM, ConcreteIdx);
+ SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
+ const SPIRVType *I32Ty = GR->getOrCreateSPIRVType(
+ Type::getInt32Ty(MIRBuilder.getContext()), MIRBuilder);
+ Registers.emplace_back(GR->buildConstantInt(Val, MIRBuilder, I32Ty, false));
+ back<int64_t>().emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+ }
+
+ size_t push(const StringRef Val, MachineIRBuilder &MIRBuilder) {
+ auto &SV = value<StringRef>();
+ const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+ if (IsDuplicate) {
+ return back<StringRef>()[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<StringRef>::TM, ConcreteIdx);
+ Registers.emplace_back(emitOpString(Val, MIRBuilder));
+ back<StringRef>().emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+ }
+
+ template <typename T>
+ constexpr size_t push(ArrayRef<size_t> Args, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ auto &SV = value<T>();
+ const auto [ConcreteIdx, IsDuplicate] = helper(T(Args), SV);
+ if (IsDuplicate) {
+ return back<T>()[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<T>::TM, ConcreteIdx);
+ Registers.emplace_back(
+ emitDIInstruction(DebugTypeContainer<T>::Inst, Args, MIRBuilder, TM));
+ back<T>().emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+ }
+};
template <>
-size_t push<DebugInfoNone>(ArrayRef<size_t>, MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+size_t LiveRepository::push<DebugInfoNone>(ArrayRef<size_t>,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
static std::optional<size_t> DebugInfoNoneIdx = std::nullopt;
if (!DebugInfoNoneIdx.has_value()) {
Instructions.emplace_back(DebugTypeContainer<DebugInfoNone>::TM, 0);
@@ -388,33 +374,17 @@ size_t push<DebugInfoNone>(ArrayRef<size_t>, MachineIRBuilder &MIRBuilder,
return DebugInfoNoneIdx.value();
}
-void cleanup() {
- DebugTypeContainer<int64_t>::Value.clear();
- DebugTypeContainer<StringRef>::Value.clear();
- DebugTypeContainer<DebugSource>::Value.clear();
- DebugTypeContainer<DebugCompilationUnit>::Value.clear();
- DebugTypeContainer<DebugTypeBasic>::Value.clear();
- DebugTypeContainer<DebugTypePointer>::Value.clear();
- DebugTypeContainer<DebugLine>::Value.clear();
-
- DebugTypeContainer<int64_t>::Back.clear();
- DebugTypeContainer<StringRef>::Back.clear();
- DebugTypeContainer<DebugSource>::Back.clear();
- DebugTypeContainer<DebugCompilationUnit>::Back.clear();
- DebugTypeContainer<DebugTypeBasic>::Back.clear();
- DebugTypeContainer<DebugTypePointer>::Back.clear();
- DebugTypeContainer<DebugLine>::Back.clear();
-}
-
-size_t emitDebugSource(const DIFile *File, MachineIRBuilder &MIRBuilder, SPIRVTargetMachine *TM) {
+size_t emitDebugSource(const DIFile *File, MachineIRBuilder &MIRBuilder,
+ SPIRVTargetMachine *TM, LiveRepository &LR) {
SmallString<128> FilePath;
sys::path::append(FilePath, File->getDirectory(), File->getFilename());
- const size_t FilePathId = push(StringRef(FilePath.c_str()), MIRBuilder);
- return push<DebugSource>({FilePathId}, MIRBuilder, TM);
+ const size_t FilePathId = LR.push(StringRef(FilePath.c_str()), MIRBuilder);
+ return LR.push<DebugSource>({FilePathId}, MIRBuilder, TM);
}
size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+ const SPIRVTargetMachine *TM,
+ LiveRepository &LR) {
std::optional<size_t> DwarfVersionId = std::nullopt;
std::optional<size_t> DebugInfoVersionId = std::nullopt;
const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
@@ -425,13 +395,13 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
cast<ConstantInt>(
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
->getSExtValue();
- DwarfVersionId = push(DwarfVersion, MIRBuilder, TM);
+ DwarfVersionId = LR.push(DwarfVersion, MIRBuilder, TM);
} else if (MaybeStrOp.equalsStr("Debug Info Version")) {
const int64_t DebugInfoVersion =
cast<ConstantInt>(
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
->getSExtValue();
- DebugInfoVersionId = push(DebugInfoVersion, MIRBuilder, TM);
+ DebugInfoVersionId = LR.push(DebugInfoVersion, MIRBuilder, TM);
}
}
@@ -442,9 +412,10 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
SmallString<128> FilePath;
sys::path::append(FilePath, File->getDirectory(), File->getFilename());
- const size_t FilePathId = push(StringRef(FilePath.c_str()), MIRBuilder);
+ const size_t FilePathId =
+ LR.push(StringRef(FilePath.c_str()), MIRBuilder);
const size_t DebugSourceId =
- push<DebugSource>({FilePathId}, MIRBuilder, TM);
+ LR.push<DebugSource>({FilePathId}, MIRBuilder, TM);
SourceLanguage SpirvSourceLanguage;
switch (CompileUnit->getSourceLanguage()) {
@@ -473,10 +444,12 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
SpirvSourceLanguage = SourceLanguage::Unknown;
}
- size_t SpirvSourceLanguageId = push(SpirvSourceLanguage, MIRBuilder, TM);
- push<DebugCompilationUnit>({DebugInfoVersionId.value(), DwarfVersionId.value(),
- DebugSourceId, SpirvSourceLanguageId},
- MIRBuilder, TM);
+ const size_t SpirvSourceLanguageId =
+ LR.push(SpirvSourceLanguage, MIRBuilder, TM);
+ LR.push<DebugCompilationUnit>({DebugInfoVersionId.value(),
+ DwarfVersionId.value(), DebugSourceId,
+ SpirvSourceLanguageId},
+ MIRBuilder, TM);
}
}
return 0;
@@ -484,11 +457,12 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+ const SPIRVTargetMachine *TM, LiveRepository &LR) {
- const size_t BasicTypeStrId = push(BT->getName(), MIRBuilder);
+ const size_t BasicTypeStrId = LR.push(BT->getName(), MIRBuilder);
- const size_t ConstIntBitWidthId = push(BT->getSizeInBits(), MIRBuilder, TM);
+ const size_t ConstIntBitWidthId =
+ LR.push(BT->getSizeInBits(), MIRBuilder, TM);
uint64_t AttributeEncoding;
switch (BT->getEncoding()) {
@@ -517,9 +491,9 @@ size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
}
- const size_t AttributeEncodingId = push(AttributeEncoding, MIRBuilder, TM);
+ const size_t AttributeEncodingId = LR.push(AttributeEncoding, MIRBuilder, TM);
- return push<DebugTypeBasic>(
+ return LR.push<DebugTypeBasic>(
{BasicTypeStrId, ConstIntBitWidthId, AttributeEncodingId, I32ZeroIdx},
MIRBuilder, TM);
}
@@ -527,38 +501,76 @@ size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t BasicTypeIdx,
const size_t I32ZeroIdx,
MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+ const SPIRVTargetMachine *TM, LiveRepository &LR) {
assert(DT->getDWARFAddressSpace().has_value());
size_t StorageClassIdx =
- push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
- *TM->getSubtargetImpl()),
- MIRBuilder, TM);
+ LR.push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+ *TM->getSubtargetImpl()),
+ MIRBuilder, TM);
- return push<DebugTypePointer>({BasicTypeIdx, StorageClassIdx, I32ZeroIdx},
- MIRBuilder, TM);
+ return LR.push<DebugTypePointer>({BasicTypeIdx, StorageClassIdx, I32ZeroIdx},
+ MIRBuilder, TM);
}
size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t I32ZeroIdx,
MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+ const SPIRVTargetMachine *TM, LiveRepository &LR) {
assert(DT->getDWARFAddressSpace().has_value());
size_t StorageClassIdx =
- push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
- *TM->getSubtargetImpl()),
- MIRBuilder, TM);
+ LR.push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+ *TM->getSubtargetImpl()),
+ MIRBuilder, TM);
// If the Pointer is representing a void type it's getBaseType
// is a nullptr
- size_t DebugInfoNoneIdx = push<DebugInfoNone>({}, MIRBuilder, TM);
- return push<DebugTypePointer>({DebugInfoNoneIdx, StorageClassIdx, I32ZeroIdx},
- MIRBuilder, TM);
+ size_t DebugInfoNoneIdx = LR.push<DebugInfoNone>({}, MIRBuilder, TM);
+ return LR.push<DebugTypePointer>(
+ {DebugInfoNoneIdx, StorageClassIdx, I32ZeroIdx}, MIRBuilder, TM);
}
} // namespace
-bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
- const Module *M) const {
+namespace llvm {
+struct SPIRVEmitNonSemanticDI : MachineFunctionPass {
+ static char ID;
+ SPIRVTargetMachine *TM = nullptr;
+ SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM);
+ SPIRVEmitNonSemanticDI();
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+private:
+ bool IsGlobalDIEmitted = false;
+ bool emitGlobalDI(MachineFunction &MF, const Module *M,
+ LiveRepository &LR) const;
+ bool emitLineDI(MachineFunction &MF, LiveRepository &LR) const;
+};
+} // namespace llvm
+
+using namespace llvm;
+
+INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE,
+ "SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false)
+
+char SPIRVEmitNonSemanticDI::ID = 0;
+
+MachineFunctionPass *
+llvm::createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) {
+ return new SPIRVEmitNonSemanticDI(TM);
+}
+
+SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM)
+ : MachineFunctionPass(ID), TM(TM) {
+ initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
+}
+
+SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
+ initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
+}
+
+bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF, const Module *M,
+ LiveRepository &LR) const {
MachineBasicBlock &MBB = *MF.begin();
// To correct placement of a OpLabel instruction during SPIRVAsmPrinter
@@ -566,7 +578,7 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
// and before first terminator
MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
- emitDebugCompilationUnits(M, MIRBuilder, TM);
+ emitDebugCompilationUnits(M, MIRBuilder, TM, LR);
for (auto &F : *M) {
for (auto &BB : F) {
@@ -577,8 +589,8 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
dyn_cast<DIBasicType>(LocalVariable->getType())) {
// We aren't extracting any DebugInfoFlags now so we're
// emitting zero to use as <id>Flags argument for DebugBasicType
- const size_t I32ZeroIdx = push(0, MIRBuilder, TM);
- emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM);
+ const size_t I32ZeroIdx = LR.push(0, MIRBuilder, TM);
+ emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM, LR);
continue;
}
// Beware else if here. Types from previous scopes are
@@ -586,7 +598,7 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
if (const auto *DerivedType =
dyn_cast<DIDerivedType>(LocalVariable->getType())) {
if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
- const size_t I32ZeroIdx = push(0, MIRBuilder, TM);
+ const size_t I32ZeroIdx = LR.push(0, MIRBuilder, TM);
// DIBasicType can be unreachable from DbgRecord and only
// pointed on from other DI types
// DerivedType->getBaseType is null when pointer
@@ -594,12 +606,13 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
if (DerivedType->getBaseType()) {
const auto *BasicType =
cast<DIBasicType>(DerivedType->getBaseType());
- const size_t BTIdx =
- emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM);
+ const size_t BTIdx = emitDebugTypeBasic(BasicType, I32ZeroIdx,
+ MIRBuilder, TM, LR);
emitDebugTypePointer(DerivedType, BTIdx, I32ZeroIdx, MIRBuilder,
- TM);
+ TM, LR);
} else {
- emitDebugTypePointer(DerivedType, I32ZeroIdx, MIRBuilder, TM);
+ emitDebugTypePointer(DerivedType, I32ZeroIdx, MIRBuilder, TM,
+ LR);
}
}
}
@@ -610,17 +623,19 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
return true;
}
-bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
+bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF,
+ LiveRepository &LR) const {
for (auto &MBB : MF) {
for (auto &MI : MBB) {
if (MI.isDebugValue()) {
MachineIRBuilder MIRBuilder(MBB, MI);
DebugLoc DL = MI.getDebugLoc();
const auto *File = cast<DISubprogram>(DL.getScope())->getFile();
- const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM);
- const size_t LineIdx = push(DL.getLine(), MIRBuilder, TM);
- const size_t ColIdx = push(DL.getLine(), MIRBuilder, TM);
- push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx}, MIRBuilder, TM);
+ const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM, LR);
+ const size_t LineIdx = LR.push(DL.getLine(), MIRBuilder, TM);
+ const size_t ColIdx = LR.push(DL.getLine(), MIRBuilder, TM);
+ LR.push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx},
+ MIRBuilder, TM);
}
}
}
@@ -629,6 +644,7 @@ bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
bool Res = false;
+ LiveRepository LR;
// emitGlobalDI needs to be executed only once to avoid
// emitting duplicates
if (!IsGlobalDIEmitted) {
@@ -642,9 +658,8 @@ bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
if (!DbgCu)
return false;
- Res = emitGlobalDI(MF, M);
+ Res = emitGlobalDI(MF, M, LR);
}
- Res |= emitLineDI(MF);
- cleanup();
+ Res |= emitLineDI(MF, LR);
return Res;
}
>From 931524fd67a3684678f0494d3993409de4b851dd Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Wed, 30 Oct 2024 13:13:21 +0100
Subject: [PATCH 4/7] Fixes in DebugLine and lit test
---
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 9 +-
.../CodeGen/SPIRV/debug-info/debug-line.ll | 139 ++++++++++++++++++
2 files changed, 143 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index 0e9cd7a8ee511d..fc7f288dc8a682 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -603,9 +603,8 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF, const Module *M,
// pointed on from other DI types
// DerivedType->getBaseType is null when pointer
// is representing a void type
- if (DerivedType->getBaseType()) {
- const auto *BasicType =
- cast<DIBasicType>(DerivedType->getBaseType());
+ if (const auto *BasicType = dyn_cast_if_present<DIBasicType>(
+ DerivedType->getBaseType())) {
const size_t BTIdx = emitDebugTypeBasic(BasicType, I32ZeroIdx,
MIRBuilder, TM, LR);
emitDebugTypePointer(DerivedType, BTIdx, I32ZeroIdx, MIRBuilder,
@@ -627,13 +626,13 @@ bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF,
LiveRepository &LR) const {
for (auto &MBB : MF) {
for (auto &MI : MBB) {
- if (MI.isDebugValue()) {
+ if (MI.getDebugLoc().get()) {
MachineIRBuilder MIRBuilder(MBB, MI);
DebugLoc DL = MI.getDebugLoc();
const auto *File = cast<DISubprogram>(DL.getScope())->getFile();
const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM, LR);
const size_t LineIdx = LR.push(DL.getLine(), MIRBuilder, TM);
- const size_t ColIdx = LR.push(DL.getLine(), MIRBuilder, TM);
+ const size_t ColIdx = LR.push(DL.getCol(), MIRBuilder, TM);
LR.push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx},
MIRBuilder, TM);
}
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll
new file mode 100644
index 00000000000000..ac81f7747bd137
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll
@@ -0,0 +1,139 @@
+; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info --print-after=spirv-nonsemantic-debug-info -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-MIR
+; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-MIR-DAG: [[void:%[0-9]+\:[a-z\(\)0-9]+]] = OpTypeVoid
+; CHECK-MIR-DAG: [[i32:%[0-9]+\:[a-z\(\)0-9]+]] = OpTypeInt 32, 0
+; CHECK-MIR-DAG: [[i32_1:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 1
+; CHECK-MIR-DAG: [[i32_6:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 6
+; CHECK-MIR-DAG: [[i32_10:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 10
+; CHECK-MIR-DAG: [[i32_5:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 5
+; CHECK-MIR-DAG: [[i32_3:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 3
+; CHECK-MIR-DAG: [[i32_32:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 32
+; CHECK-MIR-DAG: [[i32_4:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 4
+; CHECK-MIR-DAG: [[i32_11:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 11
+; CHECK-MIR-DAG: [[i32_2:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 2
+; CHECK-MIR-DAG: [[i32_7:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 7
+; CHECK-MIR-DAG: [[i32_14:%[0-9]+\:[a-z\(\)0-9]+]] = OpConstantI [[i32]], 14
+; CHECK-MIR-DAG: [[file_scope:%[0-9]+\:[a-z\(\)0-9]+]] = OpExtInst [[void]], 3, 35
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_1]], [[i32_1]], [[i32_14]], [[i32_14]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_2]], [[i32_2]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_2]], [[i32_2]], [[i32_11]], [[i32_11]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_3]], [[i32_3]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_4]], [[i32_4]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_5]], [[i32_5]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_6]], [[i32_6]], [[i32_10]], [[i32_10]]
+; CHECK-MIR-DAG: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_6]], [[i32_6]], [[i32_3]], [[i32_3]]
+;
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_1]], [[i32_1]], [[i32_14]], [[i32_14]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_2]], [[i32_2]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_2]], [[i32_2]], [[i32_11]], [[i32_11]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_3]], [[i32_3]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_4]], [[i32_4]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_5]], [[i32_5]], [[i32_7]], [[i32_7]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_6]], [[i32_6]], [[i32_10]], [[i32_10]]
+; CHECK-MIR-NOT: OpExtInst [[void]], 3, 103, [[file_scope]], [[i32_6]], [[i32_6]], [[i32_3]], [[i32_3]]
+
+; CHECK-SPIRV-DAG: [[nonsemantic_di:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV-DAG: [[i32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: [[void:%[0-9]+]] = OpTypeVoid
+; CHECK-SPIRV-DAG: [[i32_1:%[0-9]+]] = OpConstant [[i32]] 1
+; CHECK-SPIRV-DAG: [[i32_5:%[0-9]+]] = OpConstant [[i32]] 5
+; CHECK-SPIRV-DAG: [[i32_3:%[0-9]+]] = OpConstant [[i32]] 3
+; CHECK-SPIRV-DAG: [[i32_32:%[0-9]+]] = OpConstant [[i32]] 32
+; CHECK-SPIRV-DAG: [[i32_4:%[0-9]+]] = OpConstant [[i32]] 4
+; CHECK-SPIRV-DAG: [[i32_14:%[0-9]+]] = OpConstant [[i32]] 14
+; CHECK-SPIRV-DAG: [[i32_2:%[0-9]+]] = OpConstant [[i32]] 2
+; CHECK-SPIRV-DAG: [[i32_7:%[0-9]+]] = OpConstant [[i32]] 7
+; CHECK-SPIRV-DAG: [[i32_11:%[0-9]+]] = OpConstant [[i32]] 11
+; CHECK-SPIRV-DAG: [[i32_6:%[0-9]+]] = OpConstant [[i32]] 6
+; CHECK-SPIRV-DAG: [[i32_10:%[0-9]+]] = OpConstant [[i32]] 10
+; CHECK-SPIRV: [[file_source:%[0-9]+]] = OpExtInst [[void]] [[nonsemantic_di]] DebugSource
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_1]] [[i32_1]] [[i32_14]] [[i32_14]]
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_2]] [[i32_2]] [[i32_7]] [[i32_7]]
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_2]] [[i32_2]] [[i32_11]] [[i32_11]]
+; CHECK-SPIRV: OpLoad
+; CHECK-SPIRV: OpIAdd
+; CHECK-SPIRV: OpStore
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_3]] [[i32_3]] [[i32_7]] [[i32_7]]
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_3]] [[i32_3]] [[i32_11]] [[i32_11]]
+; CHECK-SPIRV: OpLoad
+; CHECK-SPIRV: OpIAdd
+; CHECK-SPIRV: OpStore
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_4]] [[i32_4]] [[i32_7]] [[i32_7]]
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_4]] [[i32_4]] [[i32_11]] [[i32_11]]
+; CHECK-SPIRV: OpLoad
+; CHECK-SPIRV: OpIAdd
+; CHECK-SPIRV: OpStore
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_5]] [[i32_5]] [[i32_7]] [[i32_7]]
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_5]] [[i32_5]] [[i32_11]] [[i32_11]]
+; CHECK-SPIRV: OpLoad
+; CHECK-SPIRV: OpIAdd
+; CHECK-SPIRV: OpStore
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_6]] [[i32_6]] [[i32_10]] [[i32_10]]
+; CHECK-SPIRV: OpLoad
+; CHECK-SPIRV: OpExtInst [[void]] [[nonsemantic_di]] DebugLine [[file_source]] [[i32_6]] [[i32_6]] [[i32_3]] [[i32_3]]
+
+define dso_local spir_func i32 @test(i32 noundef %a) #0 !dbg !6 {
+entry:
+ %a.addr = alloca i32, align 4
+ %b = alloca i32, align 4
+ %c = alloca i32, align 4
+ %d = alloca i32, align 4
+ %e = alloca i32, align 4
+ store i32 %a, ptr %a.addr, align 4
+ #dbg_declare(ptr %a.addr, !12, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !13)
+ #dbg_declare(ptr %b, !14, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !15)
+ %0 = load i32, ptr %a.addr, align 4, !dbg !16
+ %add = add nsw i32 %0, 1, !dbg !17
+ store i32 %add, ptr %b, align 4, !dbg !15
+ #dbg_declare(ptr %c, !18, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !19)
+ %1 = load i32, ptr %b, align 4, !dbg !20
+ %add1 = add nsw i32 %1, 1, !dbg !21
+ store i32 %add1, ptr %c, align 4, !dbg !19
+ #dbg_declare(ptr %d, !22, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !23)
+ %2 = load i32, ptr %c, align 4, !dbg !24
+ %add2 = add nsw i32 %2, 1, !dbg !25
+ store i32 %add2, ptr %d, align 4, !dbg !23
+ #dbg_declare(ptr %e, !26, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !27)
+ %3 = load i32, ptr %d, align 4, !dbg !28
+ %add3 = add nsw i32 %3, 1, !dbg !29
+ store i32 %add3, ptr %e, align 4, !dbg !27
+ %4 = load i32, ptr %e, align 4, !dbg !30
+ ret i32 %4, !dbg !31
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version XX.X.Xgit (GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG 9999999999999999999999999999999999999999)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "YYYYYYY", directory: "/XXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXX/XXXXXXXXXXX", checksumkind: CSK_MD5, checksum: "66666666666666666666666666666666")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!6 = distinct !DISubprogram(name: "test", scope: !7, file: !7, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !11)
+!7 = !DIFile(filename: "ZZZZZ", directory: "YYYYYYYYY/YYYYYYYYYYYY/YYYYYYYYYYYYY/YYYYYYYYY", checksumkind: CSK_MD5, checksum: "77777777777777777777777777777777")
+!8 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{}
+!12 = !DILocalVariable(name: "a", arg: 1, scope: !6, file: !7, line: 1, type: !10)
+!13 = !DILocation(line: 1, column: 14, scope: !6)
+!14 = !DILocalVariable(name: "b", scope: !6, file: !7, line: 2, type: !10)
+!15 = !DILocation(line: 2, column: 7, scope: !6)
+!16 = !DILocation(line: 2, column: 11, scope: !6)
+!17 = !DILocation(line: 2, column: 13, scope: !6)
+!18 = !DILocalVariable(name: "c", scope: !6, file: !7, line: 3, type: !10)
+!19 = !DILocation(line: 3, column: 7, scope: !6)
+!20 = !DILocation(line: 3, column: 11, scope: !6)
+!21 = !DILocation(line: 3, column: 13, scope: !6)
+!22 = !DILocalVariable(name: "d", scope: !6, file: !7, line: 4, type: !10)
+!23 = !DILocation(line: 4, column: 7, scope: !6)
+!24 = !DILocation(line: 4, column: 11, scope: !6)
+!25 = !DILocation(line: 4, column: 13, scope: !6)
+!26 = !DILocalVariable(name: "e", scope: !6, file: !7, line: 5, type: !10)
+!27 = !DILocation(line: 5, column: 7, scope: !6)
+!28 = !DILocation(line: 5, column: 11, scope: !6)
+!29 = !DILocation(line: 5, column: 13, scope: !6)
+!30 = !DILocation(line: 6, column: 10, scope: !6)
+!31 = !DILocation(line: 6, column: 3, scope: !6)
>From fce71b9dea7ddf1770f410d7c73f74dff4d64303 Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Thu, 31 Oct 2024 15:48:46 +0100
Subject: [PATCH 5/7] Disable spirv-val, descriptions, renames
---
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 126 +++++++++---------
.../CodeGen/SPIRV/debug-info/debug-line.ll | 7 +-
2 files changed, 69 insertions(+), 64 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index fc7f288dc8a682..8d8d348d8c9130 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -212,8 +212,8 @@ template <> struct DebugTypeContainer<DebugLine> {
};
template <typename T> struct DebugLiveContainer {
- SmallVector<T> Value;
- SmallVector<size_t> Back;
+ SmallVector<T> Values;
+ SmallVector<size_t> BackIdx;
};
class LiveRepository {
@@ -228,46 +228,47 @@ class LiveRepository {
SmallVector<Register> Registers;
SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
- template <typename T> constexpr SmallVector<T> &value() {
+ template <typename T> constexpr SmallVector<T> &values() {
if constexpr (std::is_same_v<T, int64_t>) {
- return PrimitiveInts.Value;
+ return PrimitiveInts.Values;
} else if constexpr (std::is_same_v<T, StringRef>) {
- return PrimitiveStrings.Value;
+ return PrimitiveStrings.Values;
} else if constexpr (std::is_same_v<T, DebugLine>) {
- return DebugLines.Value;
+ return DebugLines.Values;
} else if constexpr (std::is_same_v<T, DebugSource>) {
- return DebugSources.Value;
+ return DebugSources.Values;
} else if constexpr (std::is_same_v<T, DebugCompilationUnit>) {
- return DebugCompilationUnits.Value;
+ return DebugCompilationUnits.Values;
} else if constexpr (std::is_same_v<T, DebugTypeBasic>) {
- return DebugTypeBasics.Value;
+ return DebugTypeBasics.Values;
} else if constexpr (std::is_same_v<T, DebugTypePointer>) {
- return DebugTypePointers.Value;
+ return DebugTypePointers.Values;
}
llvm_unreachable("unreachable");
}
- template <typename T> constexpr SmallVector<size_t> &back() {
+ template <typename T> constexpr SmallVector<size_t> &backIdx() {
if constexpr (std::is_same_v<T, int64_t>) {
- return PrimitiveInts.Back;
+ return PrimitiveInts.BackIdx;
} else if constexpr (std::is_same_v<T, StringRef>) {
- return PrimitiveStrings.Back;
+ return PrimitiveStrings.BackIdx;
} else if constexpr (std::is_same_v<T, DebugLine>) {
- return DebugLines.Back;
+ return DebugLines.BackIdx;
} else if constexpr (std::is_same_v<T, DebugSource>) {
- return DebugSources.Back;
+ return DebugSources.BackIdx;
} else if constexpr (std::is_same_v<T, DebugCompilationUnit>) {
- return DebugCompilationUnits.Back;
+ return DebugCompilationUnits.BackIdx;
} else if constexpr (std::is_same_v<T, DebugTypeBasic>) {
- return DebugTypeBasics.Back;
+ return DebugTypeBasics.BackIdx;
} else if constexpr (std::is_same_v<T, DebugTypePointer>) {
- return DebugTypePointers.Back;
+ return DebugTypePointers.BackIdx;
}
llvm_unreachable("unreachable");
}
template <typename T>
- static std::pair<size_t, bool> helper(T Val, SmallVectorImpl<T> &SV) {
+ static std::pair<size_t, bool>
+ emplaceOrReturnDuplicate(T Val, SmallVectorImpl<T> &SV) {
for (unsigned Idx = 0; Idx < SV.size(); ++Idx) {
if (Val == SV[Idx]) {
return {Idx, true};
@@ -318,44 +319,45 @@ class LiveRepository {
public:
size_t push(const int64_t Val, MachineIRBuilder &MIRBuilder,
const SPIRVTargetMachine *TM) {
- auto &SV = value<int64_t>();
- const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+ auto &SV = values<int64_t>();
+ const auto [ConcreteIdx, IsDuplicate] = emplaceOrReturnDuplicate(Val, SV);
if (IsDuplicate) {
- return back<int64_t>()[ConcreteIdx];
+ return backIdx<int64_t>()[ConcreteIdx];
}
Instructions.emplace_back(DebugTypeContainer<int64_t>::TM, ConcreteIdx);
SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
const SPIRVType *I32Ty = GR->getOrCreateSPIRVType(
Type::getInt32Ty(MIRBuilder.getContext()), MIRBuilder);
Registers.emplace_back(GR->buildConstantInt(Val, MIRBuilder, I32Ty, false));
- back<int64_t>().emplace_back(Instructions.size() - 1);
+ backIdx<int64_t>().emplace_back(Instructions.size() - 1);
return Instructions.size() - 1;
}
size_t push(const StringRef Val, MachineIRBuilder &MIRBuilder) {
- auto &SV = value<StringRef>();
- const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+ auto &SV = values<StringRef>();
+ const auto [ConcreteIdx, IsDuplicate] = emplaceOrReturnDuplicate(Val, SV);
if (IsDuplicate) {
- return back<StringRef>()[ConcreteIdx];
+ return backIdx<StringRef>()[ConcreteIdx];
}
Instructions.emplace_back(DebugTypeContainer<StringRef>::TM, ConcreteIdx);
Registers.emplace_back(emitOpString(Val, MIRBuilder));
- back<StringRef>().emplace_back(Instructions.size() - 1);
+ backIdx<StringRef>().emplace_back(Instructions.size() - 1);
return Instructions.size() - 1;
}
template <typename T>
constexpr size_t push(ArrayRef<size_t> Args, MachineIRBuilder &MIRBuilder,
const SPIRVTargetMachine *TM) {
- auto &SV = value<T>();
- const auto [ConcreteIdx, IsDuplicate] = helper(T(Args), SV);
+ auto &SV = values<T>();
+ const auto [ConcreteIdx, IsDuplicate] =
+ emplaceOrReturnDuplicate(T(Args), SV);
if (IsDuplicate) {
- return back<T>()[ConcreteIdx];
+ return backIdx<T>()[ConcreteIdx];
}
Instructions.emplace_back(DebugTypeContainer<T>::TM, ConcreteIdx);
Registers.emplace_back(
emitDIInstruction(DebugTypeContainer<T>::Inst, Args, MIRBuilder, TM));
- back<T>().emplace_back(Instructions.size() - 1);
+ backIdx<T>().emplace_back(Instructions.size() - 1);
return Instructions.size() - 1;
}
};
@@ -404,7 +406,7 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
DebugInfoVersionId = LR.push(DebugInfoVersion, MIRBuilder, TM);
}
}
-
+ assert(DwarfVersionId.has_value() && DebugInfoVersionId.has_value());
const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
for (const auto *Op : DbgCu->operands()) {
if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
@@ -522,9 +524,6 @@ size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t I32ZeroIdx,
LR.push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
*TM->getSubtargetImpl()),
MIRBuilder, TM);
-
- // If the Pointer is representing a void type it's getBaseType
- // is a nullptr
size_t DebugInfoNoneIdx = LR.push<DebugInfoNone>({}, MIRBuilder, TM);
return LR.push<DebugTypePointer>(
{DebugInfoNoneIdx, StorageClassIdx, I32ZeroIdx}, MIRBuilder, TM);
@@ -573,9 +572,9 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF, const Module *M,
LiveRepository &LR) const {
MachineBasicBlock &MBB = *MF.begin();
- // To correct placement of a OpLabel instruction during SPIRVAsmPrinter
- // emission all new instructions needs to be placed after OpFunction
- // and before first terminator
+ // To ensure correct placement of an OpLabel instruction during
+ // SPIRVAsmPrinter emission, all new instructions must be positioned after
+ // OpFunction and before the first terminator.
MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
emitDebugCompilationUnits(M, MIRBuilder, TM, LR);
@@ -587,22 +586,20 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF, const Module *M,
const DILocalVariable *LocalVariable = DVR.getVariable();
if (const auto *BasicType =
dyn_cast<DIBasicType>(LocalVariable->getType())) {
- // We aren't extracting any DebugInfoFlags now so we're
- // emitting zero to use as <id>Flags argument for DebugBasicType
+ // Currently, we are not extracting any DebugInfoFlags,
+ // so we emit zero as the <id>Flags argument for DebugBasicType.
const size_t I32ZeroIdx = LR.push(0, MIRBuilder, TM);
emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM, LR);
continue;
}
- // Beware else if here. Types from previous scopes are
- // counterintuitively still visible for the next ifs scopes.
if (const auto *DerivedType =
dyn_cast<DIDerivedType>(LocalVariable->getType())) {
if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
const size_t I32ZeroIdx = LR.push(0, MIRBuilder, TM);
- // DIBasicType can be unreachable from DbgRecord and only
- // pointed on from other DI types
- // DerivedType->getBaseType is null when pointer
- // is representing a void type
+ // DIBasicType may be unreachable from DbgRecord and can only be
+ // referenced by other Debug Information (DI) types. Note:
+ // DerivedType->getBaseType returns null when the pointer
+ // represents a void type.
if (const auto *BasicType = dyn_cast_if_present<DIBasicType>(
DerivedType->getBaseType())) {
const size_t BTIdx = emitDebugTypeBasic(BasicType, I32ZeroIdx,
@@ -642,23 +639,26 @@ bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF,
}
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
- bool Res = false;
- LiveRepository LR;
- // emitGlobalDI needs to be executed only once to avoid
- // emitting duplicates
- if (!IsGlobalDIEmitted) {
- if (MF.begin() == MF.end()) {
- return false;
+ if (MF.begin() == MF.end()) {
+ return false;
+ }
+ static bool IsDIInModule = true;
+ bool IsFunctionModified = false;
+ if (IsDIInModule) {
+ LiveRepository LR;
+ // emitGlobalDI should be executed only once to prevent
+ // the emission of duplicate entries.
+ if (!IsGlobalDIEmitted) {
+ IsGlobalDIEmitted = true;
+ const MachineModuleInfo &MMI =
+ getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+ const Module *M = MMI.getModule();
+ const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
+ if (!DbgCu)
+ IsDIInModule = false;
+ IsFunctionModified = emitGlobalDI(MF, M, LR);
}
- IsGlobalDIEmitted = true;
- const MachineModuleInfo &MMI =
- getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
- const Module *M = MMI.getModule();
- const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
- if (!DbgCu)
- return false;
- Res = emitGlobalDI(MF, M, LR);
+ IsFunctionModified |= emitLineDI(MF, LR);
}
- Res |= emitLineDI(MF, LR);
- return Res;
+ return IsFunctionModified;
}
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll
index ac81f7747bd137..58f09ef43a3c36 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-line.ll
@@ -1,6 +1,11 @@
; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info --print-after=spirv-nonsemantic-debug-info -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-MIR
; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
-; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+;
+; TODO: spirv-val emits "line 42: NonSemantic.Shader.DebugInfo.100 DebugCompilationUnit:
+; expected operand Language must be a result id of 32-bit unsigned OpConstant" that's because
+; OpConstant with zero is substituted by OpConstantNull in resulting SPIR-V output. It's unrelated
+; to debug-info.
+; DISABLED: %if spirv-tools %{ llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; CHECK-MIR-DAG: [[void:%[0-9]+\:[a-z\(\)0-9]+]] = OpTypeVoid
; CHECK-MIR-DAG: [[i32:%[0-9]+\:[a-z\(\)0-9]+]] = OpTypeInt 32, 0
>From c2c97f05eecb1e6a6ddcb1e639f9ba4fe7e09f03 Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Mon, 4 Nov 2024 16:29:34 +0100
Subject: [PATCH 6/7] Fixes and asserts
---
llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index 8d8d348d8c9130..4484eda072765e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -621,21 +621,24 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF, const Module *M,
bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF,
LiveRepository &LR) const {
+ bool IsModified = false;
for (auto &MBB : MF) {
for (auto &MI : MBB) {
if (MI.getDebugLoc().get()) {
MachineIRBuilder MIRBuilder(MBB, MI);
DebugLoc DL = MI.getDebugLoc();
+ assert(DL.getScope() && "DL.getScope() must exist and be DISubprogram");
const auto *File = cast<DISubprogram>(DL.getScope())->getFile();
const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM, LR);
const size_t LineIdx = LR.push(DL.getLine(), MIRBuilder, TM);
const size_t ColIdx = LR.push(DL.getCol(), MIRBuilder, TM);
LR.push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx},
MIRBuilder, TM);
+ IsModified = true;
}
}
}
- return false;
+ return IsModified;
}
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
@@ -653,9 +656,10 @@ bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
const MachineModuleInfo &MMI =
getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
const Module *M = MMI.getModule();
- const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
- if (!DbgCu)
+ if (!M || !M->getNamedMetadata("llvm.dbg.cu")) {
IsDIInModule = false;
+ return false;
+ }
IsFunctionModified = emitGlobalDI(MF, M, LR);
}
IsFunctionModified |= emitLineDI(MF, LR);
>From d951b81adb4998bd9922dde45d49582e768a49dc Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Tue, 5 Nov 2024 14:03:32 +0100
Subject: [PATCH 7/7] class and method descriptions
---
.../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 183 ++++++++++++++----
1 file changed, 141 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index 4484eda072765e..90d629210e75b4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -215,7 +215,46 @@ template <typename T> struct DebugLiveContainer {
SmallVector<T> Values;
SmallVector<size_t> BackIdx;
};
-
+/// @class LiveRepository
+/// @brief Container for the connection graph between newly emitted Debug
+/// instructions.
+///
+/// The architecture consists of two tiers:
+/// - The **Main tier**, represented by an array of `Instructions`.
+/// - The **Concrete Type tier**, represented by separate arrays for each
+/// corresponding debug type.
+///
+/// The `Instructions` array contains records that include:
+/// - `Type`: An enum value pointing to the specific debug type array in the
+/// Concrete Type tier.
+/// - `Id`: An index into the corresponding array in the Concrete Type tier.
+///
+/// The class is designed to ensure safe and controlled access to its internal
+/// state. All interactions with the repository are done through the
+/// `getOrCreateIdx` function, which restricts direct manipulation of the
+/// underlying data structures, thus minimizing the risk of memory errors or
+/// logical mistakes.
+///
+/// Users of this class interact exclusively with the indexes of the
+/// `Instructions` array and never directly access the internal concrete type
+/// arrays. This property flattens the instruction access,
+// making it easily retrievable.
+///
+///
+/// getOrCreateIdx() <--+ Iidx
+/// V |
+/// +-------------------------+-+
+/// |[Instructions]--{Cidx,Type}|<----+
+/// +------+--------------+-----+ |
+/// v v |
+/// [PrimitiveType] [ConcreteType_0] |
+/// {Data} {Instruction} |
+/// (i32)(i32) (Iidx) (Iidx) |
+/// | | |
+/// +----+-----+
+///
+/// Class is designed to be easily removable by simply replacing the
+/// `getOrConstructIdx` method with another mechanism.
class LiveRepository {
DebugLiveContainer<int64_t> PrimitiveInts;
DebugLiveContainer<StringRef> PrimitiveStrings;
@@ -317,8 +356,26 @@ class LiveRepository {
}
public:
- size_t push(const int64_t Val, MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+ /// @brief Retrieves or creates an index for the int64_t primitive type.
+ ///
+ /// It's backed by OpConstantI instruction.
+ /// It either retrieves an existing index or creates a new one based on the
+ /// provided parameters. The function currently has a linear, cache-friendly
+ /// search time for duplicate entries. It assumes that no single type of
+ /// instruction will become so dominant in the module and every entry of that
+ /// type will be unique.
+ ///
+ /// @param[in] Val A int64_t value to retreive or construct.
+ /// @param[in] MIRBuilder A reference to the `MachineIRBuilder` used for
+ /// constructing IR.
+ /// @param[in] TM A pointer to the target machine (`SPIRVTargetMachine`) used
+ /// for this operation.
+ ///
+ /// @return The index (`size_t`) of the retrieved duplicate or newly created
+ /// entry.
+ ///
+ size_t getOrCreateIdx(const int64_t Val, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
auto &SV = values<int64_t>();
const auto [ConcreteIdx, IsDuplicate] = emplaceOrReturnDuplicate(Val, SV);
if (IsDuplicate) {
@@ -333,7 +390,25 @@ class LiveRepository {
return Instructions.size() - 1;
}
- size_t push(const StringRef Val, MachineIRBuilder &MIRBuilder) {
+ /// @brief Retrieves or creates an index for the StringRef primitive type.
+ ///
+ /// It's backed by OpString instruction.
+ /// It either retrieves an existing index or creates a new one based on the
+ /// provided parameters. The function currently has a linear, cache-friendly
+ /// search time for duplicate entries. It assumes that no single type of
+ /// instruction will become so dominant in the module and every entry of that
+ /// type will be unique.
+ ///
+ /// @param[in] Val A StringRef value to retreive or construct.
+ /// @param[in] MIRBuilder A reference to the `MachineIRBuilder` used for
+ /// constructing IR.
+ /// @param[in] TM A pointer to the target machine (`SPIRVTargetMachine`) used
+ /// for this operation.
+ ///
+ /// @return The index (`size_t`) of the retrieved duplicate or newly created
+ /// entry.
+ ///
+ size_t getOrCreateIdx(const StringRef Val, MachineIRBuilder &MIRBuilder) {
auto &SV = values<StringRef>();
const auto [ConcreteIdx, IsDuplicate] = emplaceOrReturnDuplicate(Val, SV);
if (IsDuplicate) {
@@ -345,9 +420,29 @@ class LiveRepository {
return Instructions.size() - 1;
}
+ /// @brief Retrieves or creates an index for the specified type.
+ /// It either retrieves an existing index or creates a new one based on the
+ /// provided parameters. The function currently has a linear, cache-friendly
+ /// search time for duplicate entries. It assumes that no single type of
+ /// instruction will become so dominant in the module and every entry of that
+ /// type will be unique.:w
+ ///
+ /// @tparam T The specific type being used for this instantiation.
+ ///
+ /// @param[in] arrayRef A reference to an array containing indices (of type
+ /// `size_t`).
+ /// @param[in] MIRBuilder A reference to the `MachineIRBuilder` used for
+ /// constructing IR.
+ /// @param[in] TM A pointer to the target machine (`SPIRVTargetMachine`) used
+ /// for this operation.
+ ///
+ /// @return The index (`size_t`) of the retrieved duplicate or newly created
+ /// entry.
+ ///
template <typename T>
- constexpr size_t push(ArrayRef<size_t> Args, MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+ constexpr size_t getOrCreateIdx(ArrayRef<size_t> Args,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
auto &SV = values<T>();
const auto [ConcreteIdx, IsDuplicate] =
emplaceOrReturnDuplicate(T(Args), SV);
@@ -363,9 +458,10 @@ class LiveRepository {
};
template <>
-size_t LiveRepository::push<DebugInfoNone>(ArrayRef<size_t>,
- MachineIRBuilder &MIRBuilder,
- const SPIRVTargetMachine *TM) {
+size_t
+LiveRepository::getOrCreateIdx<DebugInfoNone>(ArrayRef<size_t>,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
static std::optional<size_t> DebugInfoNoneIdx = std::nullopt;
if (!DebugInfoNoneIdx.has_value()) {
Instructions.emplace_back(DebugTypeContainer<DebugInfoNone>::TM, 0);
@@ -380,8 +476,9 @@ size_t emitDebugSource(const DIFile *File, MachineIRBuilder &MIRBuilder,
SPIRVTargetMachine *TM, LiveRepository &LR) {
SmallString<128> FilePath;
sys::path::append(FilePath, File->getDirectory(), File->getFilename());
- const size_t FilePathId = LR.push(StringRef(FilePath.c_str()), MIRBuilder);
- return LR.push<DebugSource>({FilePathId}, MIRBuilder, TM);
+ const size_t FilePathId =
+ LR.getOrCreateIdx(StringRef(FilePath.c_str()), MIRBuilder);
+ return LR.getOrCreateIdx<DebugSource>({FilePathId}, MIRBuilder, TM);
}
size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
@@ -397,13 +494,13 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
cast<ConstantInt>(
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
->getSExtValue();
- DwarfVersionId = LR.push(DwarfVersion, MIRBuilder, TM);
+ DwarfVersionId = LR.getOrCreateIdx(DwarfVersion, MIRBuilder, TM);
} else if (MaybeStrOp.equalsStr("Debug Info Version")) {
const int64_t DebugInfoVersion =
cast<ConstantInt>(
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
->getSExtValue();
- DebugInfoVersionId = LR.push(DebugInfoVersion, MIRBuilder, TM);
+ DebugInfoVersionId = LR.getOrCreateIdx(DebugInfoVersion, MIRBuilder, TM);
}
}
assert(DwarfVersionId.has_value() && DebugInfoVersionId.has_value());
@@ -415,9 +512,9 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
sys::path::append(FilePath, File->getDirectory(), File->getFilename());
const size_t FilePathId =
- LR.push(StringRef(FilePath.c_str()), MIRBuilder);
+ LR.getOrCreateIdx(StringRef(FilePath.c_str()), MIRBuilder);
const size_t DebugSourceId =
- LR.push<DebugSource>({FilePathId}, MIRBuilder, TM);
+ LR.getOrCreateIdx<DebugSource>({FilePathId}, MIRBuilder, TM);
SourceLanguage SpirvSourceLanguage;
switch (CompileUnit->getSourceLanguage()) {
@@ -447,11 +544,11 @@ size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
}
const size_t SpirvSourceLanguageId =
- LR.push(SpirvSourceLanguage, MIRBuilder, TM);
- LR.push<DebugCompilationUnit>({DebugInfoVersionId.value(),
- DwarfVersionId.value(), DebugSourceId,
- SpirvSourceLanguageId},
- MIRBuilder, TM);
+ LR.getOrCreateIdx(SpirvSourceLanguage, MIRBuilder, TM);
+ LR.getOrCreateIdx<DebugCompilationUnit>(
+ {DebugInfoVersionId.value(), DwarfVersionId.value(), DebugSourceId,
+ SpirvSourceLanguageId},
+ MIRBuilder, TM);
}
}
return 0;
@@ -461,10 +558,10 @@ size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
MachineIRBuilder &MIRBuilder,
const SPIRVTargetMachine *TM, LiveRepository &LR) {
- const size_t BasicTypeStrId = LR.push(BT->getName(), MIRBuilder);
+ const size_t BasicTypeStrId = LR.getOrCreateIdx(BT->getName(), MIRBuilder);
const size_t ConstIntBitWidthId =
- LR.push(BT->getSizeInBits(), MIRBuilder, TM);
+ LR.getOrCreateIdx(BT->getSizeInBits(), MIRBuilder, TM);
uint64_t AttributeEncoding;
switch (BT->getEncoding()) {
@@ -493,9 +590,10 @@ size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
}
- const size_t AttributeEncodingId = LR.push(AttributeEncoding, MIRBuilder, TM);
+ const size_t AttributeEncodingId =
+ LR.getOrCreateIdx(AttributeEncoding, MIRBuilder, TM);
- return LR.push<DebugTypeBasic>(
+ return LR.getOrCreateIdx<DebugTypeBasic>(
{BasicTypeStrId, ConstIntBitWidthId, AttributeEncodingId, I32ZeroIdx},
MIRBuilder, TM);
}
@@ -506,13 +604,13 @@ size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t BasicTypeIdx,
const SPIRVTargetMachine *TM, LiveRepository &LR) {
assert(DT->getDWARFAddressSpace().has_value());
- size_t StorageClassIdx =
- LR.push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
- *TM->getSubtargetImpl()),
- MIRBuilder, TM);
+ size_t StorageClassIdx = LR.getOrCreateIdx(
+ addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+ *TM->getSubtargetImpl()),
+ MIRBuilder, TM);
- return LR.push<DebugTypePointer>({BasicTypeIdx, StorageClassIdx, I32ZeroIdx},
- MIRBuilder, TM);
+ return LR.getOrCreateIdx<DebugTypePointer>(
+ {BasicTypeIdx, StorageClassIdx, I32ZeroIdx}, MIRBuilder, TM);
}
size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t I32ZeroIdx,
@@ -520,12 +618,13 @@ size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t I32ZeroIdx,
const SPIRVTargetMachine *TM, LiveRepository &LR) {
assert(DT->getDWARFAddressSpace().has_value());
- size_t StorageClassIdx =
- LR.push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
- *TM->getSubtargetImpl()),
- MIRBuilder, TM);
- size_t DebugInfoNoneIdx = LR.push<DebugInfoNone>({}, MIRBuilder, TM);
- return LR.push<DebugTypePointer>(
+ size_t StorageClassIdx = LR.getOrCreateIdx(
+ addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+ *TM->getSubtargetImpl()),
+ MIRBuilder, TM);
+ size_t DebugInfoNoneIdx =
+ LR.getOrCreateIdx<DebugInfoNone>({}, MIRBuilder, TM);
+ return LR.getOrCreateIdx<DebugTypePointer>(
{DebugInfoNoneIdx, StorageClassIdx, I32ZeroIdx}, MIRBuilder, TM);
}
} // namespace
@@ -588,14 +687,14 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF, const Module *M,
dyn_cast<DIBasicType>(LocalVariable->getType())) {
// Currently, we are not extracting any DebugInfoFlags,
// so we emit zero as the <id>Flags argument for DebugBasicType.
- const size_t I32ZeroIdx = LR.push(0, MIRBuilder, TM);
+ const size_t I32ZeroIdx = LR.getOrCreateIdx(0, MIRBuilder, TM);
emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM, LR);
continue;
}
if (const auto *DerivedType =
dyn_cast<DIDerivedType>(LocalVariable->getType())) {
if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
- const size_t I32ZeroIdx = LR.push(0, MIRBuilder, TM);
+ const size_t I32ZeroIdx = LR.getOrCreateIdx(0, MIRBuilder, TM);
// DIBasicType may be unreachable from DbgRecord and can only be
// referenced by other Debug Information (DI) types. Note:
// DerivedType->getBaseType returns null when the pointer
@@ -630,10 +729,10 @@ bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF,
assert(DL.getScope() && "DL.getScope() must exist and be DISubprogram");
const auto *File = cast<DISubprogram>(DL.getScope())->getFile();
const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM, LR);
- const size_t LineIdx = LR.push(DL.getLine(), MIRBuilder, TM);
- const size_t ColIdx = LR.push(DL.getCol(), MIRBuilder, TM);
- LR.push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx},
- MIRBuilder, TM);
+ const size_t LineIdx = LR.getOrCreateIdx(DL.getLine(), MIRBuilder, TM);
+ const size_t ColIdx = LR.getOrCreateIdx(DL.getCol(), MIRBuilder, TM);
+ LR.getOrCreateIdx<DebugLine>(
+ {ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx}, MIRBuilder, TM);
IsModified = true;
}
}
More information about the llvm-commits
mailing list