1 | //===-- SPIRVGlobalRegistry.h - SPIR-V Global Registry ----------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // SPIRVGlobalRegistry is used to maintain rich type information required for |
10 | // SPIR-V even after lowering from LLVM IR to GMIR. It can convert an llvm::Type |
11 | // into an OpTypeXXX instruction, and map it to a virtual register. Also it |
12 | // builds and supports consistency of constants and global variables. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H |
17 | #define LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H |
18 | |
19 | #include "MCTargetDesc/SPIRVBaseInfo.h" |
20 | #include "SPIRVDuplicatesTracker.h" |
21 | #include "SPIRVInstrInfo.h" |
22 | #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" |
23 | #include "llvm/IR/Constant.h" |
24 | #include "llvm/IR/TypedPointerType.h" |
25 | |
26 | namespace llvm { |
27 | using SPIRVType = const MachineInstr; |
28 | |
29 | class SPIRVGlobalRegistry { |
30 | // Registers holding values which have types associated with them. |
31 | // Initialized upon VReg definition in IRTranslator. |
32 | // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg> |
33 | // where Reg = OpType... |
34 | // while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. not |
35 | // type-declaring ones). |
36 | DenseMap<const MachineFunction *, DenseMap<Register, SPIRVType *>> |
37 | VRegToTypeMap; |
38 | |
39 | // Map LLVM Type* to <MF, Reg> |
40 | SPIRVGeneralDuplicatesTracker DT; |
41 | |
42 | DenseMap<SPIRVType *, const Type *> SPIRVToLLVMType; |
43 | |
44 | // map a Function to its definition (as a machine instruction operand) |
45 | DenseMap<const Function *, const MachineOperand *> FunctionToInstr; |
46 | DenseMap<const MachineInstr *, const Function *> FunctionToInstrRev; |
47 | // map function pointer (as a machine instruction operand) to the used |
48 | // Function |
49 | DenseMap<const MachineOperand *, const Function *> InstrToFunction; |
50 | // Maps Functions to their calls (in a form of the machine instruction, |
51 | // OpFunctionCall) that happened before the definition is available |
52 | DenseMap<const Function *, SmallPtrSet<MachineInstr *, 8>> ForwardCalls; |
53 | |
54 | // Look for an equivalent of the newType in the map. Return the equivalent |
55 | // if it's found, otherwise insert newType to the map and return the type. |
56 | const MachineInstr *checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD, |
57 | MachineIRBuilder &MIRBuilder); |
58 | |
59 | SmallPtrSet<const Type *, 4> TypesInProcessing; |
60 | DenseMap<const Type *, SPIRVType *> ForwardPointerTypes; |
61 | |
62 | // if a function returns a pointer, this is to map it into TypedPointerType |
63 | DenseMap<const Function *, TypedPointerType *> FunResPointerTypes; |
64 | |
65 | // Number of bits pointers and size_t integers require. |
66 | const unsigned PointerSize; |
67 | |
68 | // Holds the maximum ID we have in the module. |
69 | unsigned Bound; |
70 | |
71 | // Maps values associated with untyped pointers into deduced element types of |
72 | // untyped pointers. |
73 | DenseMap<Value *, Type *> DeducedElTys; |
74 | // Maps composite values to deduced types where untyped pointers are replaced |
75 | // with typed ones |
76 | DenseMap<Value *, Type *> DeducedNestedTys; |
77 | |
78 | // Add a new OpTypeXXX instruction without checking for duplicates. |
79 | SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, |
80 | SPIRV::AccessQualifier::AccessQualifier AQ = |
81 | SPIRV::AccessQualifier::ReadWrite, |
82 | bool EmitIR = true); |
83 | SPIRVType *findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder, |
84 | SPIRV::AccessQualifier::AccessQualifier accessQual = |
85 | SPIRV::AccessQualifier::ReadWrite, |
86 | bool EmitIR = true); |
87 | SPIRVType * |
88 | restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, |
89 | SPIRV::AccessQualifier::AccessQualifier AccessQual, |
90 | bool EmitIR); |
91 | |
92 | public: |
93 | SPIRVGlobalRegistry(unsigned PointerSize); |
94 | |
95 | MachineFunction *CurMF; |
96 | |
97 | void add(const Constant *C, MachineFunction *MF, Register R) { |
98 | DT.add(C, MF, R); |
99 | } |
100 | |
101 | void add(const GlobalVariable *GV, MachineFunction *MF, Register R) { |
102 | DT.add(GV, MF, R); |
103 | } |
104 | |
105 | void add(const Function *F, MachineFunction *MF, Register R) { |
106 | DT.add(F, MF, R); |
107 | } |
108 | |
109 | void add(const Argument *Arg, MachineFunction *MF, Register R) { |
110 | DT.add(Arg, MF, R); |
111 | } |
112 | |
113 | void add(const MachineInstr *MI, MachineFunction *MF, Register R) { |
114 | DT.add(MI, MF, R); |
115 | } |
116 | |
117 | Register find(const MachineInstr *MI, MachineFunction *MF) { |
118 | return DT.find(MI, MF); |
119 | } |
120 | |
121 | Register find(const Constant *C, MachineFunction *MF) { |
122 | return DT.find(C, MF); |
123 | } |
124 | |
125 | Register find(const GlobalVariable *GV, MachineFunction *MF) { |
126 | return DT.find(GV, MF); |
127 | } |
128 | |
129 | Register find(const Function *F, MachineFunction *MF) { |
130 | return DT.find(F, MF); |
131 | } |
132 | |
133 | void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph, |
134 | MachineModuleInfo *MMI = nullptr) { |
135 | DT.buildDepsGraph(Graph, MMI); |
136 | } |
137 | |
138 | void setBound(unsigned V) { Bound = V; } |
139 | unsigned getBound() { return Bound; } |
140 | |
141 | // Add a record to the map of function return pointer types. |
142 | void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy) { |
143 | FunResPointerTypes[ArgF] = DerivedTy; |
144 | } |
145 | // Find a record in the map of function return pointer types. |
146 | const TypedPointerType *findReturnType(const Function *ArgF) { |
147 | auto It = FunResPointerTypes.find(Val: ArgF); |
148 | return It == FunResPointerTypes.end() ? nullptr : It->second; |
149 | } |
150 | |
151 | // Deduced element types of untyped pointers and composites: |
152 | // - Add a record to the map of deduced element types. |
153 | void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; } |
154 | // - Find a record in the map of deduced element types. |
155 | Type *findDeducedElementType(const Value *Val) { |
156 | auto It = DeducedElTys.find(Val); |
157 | return It == DeducedElTys.end() ? nullptr : It->second; |
158 | } |
159 | // - Add a record to the map of deduced composite types. |
160 | void addDeducedCompositeType(Value *Val, Type *Ty) { |
161 | DeducedNestedTys[Val] = Ty; |
162 | } |
163 | // - Find a record in the map of deduced composite types. |
164 | Type *findDeducedCompositeType(const Value *Val) { |
165 | auto It = DeducedNestedTys.find(Val); |
166 | return It == DeducedNestedTys.end() ? nullptr : It->second; |
167 | } |
168 | // - Find a type of the given Global value |
169 | Type *getDeducedGlobalValueType(const GlobalValue *Global) { |
170 | // we may know element type if it was deduced earlier |
171 | Type *ElementTy = findDeducedElementType(Val: Global); |
172 | if (!ElementTy) { |
173 | // or we may know element type if it's associated with a composite |
174 | // value |
175 | if (Value *GlobalElem = |
176 | Global->getNumOperands() > 0 ? Global->getOperand(i: 0) : nullptr) |
177 | ElementTy = findDeducedCompositeType(Val: GlobalElem); |
178 | } |
179 | return ElementTy ? ElementTy : Global->getValueType(); |
180 | } |
181 | |
182 | // Map a machine operand that represents a use of a function via function |
183 | // pointer to a machine operand that represents the function definition. |
184 | // Return either the register or invalid value, because we have no context for |
185 | // a good diagnostic message in case of unexpectedly missing references. |
186 | const MachineOperand *getFunctionDefinitionByUse(const MachineOperand *Use) { |
187 | auto ResF = InstrToFunction.find(Val: Use); |
188 | if (ResF == InstrToFunction.end()) |
189 | return nullptr; |
190 | auto ResReg = FunctionToInstr.find(Val: ResF->second); |
191 | return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second; |
192 | } |
193 | |
194 | // Map a Function to a machine instruction that represents the function |
195 | // definition. |
196 | const MachineInstr *getFunctionDefinition(const Function *F) { |
197 | if (!F) |
198 | return nullptr; |
199 | auto MOIt = FunctionToInstr.find(Val: F); |
200 | return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent(); |
201 | } |
202 | |
203 | // Map a Function to a machine instruction that represents the function |
204 | // definition. |
205 | const Function *getFunctionByDefinition(const MachineInstr *MI) { |
206 | if (!MI) |
207 | return nullptr; |
208 | auto FIt = FunctionToInstrRev.find(Val: MI); |
209 | return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second; |
210 | } |
211 | |
212 | // map function pointer (as a machine instruction operand) to the used |
213 | // Function |
214 | void recordFunctionPointer(const MachineOperand *MO, const Function *F) { |
215 | InstrToFunction[MO] = F; |
216 | } |
217 | |
218 | // map a Function to its definition (as a machine instruction) |
219 | void recordFunctionDefinition(const Function *F, const MachineOperand *MO) { |
220 | FunctionToInstr[F] = MO; |
221 | FunctionToInstrRev[MO->getParent()] = F; |
222 | } |
223 | |
224 | // Return true if any OpConstantFunctionPointerINTEL were generated |
225 | bool hasConstFunPtr() { return !InstrToFunction.empty(); } |
226 | |
227 | // Add a record about forward function call. |
228 | void addForwardCall(const Function *F, MachineInstr *MI) { |
229 | auto It = ForwardCalls.find(Val: F); |
230 | if (It == ForwardCalls.end()) |
231 | ForwardCalls[F] = {MI}; |
232 | else |
233 | It->second.insert(Ptr: MI); |
234 | } |
235 | |
236 | // Map a Function to the vector of machine instructions that represents |
237 | // forward function calls or to nullptr if not found. |
238 | SmallPtrSet<MachineInstr *, 8> *getForwardCalls(const Function *F) { |
239 | auto It = ForwardCalls.find(Val: F); |
240 | return It == ForwardCalls.end() ? nullptr : &It->second; |
241 | } |
242 | |
243 | // Get or create a SPIR-V type corresponding the given LLVM IR type, |
244 | // and map it to the given VReg by creating an ASSIGN_TYPE instruction. |
245 | SPIRVType *assignTypeToVReg(const Type *Type, Register VReg, |
246 | MachineIRBuilder &MIRBuilder, |
247 | SPIRV::AccessQualifier::AccessQualifier AQ = |
248 | SPIRV::AccessQualifier::ReadWrite, |
249 | bool EmitIR = true); |
250 | SPIRVType *assignIntTypeToVReg(unsigned BitWidth, Register VReg, |
251 | MachineInstr &I, const SPIRVInstrInfo &TII); |
252 | SPIRVType *assignFloatTypeToVReg(unsigned BitWidth, Register VReg, |
253 | MachineInstr &I, const SPIRVInstrInfo &TII); |
254 | SPIRVType *assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements, |
255 | Register VReg, MachineInstr &I, |
256 | const SPIRVInstrInfo &TII); |
257 | |
258 | // In cases where the SPIR-V type is already known, this function can be |
259 | // used to map it to the given VReg via an ASSIGN_TYPE instruction. |
260 | void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, |
261 | MachineFunction &MF); |
262 | |
263 | // Either generate a new OpTypeXXX instruction or return an existing one |
264 | // corresponding to the given LLVM IR type. |
265 | // EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes) |
266 | // because this method may be called from InstructionSelector and we don't |
267 | // want to emit extra IR instructions there. |
268 | SPIRVType *getOrCreateSPIRVType(const Type *Type, |
269 | MachineIRBuilder &MIRBuilder, |
270 | SPIRV::AccessQualifier::AccessQualifier AQ = |
271 | SPIRV::AccessQualifier::ReadWrite, |
272 | bool EmitIR = true); |
273 | |
274 | const Type *getTypeForSPIRVType(const SPIRVType *Ty) const { |
275 | auto Res = SPIRVToLLVMType.find(Val: Ty); |
276 | assert(Res != SPIRVToLLVMType.end()); |
277 | return Res->second; |
278 | } |
279 | |
280 | // Return a pointee's type op code, or 0 otherwise. |
281 | unsigned getPointeeTypeOp(Register PtrReg); |
282 | |
283 | // Either generate a new OpTypeXXX instruction or return an existing one |
284 | // corresponding to the given string containing the name of the builtin type. |
285 | // Return nullptr if unable to recognize SPIRV type name from `TypeStr`. |
286 | SPIRVType *getOrCreateSPIRVTypeByName( |
287 | StringRef TypeStr, MachineIRBuilder &MIRBuilder, |
288 | SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function, |
289 | SPIRV::AccessQualifier::AccessQualifier AQ = |
290 | SPIRV::AccessQualifier::ReadWrite); |
291 | |
292 | // Return the SPIR-V type instruction corresponding to the given VReg, or |
293 | // nullptr if no such type instruction exists. The second argument MF |
294 | // allows to search for the association in a context of the machine functions |
295 | // than the current one, without switching between different "current" machine |
296 | // functions. |
297 | SPIRVType *getSPIRVTypeForVReg(Register VReg, |
298 | const MachineFunction *MF = nullptr) const; |
299 | |
300 | // Whether the given VReg has a SPIR-V type mapped to it yet. |
301 | bool hasSPIRVTypeForVReg(Register VReg) const { |
302 | return getSPIRVTypeForVReg(VReg) != nullptr; |
303 | } |
304 | |
305 | // Return the VReg holding the result of the given OpTypeXXX instruction. |
306 | Register getSPIRVTypeID(const SPIRVType *SpirvType) const; |
307 | |
308 | // Return previous value of the current machine function |
309 | MachineFunction *setCurrentFunc(MachineFunction &MF) { |
310 | MachineFunction *Ret = CurMF; |
311 | CurMF = &MF; |
312 | return Ret; |
313 | } |
314 | |
315 | // Whether the given VReg has an OpTypeXXX instruction mapped to it with the |
316 | // given opcode (e.g. OpTypeFloat). |
317 | bool isScalarOfType(Register VReg, unsigned TypeOpcode) const; |
318 | |
319 | // Return true if the given VReg's assigned SPIR-V type is either a scalar |
320 | // matching the given opcode, or a vector with an element type matching that |
321 | // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool). |
322 | bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const; |
323 | |
324 | // Return number of elements in a vector if the argument is associated with |
325 | // a vector type. Return 1 for a scalar type, and 0 for a missing type. |
326 | unsigned getScalarOrVectorComponentCount(Register VReg) const; |
327 | unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const; |
328 | |
329 | // For vectors or scalars of booleans, integers and floats, return the scalar |
330 | // type's bitwidth. Otherwise calls llvm_unreachable(). |
331 | unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const; |
332 | |
333 | // For vectors or scalars of integers and floats, return total bitwidth of the |
334 | // argument. Otherwise returns 0. |
335 | unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const; |
336 | |
337 | // Returns either pointer to integer type, that may be a type of vector |
338 | // elements or an original type, or nullptr if the argument is niether |
339 | // an integer scalar, nor an integer vector |
340 | const SPIRVType *retrieveScalarOrVectorIntType(const SPIRVType *Type) const; |
341 | |
342 | // For integer vectors or scalars, return whether the integers are signed. |
343 | bool isScalarOrVectorSigned(const SPIRVType *Type) const; |
344 | |
345 | // Gets the storage class of the pointer type assigned to this vreg. |
346 | SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const; |
347 | |
348 | // Return the number of bits SPIR-V pointers and size_t variables require. |
349 | unsigned getPointerSize() const { return PointerSize; } |
350 | |
351 | // Returns true if two types are defined and are compatible in a sense of |
352 | // OpBitcast instruction |
353 | bool isBitcastCompatible(const SPIRVType *Type1, |
354 | const SPIRVType *Type2) const; |
355 | |
356 | private: |
357 | SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder); |
358 | |
359 | SPIRVType *getOpTypeInt(uint32_t Width, MachineIRBuilder &MIRBuilder, |
360 | bool IsSigned = false); |
361 | |
362 | SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder); |
363 | |
364 | SPIRVType *getOpTypeVoid(MachineIRBuilder &MIRBuilder); |
365 | |
366 | SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType, |
367 | MachineIRBuilder &MIRBuilder); |
368 | |
369 | SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType, |
370 | MachineIRBuilder &MIRBuilder, bool EmitIR = true); |
371 | |
372 | SPIRVType *getOpTypeOpaque(const StructType *Ty, |
373 | MachineIRBuilder &MIRBuilder); |
374 | |
375 | SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder, |
376 | bool EmitIR = true); |
377 | |
378 | SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC, |
379 | SPIRVType *ElemType, MachineIRBuilder &MIRBuilder, |
380 | Register Reg); |
381 | |
382 | SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC, |
383 | MachineIRBuilder &MIRBuilder); |
384 | |
385 | SPIRVType *getOpTypeFunction(SPIRVType *RetType, |
386 | const SmallVectorImpl<SPIRVType *> &ArgTypes, |
387 | MachineIRBuilder &MIRBuilder); |
388 | |
389 | SPIRVType * |
390 | getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder, |
391 | SPIRV::AccessQualifier::AccessQualifier AccQual); |
392 | |
393 | std::tuple<Register, ConstantInt *, bool> getOrCreateConstIntReg( |
394 | uint64_t Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder, |
395 | MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr); |
396 | std::tuple<Register, ConstantFP *, bool, unsigned> getOrCreateConstFloatReg( |
397 | APFloat Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder, |
398 | MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr); |
399 | SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType); |
400 | Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I, |
401 | SPIRVType *SpvType, |
402 | const SPIRVInstrInfo &TII, |
403 | unsigned BitWidth); |
404 | Register getOrCreateCompositeOrNull(Constant *Val, MachineInstr &I, |
405 | SPIRVType *SpvType, |
406 | const SPIRVInstrInfo &TII, Constant *CA, |
407 | unsigned BitWidth, unsigned ElemCnt, |
408 | bool ZeroAsNull = true); |
409 | |
410 | Register getOrCreateIntCompositeOrNull(uint64_t Val, |
411 | MachineIRBuilder &MIRBuilder, |
412 | SPIRVType *SpvType, bool EmitIR, |
413 | Constant *CA, unsigned BitWidth, |
414 | unsigned ElemCnt); |
415 | |
416 | public: |
417 | Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, |
418 | SPIRVType *SpvType = nullptr, bool EmitIR = true); |
419 | Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, |
420 | SPIRVType *SpvType, const SPIRVInstrInfo &TII, |
421 | bool ZeroAsNull = true); |
422 | Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, |
423 | const SPIRVInstrInfo &TII, |
424 | bool ZeroAsNull = true); |
425 | Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, |
426 | SPIRVType *SpvType = nullptr); |
427 | |
428 | Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, |
429 | SPIRVType *SpvType, const SPIRVInstrInfo &TII, |
430 | bool ZeroAsNull = true); |
431 | Register getOrCreateConstVector(APFloat Val, MachineInstr &I, |
432 | SPIRVType *SpvType, const SPIRVInstrInfo &TII, |
433 | bool ZeroAsNull = true); |
434 | Register getOrCreateConsIntArray(uint64_t Val, MachineInstr &I, |
435 | SPIRVType *SpvType, |
436 | const SPIRVInstrInfo &TII); |
437 | Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, |
438 | SPIRVType *SpvType, bool EmitIR = true); |
439 | Register getOrCreateConsIntArray(uint64_t Val, MachineIRBuilder &MIRBuilder, |
440 | SPIRVType *SpvType, bool EmitIR = true); |
441 | Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, |
442 | SPIRVType *SpvType); |
443 | Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, |
444 | unsigned FilerMode, |
445 | MachineIRBuilder &MIRBuilder, |
446 | SPIRVType *SpvType); |
447 | Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, |
448 | const SPIRVInstrInfo &TII); |
449 | Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, |
450 | StringRef Name, const GlobalValue *GV, |
451 | SPIRV::StorageClass::StorageClass Storage, |
452 | const MachineInstr *Init, bool IsConst, |
453 | bool HasLinkageTy, |
454 | SPIRV::LinkageType::LinkageType LinkageType, |
455 | MachineIRBuilder &MIRBuilder, |
456 | bool IsInstSelector); |
457 | |
458 | // Convenient helpers for getting types with check for duplicates. |
459 | SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, |
460 | MachineIRBuilder &MIRBuilder); |
461 | SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineInstr &I, |
462 | const SPIRVInstrInfo &TII); |
463 | SPIRVType *getOrCreateSPIRVType(unsigned BitWidth, MachineInstr &I, |
464 | const SPIRVInstrInfo &TII, |
465 | unsigned SPIRVOPcode, Type *LLVMTy); |
466 | SPIRVType *getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, |
467 | const SPIRVInstrInfo &TII); |
468 | SPIRVType *getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder); |
469 | SPIRVType *getOrCreateSPIRVBoolType(MachineInstr &I, |
470 | const SPIRVInstrInfo &TII); |
471 | SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType, |
472 | unsigned NumElements, |
473 | MachineIRBuilder &MIRBuilder); |
474 | SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType, |
475 | unsigned NumElements, MachineInstr &I, |
476 | const SPIRVInstrInfo &TII); |
477 | SPIRVType *getOrCreateSPIRVArrayType(SPIRVType *BaseType, |
478 | unsigned NumElements, MachineInstr &I, |
479 | const SPIRVInstrInfo &TII); |
480 | |
481 | SPIRVType *getOrCreateSPIRVPointerType( |
482 | SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, |
483 | SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function); |
484 | SPIRVType *getOrCreateSPIRVPointerType( |
485 | SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &TII, |
486 | SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function); |
487 | |
488 | SPIRVType * |
489 | getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, |
490 | SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed, |
491 | uint32_t Multisampled, uint32_t Sampled, |
492 | SPIRV::ImageFormat::ImageFormat ImageFormat, |
493 | SPIRV::AccessQualifier::AccessQualifier AccQual); |
494 | |
495 | SPIRVType *getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder); |
496 | |
497 | SPIRVType *getOrCreateOpTypeSampledImage(SPIRVType *ImageType, |
498 | MachineIRBuilder &MIRBuilder); |
499 | |
500 | SPIRVType * |
501 | getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, |
502 | SPIRV::AccessQualifier::AccessQualifier AccQual); |
503 | SPIRVType *getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder); |
504 | SPIRVType *getOrCreateOpTypeFunctionWithArgs( |
505 | const Type *Ty, SPIRVType *RetType, |
506 | const SmallVectorImpl<SPIRVType *> &ArgTypes, |
507 | MachineIRBuilder &MIRBuilder); |
508 | SPIRVType *getOrCreateOpTypeByOpcode(const Type *Ty, |
509 | MachineIRBuilder &MIRBuilder, |
510 | unsigned Opcode); |
511 | }; |
512 | } // end namespace llvm |
513 | #endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H |
514 | |