-
Notifications
You must be signed in to change notification settings - Fork 12.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SPIRV] Emitting DebugSource, DebugCompileUnit (#97558)
This commit introduces emission of DebugSource, DebugCompileUnit from NonSemantic.Shader.DebugInfo.100 and required OpString with filename. NonSemantic.Shader.DebugInfo.100 is divided, following DWARF into two main concepts – emitting DIE and Line. In DWARF .debug_abbriev and .debug_info sections are responsible for emitting tree with information (DEIs) about e.g. types, compilation unit. Corresponding to that in NonSemantic.Shader.DebugInfo.100 have instructions like DebugSource, DebugCompileUnit etc. which preforms same role in SPIR-V file. The difference is in fact that in SPIR-V there are no sections but logical layout which forces order of the instruction emission. The NonSemantic.Shader.DebugInfo.100 requires for this type of global information to be emitted after OpTypeXXX and OpConstantXXX instructions. One of the goals was to minimize changes and interaction with SPIRVModuleAnalysis as possible which current commit achieves by emitting it’s instructions directly into MachineFunction. The possibility of duplicates are mitigated by guard inside pass which emits the global information only once in one function. By that method duplicates don’t have chance to be emitted. From that point, adding new debug global instructions should be straightforward.
- Loading branch information
Showing
10 changed files
with
287 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#include "MCTargetDesc/SPIRVBaseInfo.h" | ||
#include "MCTargetDesc/SPIRVMCTargetDesc.h" | ||
#include "SPIRVGlobalRegistry.h" | ||
#include "SPIRVRegisterInfo.h" | ||
#include "SPIRVTargetMachine.h" | ||
#include "llvm/ADT/SmallString.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/IR/DebugInfoMetadata.h" | ||
#include "llvm/IR/Metadata.h" | ||
#include "llvm/PassRegistry.h" | ||
#include "llvm/Support/Casting.h" | ||
#include "llvm/Support/Path.h" | ||
|
||
#define DEBUG_TYPE "spirv-nonsemantic-debug-info" | ||
|
||
namespace llvm { | ||
struct SPIRVEmitNonSemanticDI : public MachineFunctionPass { | ||
static char ID; | ||
SPIRVTargetMachine *TM; | ||
SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM); | ||
SPIRVEmitNonSemanticDI(); | ||
|
||
bool runOnMachineFunction(MachineFunction &MF) override; | ||
|
||
private: | ||
bool IsGlobalDIEmitted = false; | ||
bool emitGlobalDI(MachineFunction &MF); | ||
}; | ||
|
||
void initializeSPIRVEmitNonSemanticDIPass(PassRegistry &); | ||
|
||
FunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) { | ||
return new SPIRVEmitNonSemanticDI(TM); | ||
} | ||
} // namespace llvm | ||
|
||
using namespace llvm; | ||
|
||
INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE, | ||
"SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false) | ||
|
||
char SPIRVEmitNonSemanticDI::ID = 0; | ||
|
||
SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM) | ||
: MachineFunctionPass(ID), TM(TM) { | ||
initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry()); | ||
} | ||
|
||
SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) { | ||
initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry()); | ||
} | ||
|
||
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; | ||
} | ||
|
||
// Required variables to get from metadata search | ||
LLVMContext *Context; | ||
SmallString<128> FilePath; | ||
unsigned SourceLanguage = 0; | ||
int64_t DwarfVersion = 0; | ||
int64_t DebugInfoVersion = 0; | ||
|
||
// 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(); | ||
sys::path::append(FilePath, File->getDirectory(), File->getFilename()); | ||
SourceLanguage = CompileUnit->getSourceLanguage(); | ||
break; | ||
} | ||
} | ||
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(); | ||
} | ||
} | ||
// 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()); | ||
|
||
// Emit OpString with FilePath which is required by DebugSource | ||
const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass); | ||
MRI.setType(StrReg, LLT::scalar(32)); | ||
MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString); | ||
MIB.addDef(StrReg); | ||
addStringImm(FilePath, MIB); | ||
|
||
const SPIRVType *VoidTy = | ||
GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder); | ||
|
||
// Emit DebugSource which is required by DebugCompilationUnit | ||
const Register DebugSourceResIdReg = | ||
MRI.createVirtualRegister(&SPIRV::IDRegClass); | ||
MRI.setType(DebugSourceResIdReg, LLT::scalar(32)); | ||
MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst) | ||
.addDef(DebugSourceResIdReg) | ||
.addUse(GR->getSPIRVTypeID(VoidTy)) | ||
.addImm(static_cast<int64_t>( | ||
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) | ||
.addImm(SPIRV::NonSemanticExtInst::DebugSource) | ||
.addUse(StrReg); | ||
MIB.constrainAllUses(*TII, *TRI, *RBI); | ||
GR->assignSPIRVTypeToVReg(VoidTy, DebugSourceResIdReg, MF); | ||
|
||
const SPIRVType *I32Ty = | ||
GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder); | ||
|
||
// Convert DwarfVersion, DebugInfo and SourceLanguage integers to OpConstant | ||
// instructions required by DebugCompilationUnit | ||
const Register DwarfVersionReg = | ||
GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false); | ||
const Register DebugInfoVersionReg = | ||
GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false); | ||
const Register SourceLanguageReg = | ||
GR->buildConstantInt(SourceLanguage, MIRBuilder, I32Ty, false); | ||
|
||
// Emit DebugCompilationUnit | ||
const Register DebugCompUnitResIdReg = | ||
MRI.createVirtualRegister(&SPIRV::IDRegClass); | ||
MRI.setType(DebugCompUnitResIdReg, LLT::scalar(32)); | ||
MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst) | ||
.addDef(DebugCompUnitResIdReg) | ||
.addUse(GR->getSPIRVTypeID(VoidTy)) | ||
.addImm(static_cast<int64_t>( | ||
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) | ||
.addImm(SPIRV::NonSemanticExtInst::DebugCompilationUnit) | ||
.addUse(DebugInfoVersionReg) | ||
.addUse(DwarfVersionReg) | ||
.addUse(DebugSourceResIdReg) | ||
.addUse(SourceLanguageReg); | ||
MIB.constrainAllUses(*TII, *TRI, *RBI); | ||
GR->assignSPIRVTypeToVReg(VoidTy, DebugCompUnitResIdReg, MF); | ||
} | ||
return true; | ||
} | ||
|
||
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) { | ||
bool Res = false; | ||
// emitGlobalDI needs to be executed only once to avoid | ||
// emitting duplicates | ||
if (!IsGlobalDIEmitted) { | ||
IsGlobalDIEmitted = true; | ||
Res = emitGlobalDI(MF); | ||
} | ||
return Res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.