xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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(CreateHandleFromBinding,
122                                    resource_handlefrombinding)
123   GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding,
124                                    resource_handlefromimplicitbinding)
125   GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
126   GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
127                                    group_memory_barrier_with_group_sync)
128 
129   //===----------------------------------------------------------------------===//
130   // End of reserved area for HLSL intrinsic getters.
131   //===----------------------------------------------------------------------===//
132 
133 protected:
134   CodeGenModule &CGM;
135 
136   llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D,
137                                  llvm::Type *Ty);
138 
139 public:
CGHLSLRuntime(CodeGenModule & CGM)140   CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
~CGHLSLRuntime()141   virtual ~CGHLSLRuntime() {}
142 
143   llvm::Type *
144   convertHLSLSpecificType(const Type *T,
145                           SmallVector<int32_t> *Packoffsets = nullptr);
146 
147   void generateGlobalCtorDtorCalls();
148 
149   void addBuffer(const HLSLBufferDecl *D);
150   void finishCodeGen();
151 
152   void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);
153 
154   void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
155   void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);
156   void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var);
157 
158   llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);
159 
160   llvm::TargetExtType *
161   getHLSLBufferLayoutType(const RecordType *LayoutStructTy);
162   void addHLSLBufferLayoutType(const RecordType *LayoutStructTy,
163                                llvm::TargetExtType *LayoutTy);
164   void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E);
165 
166 private:
167   void emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
168                                     llvm::GlobalVariable *BufGV);
169   void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
170                                    llvm::GlobalVariable *GV,
171                                    HLSLResourceBindingAttr *RBA);
172   llvm::Triple::ArchType getArch();
173 
174   llvm::DenseMap<const clang::RecordType *, llvm::TargetExtType *> LayoutTypes;
175 };
176 
177 } // namespace CodeGen
178 } // namespace clang
179 
180 #endif
181