//===- LLVMToSPIRVDbgTran.h - Converts LLVM DebugInfo to SPIR-V -*- C++ -*-===// // // The LLVM/SPIR-V Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2018 Intel Corporation. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal with the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimers. // Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimers in the documentation // and/or other materials provided with the distribution. // Neither the names of Intel Corporation, nor the names of its // contributors may be used to endorse or promote products derived from this // Software without specific prior written permission. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH // THE SOFTWARE. // //===----------------------------------------------------------------------===// // // This file implements translation of debug info from LLVM metadata to SPIR-V // //===----------------------------------------------------------------------===// #ifndef LLVMTOSPIRVDBGTRAN_HPP_ #define LLVMTOSPIRVDBGTRAN_HPP_ #include "SPIRVModule.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Module.h" using namespace llvm; namespace SPIRV { class LLVMToSPIRVBase; class LLVMToSPIRVDbgTran { public: typedef std::vector SPIRVWordVec; LLVMToSPIRVDbgTran(Module *TM = nullptr, SPIRVModule *TBM = nullptr, LLVMToSPIRVBase *Writer = nullptr) : BM(TBM), M(TM), SPIRVWriter(Writer), VoidT(nullptr), DebugInfoNone(nullptr) {} void transDebugMetadata(); void setModule(Module *Mod) { M = Mod; } // Mixing translation of regular instructions and debug info creates a mess. // To avoid it we translate debug info intrinsics in two steps: // 1. First time we meet debug info intrinsic during translation of a basic // block. At this time we create corresponding SPIRV debug info instruction, // but with dummy operands. Doing so we a) map llvm value to spirv value, // b) get a place for SPIRV debug info intrinsic in SPIRV basic block. // We also remember all debug intrinsics. SPIRVValue *createDebugDeclarePlaceholder(const DbgVariableIntrinsic *DbgDecl, SPIRVBasicBlock *BB); SPIRVValue *createDebugValuePlaceholder(const DbgVariableIntrinsic *DbgValue, SPIRVBasicBlock *BB); private: // 2. After translation of all regular instructions we deal with debug info. // We iterate over debug intrinsics stored on the first step, get its mapped // SPIRV instruction and tweak the operands. void finalizeDebugDeclare(const DbgVariableIntrinsic *DbgDecl); void finalizeDebugValue(const DbgVariableIntrinsic *DbgValue); // Emit DebugScope and OpLine instructions void transLocationInfo(); // Dispatcher SPIRVEntry *transDbgEntry(const MDNode *DIEntry); SPIRVEntry *transDbgEntryImpl(const MDNode *MDN); // Helper methods SPIRVType *getVoidTy(); SPIRVType *getInt32Ty(); SPIRVEntry *getScope(DIScope *SR); SPIRVEntry *getGlobalVariable(const DIGlobalVariable *GV); inline bool isNonSemanticDebugInfo(); void transformToConstant(std::vector &Ops, std::vector Idxs); // No debug info SPIRVEntry *getDebugInfoNone(); SPIRVId getDebugInfoNoneId(); // Compilation unit SPIRVEntry *transDbgCompileUnit(const DICompileUnit *CU); /// The following methods (till the end of the file) implement translation /// of debug instrtuctions described in the spec. // Types SPIRVEntry *transDbgBaseType(const DIBasicType *BT); SPIRVEntry *transDbgPointerType(const DIDerivedType *PT); SPIRVEntry *transDbgQualifiedType(const DIDerivedType *QT); SPIRVEntry *transDbgArrayType(const DICompositeType *AT); SPIRVEntry *transDbgArrayTypeOpenCL(const DICompositeType *AT); SPIRVEntry *transDbgArrayTypeNonSemantic(const DICompositeType *AT); SPIRVEntry *transDbgArrayTypeDynamic(const DICompositeType *AT); SPIRVEntry *transDbgSubrangeType(const DISubrange *ST); SPIRVEntry *transDbgStringType(const DIStringType *ST); SPIRVEntry *transDbgTypeDef(const DIDerivedType *D); SPIRVEntry *transDbgSubroutineType(const DISubroutineType *FT); SPIRVEntry *transDbgEnumType(const DICompositeType *ET); SPIRVEntry *transDbgCompositeType(const DICompositeType *CT); SPIRVEntry *transDbgMemberType(const DIDerivedType *MT); SPIRVEntry *transDbgMemberTypeOpenCL(const DIDerivedType *MT); SPIRVEntry *transDbgMemberTypeNonSemantic(const DIDerivedType *MT); SPIRVEntry *transDbgInheritance(const DIDerivedType *DT); SPIRVEntry *transDbgPtrToMember(const DIDerivedType *DT); // Templates SPIRVEntry *transDbgTemplateParams(DITemplateParameterArray TPA, const SPIRVEntry *Target); SPIRVEntry *transDbgTemplateParameter(const DITemplateParameter *TP); SPIRVEntry * transDbgTemplateTemplateParameter(const DITemplateValueParameter *TP); SPIRVEntry *transDbgTemplateParameterPack(const DITemplateValueParameter *TP); // Global objects SPIRVEntry *transDbgGlobalVariable(const DIGlobalVariable *GV); SPIRVEntry *transDbgFunction(const DISubprogram *Func); SPIRVEntry *transDbgFuncDefinition(SPIRVValue *SPVFunc, SPIRVEntry *DbgFunc); SPIRVEntry *transDbgEntryPoint(const DISubprogram *Func, SPIRVEntry *DbgFunc); // Location information SPIRVEntry *transDbgScope(const DIScope *S); SPIRVEntry *transDebugLoc(const DebugLoc &Loc, SPIRVBasicBlock *BB, SPIRVInstruction *InsertBefore = nullptr); SPIRVEntry *transDbgInlinedAt(const DILocation *D); SPIRVEntry *transDbgInlinedAtNonSemanticShader200(const DILocation *D); template SPIRVExtInst *getSource(const T *DIEntry); SPIRVEntry *transDbgFileType(const DIFile *F); // Generate instructions recording identifier and file where debug information // was split to void generateBuildIdentifierAndStoragePath(const DICompileUnit *DIEntry); // Local Variables SPIRVEntry *transDbgLocalVariable(const DILocalVariable *Var); // DWARF expressions SPIRVEntry *transDbgExpression(const DIExpression *Expr); template void transDIOpOperand(SPIRVWordVec &Vec, unsigned Idx, OperandTy Operand); // Imported declarations and modules SPIRVEntry *transDbgImportedEntry(const DIImportedEntity *IE); // A module in programming language. Example - Fortran module, clang module. SPIRVEntry *transDbgModule(const DIModule *IE); // Macros SPIRVEntry *transDbgMacroDefine(const DIMacro *Macro, SPIRVString *FileName); SPIRVEntry *transDbgMacroUndef(const DIMacro *Macro, SPIRVString *FileName); void transDbgMacros(); // Flags SPIRVWord mapDebugFlags(DINode::DIFlags DFlags); SPIRVWord transDebugFlags(const DINode *DN); SPIRVModule *BM; Module *M; LLVMToSPIRVBase *SPIRVWriter; std::unordered_map MDMap; std::unordered_map FileMap; std::unordered_map MacroDefMap; DebugInfoFinder DIF; SPIRVType *VoidT = nullptr; SPIRVType *Int32T = nullptr; SPIRVEntry *DebugInfoNone; std::unordered_map SPIRVCUMap; std::vector DbgDeclareIntrinsics; std::vector DbgValueIntrinsics; inline static SPIRVExtInst *BuildIdentifierInsn{nullptr}; inline static SPIRVExtInst *StoragePathInsn{nullptr}; }; // class LLVMToSPIRVDbgTran } // namespace SPIRV #endif // LLVMTOSPIRVDBGTRAN_HPP_