xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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/IR/IRBuilder.h"
19 #include "llvm/IR/Intrinsics.h"
20 #include "llvm/IR/IntrinsicsDirectX.h"
21 #include "llvm/IR/IntrinsicsSPIRV.h"
22 
23 #include "clang/Basic/Builtins.h"
24 #include "clang/Basic/HLSLRuntime.h"
25 
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Frontend/HLSL/HLSLResource.h"
29 
30 #include <optional>
31 #include <vector>
32 
33 // A function generator macro for picking the right intrinsic
34 // for the target backend
35 #define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix)       \
36   llvm::Intrinsic::ID get##FunctionName##Intrinsic() {                         \
37     llvm::Triple::ArchType Arch = getArch();                                   \
38     switch (Arch) {                                                            \
39     case llvm::Triple::dxil:                                                   \
40       return llvm::Intrinsic::dx_##IntrinsicPostfix;                           \
41     case llvm::Triple::spirv:                                                  \
42       return llvm::Intrinsic::spv_##IntrinsicPostfix;                          \
43     default:                                                                   \
44       llvm_unreachable("Intrinsic " #IntrinsicPostfix                          \
45                        " not supported by target architecture");               \
46     }                                                                          \
47   }
48 
49 namespace llvm {
50 class GlobalVariable;
51 class Function;
52 class StructType;
53 } // namespace llvm
54 
55 namespace clang {
56 class VarDecl;
57 class ParmVarDecl;
58 class HLSLBufferDecl;
59 class HLSLResourceBindingAttr;
60 class Type;
61 class DeclContext;
62 
63 class FunctionDecl;
64 
65 namespace CodeGen {
66 
67 class CodeGenModule;
68 
69 class CGHLSLRuntime {
70 public:
71   //===----------------------------------------------------------------------===//
72   // Start of reserved area for HLSL intrinsic getters.
73   //===----------------------------------------------------------------------===//
74 
75   GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
76   GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
77   GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
78   GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
79   GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
80 
81   //===----------------------------------------------------------------------===//
82   // End of reserved area for HLSL intrinsic getters.
83   //===----------------------------------------------------------------------===//
84 
85   struct BufferResBinding {
86     // The ID like 2 in register(b2, space1).
87     std::optional<unsigned> Reg;
88     // The Space like 1 is register(b2, space1).
89     // Default value is 0.
90     unsigned Space;
91     BufferResBinding(HLSLResourceBindingAttr *Attr);
92   };
93   struct Buffer {
94     Buffer(const HLSLBufferDecl *D);
95     llvm::StringRef Name;
96     // IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
97     bool IsCBuffer;
98     BufferResBinding Binding;
99     // Global variable and offset for each constant.
100     std::vector<std::pair<llvm::GlobalVariable *, unsigned>> Constants;
101     llvm::StructType *LayoutStruct = nullptr;
102   };
103 
104 protected:
105   CodeGenModule &CGM;
106 
107   llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D,
108                                  llvm::Type *Ty);
109 
110 public:
111   CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
112   virtual ~CGHLSLRuntime() {}
113 
114   void annotateHLSLResource(const VarDecl *D, llvm::GlobalVariable *GV);
115   void generateGlobalCtorDtorCalls();
116 
117   void addBuffer(const HLSLBufferDecl *D);
118   void finishCodeGen();
119 
120   void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);
121 
122   void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
123   void setHLSLFunctionAttributes(llvm::Function *, const FunctionDecl *);
124 
125 private:
126   void addBufferResourceAnnotation(llvm::GlobalVariable *GV,
127                                    llvm::hlsl::ResourceClass RC,
128                                    llvm::hlsl::ResourceKind RK, bool IsROV,
129                                    llvm::hlsl::ElementType ET,
130                                    BufferResBinding &Binding);
131   void addConstant(VarDecl *D, Buffer &CB);
132   void addBufferDecls(const DeclContext *DC, Buffer &CB);
133   llvm::Triple::ArchType getArch();
134   llvm::SmallVector<Buffer> Buffers;
135 };
136 
137 } // namespace CodeGen
138 } // namespace clang
139 
140 #endif
141