1 //===- SPIRVToLLVMDbgTran.h - Converts SPIR-V DebugInfo to LLVM -*- C++ -*-===//
2 //
3 //                     The LLVM/SPIR-V Translator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // Copyright (c) 2018 Intel Corporation. All rights reserved.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal with the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimers.
19 // Redistributions in binary form must reproduce the above copyright notice,
20 // this list of conditions and the following disclaimers in the documentation
21 // and/or other materials provided with the distribution.
22 // Neither the names of Intel Corporation, nor the names of its
23 // contributors may be used to endorse or promote products derived from this
24 // Software without specific prior written permission.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
31 // THE SOFTWARE.
32 //
33 //===----------------------------------------------------------------------===//
34 //
35 // This file implements translation of debug info from SPIR-V to LLVM metadata
36 //
37 //===----------------------------------------------------------------------===//
38 
39 #ifndef SPIRVTOLLVMDBGTRAN_H
40 #define SPIRVTOLLVMDBGTRAN_H
41 
42 #include "SPIRVInstruction.h"
43 
44 #include "llvm/IR/DIBuilder.h"
45 #include "llvm/IR/DebugLoc.h"
46 
47 #include <unordered_map>
48 
49 namespace llvm {
50 class Module;
51 class Value;
52 class Instruction;
53 class Type;
54 } // namespace llvm
55 using namespace llvm;
56 
57 namespace SPIRV {
58 class SPIRVToLLVM;
59 class SPIRVEntry;
60 class SPIRVFunction;
61 class SPIRVValue;
62 
63 class SPIRVToLLVMDbgTran {
64 public:
65   typedef std::vector<SPIRVWord> SPIRVWordVec;
66 
67   SPIRVToLLVMDbgTran(SPIRVModule *TBM, Module *TM, SPIRVToLLVM *Reader);
68   void addDbgInfoVersion();
69   void transDbgInfo(const SPIRVValue *SV, Value *V);
70   template <typename T = MDNode>
transDebugInst(const SPIRVExtInst * DebugInst)71   T *transDebugInst(const SPIRVExtInst *DebugInst) {
72     assert((DebugInst->getExtSetKind() == SPIRVEIS_Debug ||
73             DebugInst->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100) &&
74            "Unexpected extended instruction set");
75     auto It = DebugInstCache.find(DebugInst);
76     if (It != DebugInstCache.end())
77       return static_cast<T *>(It->second);
78     MDNode *Res = transDebugInstImpl(DebugInst);
79     DebugInstCache[DebugInst] = Res;
80     return static_cast<T *>(Res);
81   }
82   Instruction *transDebugIntrinsic(const SPIRVExtInst *DebugInst,
83                                    BasicBlock *BB);
84   void finalize();
85 
86 private:
87   DIFile *getFile(const SPIRVId SourceId);
88   DIFile *getDIFile(const std::string &FileName,
89                     Optional<DIFile::ChecksumInfo<StringRef>> CS = None);
90   DIFile *getDIFile(const SPIRVEntry *E);
91   unsigned getLineNo(const SPIRVEntry *E);
92 
93   MDNode *transDebugInstImpl(const SPIRVExtInst *DebugInst);
94 
95   llvm::DebugLoc transDebugLocation(const SPIRVExtInst *DebugInst);
96 
97   llvm::DebugLoc transDebugScope(const SPIRVInstruction *Inst);
98 
99   MDNode *transDebugInlined(const SPIRVExtInst *Inst);
100 
101   DICompileUnit *transCompileUnit(const SPIRVExtInst *DebugInst);
102 
103   DIBasicType *transTypeBasic(const SPIRVExtInst *DebugInst);
104 
105   DIDerivedType *transTypeQualifier(const SPIRVExtInst *DebugInst);
106 
107   DIType *transTypePointer(const SPIRVExtInst *DebugInst);
108 
109   DICompositeType *transTypeArray(const SPIRVExtInst *DebugInst);
110 
111   DICompositeType *transTypeVector(const SPIRVExtInst *DebugInst);
112 
113   DICompositeType *transTypeComposite(const SPIRVExtInst *DebugInst);
114 
115   DINode *transTypeMember(const SPIRVExtInst *DebugInst);
116 
117   DINode *transTypeEnum(const SPIRVExtInst *DebugInst);
118 
119   DINode *transTemplateParameter(const SPIRVExtInst *DebugInst);
120   DINode *transTemplateTemplateParameter(const SPIRVExtInst *DebugInst);
121   DINode *transTemplateParameterPack(const SPIRVExtInst *DebugInst);
122 
123   MDNode *transTemplate(const SPIRVExtInst *DebugInst);
124 
125   DINode *transTypeFunction(const SPIRVExtInst *DebugInst);
126 
127   DINode *transTypePtrToMember(const SPIRVExtInst *DebugInst);
128 
129   DINode *transLexicalBlock(const SPIRVExtInst *DebugInst);
130   DINode *transLexicalBlockDiscriminator(const SPIRVExtInst *DebugInst);
131 
132   DINode *transFunction(const SPIRVExtInst *DebugInst);
133 
134   DINode *transFunctionDecl(const SPIRVExtInst *DebugInst);
135 
136   MDNode *transGlobalVariable(const SPIRVExtInst *DebugInst);
137 
138   DINode *transLocalVariable(const SPIRVExtInst *DebugInst);
139 
140   DINode *transTypedef(const SPIRVExtInst *DebugInst);
141 
142   DINode *transInheritance(const SPIRVExtInst *DebugInst);
143 
144   DINode *transImportedEntry(const SPIRVExtInst *DebugInst);
145 
146   DINode *transModule(const SPIRVExtInst *DebugInst);
147 
148   MDNode *transExpression(const SPIRVExtInst *DebugInst);
149 
150   SPIRVModule *BM;
151   Module *M;
152   DIBuilder Builder;
153   SPIRVToLLVM *SPIRVReader;
154   DICompileUnit *CU;
155   bool Enable;
156   std::unordered_map<std::string, DIFile *> FileMap;
157   std::unordered_map<SPIRVId, DISubprogram *> FuncMap;
158   std::unordered_map<const SPIRVExtInst *, MDNode *> DebugInstCache;
159 
160   struct SplitFileName {
161     SplitFileName(const std::string &FileName);
162     std::string BaseName;
163     std::string Path;
164   };
165 
166   DIScope *getScope(const SPIRVEntry *ScopeInst);
167   SPIRVExtInst *getDbgInst(const SPIRVId Id);
168 
getDbgInst(const SPIRVId Id)169   template <SPIRVWord OpCode> SPIRVExtInst *getDbgInst(const SPIRVId Id) {
170     if (SPIRVExtInst *DI = getDbgInst(Id)) {
171       if (DI->getExtOp() == OpCode) {
172         return DI;
173       }
174     }
175     return nullptr;
176   }
177   const std::string &getString(const SPIRVId Id);
178   std::string findModuleProducer();
179   Optional<DIFile::ChecksumInfo<StringRef>> ParseChecksum(StringRef Text);
180 };
181 } // namespace SPIRV
182 
183 #endif // SPIRVTOLLVMDBGTRAN_H
184