1 | //===--- SPIRVUtils.h ---- SPIR-V Utility Functions -------------*- 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 | // This file contains miscellaneous utility functions. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H |
14 | #define LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H |
15 | |
16 | #include "MCTargetDesc/SPIRVBaseInfo.h" |
17 | #include "llvm/IR/IRBuilder.h" |
18 | #include "llvm/IR/TypedPointerType.h" |
19 | #include <string> |
20 | |
21 | namespace llvm { |
22 | class MCInst; |
23 | class MachineFunction; |
24 | class MachineInstr; |
25 | class MachineInstrBuilder; |
26 | class MachineIRBuilder; |
27 | class MachineRegisterInfo; |
28 | class Register; |
29 | class StringRef; |
30 | class SPIRVInstrInfo; |
31 | class SPIRVSubtarget; |
32 | |
33 | // Add the given string as a series of integer operand, inserting null |
34 | // terminators and padding to make sure the operands all have 32-bit |
35 | // little-endian words. |
36 | void addStringImm(const StringRef &Str, MCInst &Inst); |
37 | void addStringImm(const StringRef &Str, MachineInstrBuilder &MIB); |
38 | void addStringImm(const StringRef &Str, IRBuilder<> &B, |
39 | std::vector<Value *> &Args); |
40 | |
41 | // Read the series of integer operands back as a null-terminated string using |
42 | // the reverse of the logic in addStringImm. |
43 | std::string getStringImm(const MachineInstr &MI, unsigned StartIndex); |
44 | |
45 | // Add the given numerical immediate to MIB. |
46 | void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB); |
47 | |
48 | // Add an OpName instruction for the given target register. |
49 | void buildOpName(Register Target, const StringRef &Name, |
50 | MachineIRBuilder &MIRBuilder); |
51 | |
52 | // Add an OpDecorate instruction for the given Reg. |
53 | void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, |
54 | SPIRV::Decoration::Decoration Dec, |
55 | const std::vector<uint32_t> &DecArgs, |
56 | StringRef StrImm = "" ); |
57 | void buildOpDecorate(Register Reg, MachineInstr &I, const SPIRVInstrInfo &TII, |
58 | SPIRV::Decoration::Decoration Dec, |
59 | const std::vector<uint32_t> &DecArgs, |
60 | StringRef StrImm = "" ); |
61 | |
62 | // Convert a SPIR-V storage class to the corresponding LLVM IR address space. |
63 | unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC); |
64 | |
65 | // Convert an LLVM IR address space to a SPIR-V storage class. |
66 | SPIRV::StorageClass::StorageClass |
67 | addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI); |
68 | |
69 | SPIRV::MemorySemantics::MemorySemantics |
70 | getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC); |
71 | |
72 | SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord); |
73 | |
74 | // Find def instruction for the given ConstReg, walking through |
75 | // spv_track_constant and ASSIGN_TYPE instructions. Updates ConstReg by def |
76 | // of OpConstant instruction. |
77 | MachineInstr *getDefInstrMaybeConstant(Register &ConstReg, |
78 | const MachineRegisterInfo *MRI); |
79 | |
80 | // Get constant integer value of the given ConstReg. |
81 | uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI); |
82 | |
83 | // Check if MI is a SPIR-V specific intrinsic call. |
84 | bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID); |
85 | |
86 | // Get type of i-th operand of the metadata node. |
87 | Type *getMDOperandAsType(const MDNode *N, unsigned I); |
88 | |
89 | // If OpenCL or SPIR-V builtin function name is recognized, return a demangled |
90 | // name, otherwise return an empty string. |
91 | std::string getOclOrSpirvBuiltinDemangledName(StringRef Name); |
92 | |
93 | // Check if a string contains a builtin prefix. |
94 | bool hasBuiltinTypePrefix(StringRef Name); |
95 | |
96 | // Check if given LLVM type is a special opaque builtin type. |
97 | bool isSpecialOpaqueType(const Type *Ty); |
98 | |
99 | // Check if the function is an SPIR-V entry point |
100 | bool isEntryPoint(const Function &F); |
101 | |
102 | // Parse basic scalar type name, substring TypeName, and return LLVM type. |
103 | Type *parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx); |
104 | |
105 | // True if this is an instance of TypedPointerType. |
106 | inline bool isTypedPointerTy(const Type *T) { |
107 | return T->getTypeID() == Type::TypedPointerTyID; |
108 | } |
109 | |
110 | // True if this is an instance of PointerType. |
111 | inline bool isUntypedPointerTy(const Type *T) { |
112 | return T->getTypeID() == Type::PointerTyID; |
113 | } |
114 | |
115 | // True if this is an instance of PointerType or TypedPointerType. |
116 | inline bool isPointerTy(const Type *T) { |
117 | return isUntypedPointerTy(T) || isTypedPointerTy(T); |
118 | } |
119 | |
120 | // Get the address space of this pointer or pointer vector type for instances of |
121 | // PointerType or TypedPointerType. |
122 | inline unsigned getPointerAddressSpace(const Type *T) { |
123 | Type *SubT = T->getScalarType(); |
124 | return SubT->getTypeID() == Type::PointerTyID |
125 | ? cast<PointerType>(Val: SubT)->getAddressSpace() |
126 | : cast<TypedPointerType>(Val: SubT)->getAddressSpace(); |
127 | } |
128 | |
129 | // Return true if the Argument is decorated with a pointee type |
130 | inline bool hasPointeeTypeAttr(Argument *Arg) { |
131 | return Arg->hasByValAttr() || Arg->hasByRefAttr() || Arg->hasStructRetAttr(); |
132 | } |
133 | |
134 | // Return the pointee type of the argument or nullptr otherwise |
135 | inline Type *getPointeeTypeByAttr(Argument *Arg) { |
136 | if (Arg->hasByValAttr()) |
137 | return Arg->getParamByValType(); |
138 | if (Arg->hasStructRetAttr()) |
139 | return Arg->getParamStructRetType(); |
140 | if (Arg->hasByRefAttr()) |
141 | return Arg->getParamByRefType(); |
142 | return nullptr; |
143 | } |
144 | |
145 | inline Type *reconstructFunctionType(Function *F) { |
146 | SmallVector<Type *> ArgTys; |
147 | for (unsigned i = 0; i < F->arg_size(); ++i) |
148 | ArgTys.push_back(Elt: F->getArg(i)->getType()); |
149 | return FunctionType::get(Result: F->getReturnType(), Params: ArgTys, isVarArg: F->isVarArg()); |
150 | } |
151 | |
152 | inline Type *toTypedPointer(Type *Ty, LLVMContext &Ctx) { |
153 | return isUntypedPointerTy(T: Ty) |
154 | ? TypedPointerType::get(ElementType: IntegerType::getInt8Ty(C&: Ctx), |
155 | AddressSpace: getPointerAddressSpace(T: Ty)) |
156 | : Ty; |
157 | } |
158 | |
159 | } // namespace llvm |
160 | #endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H |
161 | |