1 | //===----- CGHLSLRuntime.h - Interface to HLSL Runtimes -----*- 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 provides an abstract class for HLSL code generation. Concrete |
10 | // subclasses of this implement code generation for specific HLSL |
11 | // runtime libraries. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H |
16 | #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H |
17 | |
18 | #include "llvm/ADT/DenseMap.h" |
19 | #include "llvm/IR/IRBuilder.h" |
20 | #include "llvm/IR/Intrinsics.h" |
21 | #include "llvm/IR/IntrinsicsDirectX.h" |
22 | #include "llvm/IR/IntrinsicsSPIRV.h" |
23 | |
24 | #include "clang/Basic/Builtins.h" |
25 | #include "clang/Basic/HLSLRuntime.h" |
26 | |
27 | #include "llvm/ADT/SmallVector.h" |
28 | #include "llvm/ADT/StringRef.h" |
29 | #include "llvm/Frontend/HLSL/HLSLResource.h" |
30 | |
31 | #include <optional> |
32 | #include <vector> |
33 | |
34 | // A function generator macro for picking the right intrinsic |
35 | // for the target backend |
36 | #define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix) \ |
37 | llvm::Intrinsic::ID get##FunctionName##Intrinsic() { \ |
38 | llvm::Triple::ArchType Arch = getArch(); \ |
39 | switch (Arch) { \ |
40 | case llvm::Triple::dxil: \ |
41 | return llvm::Intrinsic::dx_##IntrinsicPostfix; \ |
42 | case llvm::Triple::spirv: \ |
43 | return llvm::Intrinsic::spv_##IntrinsicPostfix; \ |
44 | default: \ |
45 | llvm_unreachable("Intrinsic " #IntrinsicPostfix \ |
46 | " not supported by target architecture"); \ |
47 | } \ |
48 | } |
49 | |
50 | using ResourceClass = llvm::dxil::ResourceClass; |
51 | |
52 | namespace llvm { |
53 | class GlobalVariable; |
54 | class Function; |
55 | class StructType; |
56 | class Metadata; |
57 | } // namespace llvm |
58 | |
59 | namespace clang { |
60 | class NamedDecl; |
61 | class VarDecl; |
62 | class ParmVarDecl; |
63 | class InitListExpr; |
64 | class HLSLBufferDecl; |
65 | class HLSLResourceBindingAttr; |
66 | class Type; |
67 | class RecordType; |
68 | class DeclContext; |
69 | class HLSLPackOffsetAttr; |
70 | |
71 | class FunctionDecl; |
72 | |
73 | namespace CodeGen { |
74 | |
75 | class CodeGenModule; |
76 | class CodeGenFunction; |
77 | |
78 | class CGHLSLRuntime { |
79 | public: |
80 | //===----------------------------------------------------------------------===// |
81 | // Start of reserved area for HLSL intrinsic getters. |
82 | //===----------------------------------------------------------------------===// |
83 | |
84 | GENERATE_HLSL_INTRINSIC_FUNCTION(All, all) |
85 | GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any) |
86 | GENERATE_HLSL_INTRINSIC_FUNCTION(Cross, cross) |
87 | GENERATE_HLSL_INTRINSIC_FUNCTION(Degrees, degrees) |
88 | GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac) |
89 | GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup, |
90 | flattened_thread_id_in_group) |
91 | GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp) |
92 | GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize) |
93 | GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt) |
94 | GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate) |
95 | GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign) |
96 | GENERATE_HLSL_INTRINSIC_FUNCTION(Step, step) |
97 | GENERATE_HLSL_INTRINSIC_FUNCTION(Radians, radians) |
98 | GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id) |
99 | GENERATE_HLSL_INTRINSIC_FUNCTION(GroupThreadId, thread_id_in_group) |
100 | GENERATE_HLSL_INTRINSIC_FUNCTION(GroupId, group_id) |
101 | GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot) |
102 | GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) |
103 | GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) |
104 | GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed) |
105 | GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed) |
106 | GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all) |
107 | GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any) |
108 | GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) |
109 | GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) |
110 | GENERATE_HLSL_INTRINSIC_FUNCTION(WaveGetLaneCount, wave_get_lane_count) |
111 | GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) |
112 | GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) |
113 | GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) |
114 | GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow) |
115 | GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp) |
116 | GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp) |
117 | GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp) |
118 | |
119 | GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer, |
120 | resource_getpointer) |
121 | GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) |
122 | GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, |
123 | group_memory_barrier_with_group_sync) |
124 | |
125 | //===----------------------------------------------------------------------===// |
126 | // End of reserved area for HLSL intrinsic getters. |
127 | //===----------------------------------------------------------------------===// |
128 | |
129 | // Returns ID of the intrinsic that initializes resource handle from binding |
130 | // and a bool value indicating whether the last argument of the intrinsic is |
131 | // the resource name (not all targets need that). |
132 | std::pair<llvm::Intrinsic::ID, bool> getCreateHandleFromBindingIntrinsic(); |
133 | |
134 | // Same as above but for implicit binding. |
135 | std::pair<llvm::Intrinsic::ID, bool> |
136 | getCreateHandleFromImplicitBindingIntrinsic(); |
137 | |
138 | protected: |
139 | CodeGenModule &CGM; |
140 | |
141 | llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D, |
142 | llvm::Type *Ty); |
143 | |
144 | public: |
145 | CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} |
146 | virtual ~CGHLSLRuntime() {} |
147 | |
148 | llvm::Type * |
149 | convertHLSLSpecificType(const Type *T, |
150 | SmallVector<int32_t> *Packoffsets = nullptr); |
151 | |
152 | void generateGlobalCtorDtorCalls(); |
153 | |
154 | void addBuffer(const HLSLBufferDecl *D); |
155 | void finishCodeGen(); |
156 | |
157 | void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn); |
158 | |
159 | void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn); |
160 | void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn); |
161 | void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var); |
162 | |
163 | llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB); |
164 | |
165 | llvm::TargetExtType * |
166 | getHLSLBufferLayoutType(const RecordType *LayoutStructTy); |
167 | void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, |
168 | llvm::TargetExtType *LayoutTy); |
169 | void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E); |
170 | |
171 | private: |
172 | void emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl, |
173 | llvm::GlobalVariable *BufGV); |
174 | void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl, |
175 | llvm::GlobalVariable *GV, |
176 | HLSLResourceBindingAttr *RBA); |
177 | llvm::Triple::ArchType getArch(); |
178 | |
179 | llvm::DenseMap<const clang::RecordType *, llvm::TargetExtType *> LayoutTypes; |
180 | }; |
181 | |
182 | } // namespace CodeGen |
183 | } // namespace clang |
184 | |
185 | #endif |
186 | |