xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/CGHLSLRuntime.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===----- CGHLSLRuntime.h - Interface to HLSL Runtimes -----*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // This provides an abstract class for HLSL code generation.  Concrete
1081ad6265SDimitry Andric // subclasses of this implement code generation for specific HLSL
1181ad6265SDimitry Andric // runtime libraries.
1281ad6265SDimitry Andric //
1381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1481ad6265SDimitry Andric 
1581ad6265SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
1681ad6265SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
1781ad6265SDimitry Andric 
18bdd1243dSDimitry Andric #include "llvm/IR/IRBuilder.h"
19*0fca6ea1SDimitry Andric #include "llvm/IR/Intrinsics.h"
20*0fca6ea1SDimitry Andric #include "llvm/IR/IntrinsicsDirectX.h"
21*0fca6ea1SDimitry Andric #include "llvm/IR/IntrinsicsSPIRV.h"
22bdd1243dSDimitry Andric 
23*0fca6ea1SDimitry Andric #include "clang/Basic/Builtins.h"
24bdd1243dSDimitry Andric #include "clang/Basic/HLSLRuntime.h"
25bdd1243dSDimitry Andric 
26bdd1243dSDimitry Andric #include "llvm/ADT/SmallVector.h"
27bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h"
28bdd1243dSDimitry Andric #include "llvm/Frontend/HLSL/HLSLResource.h"
29bdd1243dSDimitry Andric 
30bdd1243dSDimitry Andric #include <optional>
31bdd1243dSDimitry Andric #include <vector>
32bdd1243dSDimitry Andric 
33*0fca6ea1SDimitry Andric // A function generator macro for picking the right intrinsic
34*0fca6ea1SDimitry Andric // for the target backend
35*0fca6ea1SDimitry Andric #define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix)       \
36*0fca6ea1SDimitry Andric   llvm::Intrinsic::ID get##FunctionName##Intrinsic() {                         \
37*0fca6ea1SDimitry Andric     llvm::Triple::ArchType Arch = getArch();                                   \
38*0fca6ea1SDimitry Andric     switch (Arch) {                                                            \
39*0fca6ea1SDimitry Andric     case llvm::Triple::dxil:                                                   \
40*0fca6ea1SDimitry Andric       return llvm::Intrinsic::dx_##IntrinsicPostfix;                           \
41*0fca6ea1SDimitry Andric     case llvm::Triple::spirv:                                                  \
42*0fca6ea1SDimitry Andric       return llvm::Intrinsic::spv_##IntrinsicPostfix;                          \
43*0fca6ea1SDimitry Andric     default:                                                                   \
44*0fca6ea1SDimitry Andric       llvm_unreachable("Intrinsic " #IntrinsicPostfix                          \
45*0fca6ea1SDimitry Andric                        " not supported by target architecture");               \
46*0fca6ea1SDimitry Andric     }                                                                          \
47*0fca6ea1SDimitry Andric   }
48*0fca6ea1SDimitry Andric 
49bdd1243dSDimitry Andric namespace llvm {
50bdd1243dSDimitry Andric class GlobalVariable;
51bdd1243dSDimitry Andric class Function;
52bdd1243dSDimitry Andric class StructType;
53bdd1243dSDimitry Andric } // namespace llvm
54bdd1243dSDimitry Andric 
5581ad6265SDimitry Andric namespace clang {
56bdd1243dSDimitry Andric class VarDecl;
57bdd1243dSDimitry Andric class ParmVarDecl;
58bdd1243dSDimitry Andric class HLSLBufferDecl;
59bdd1243dSDimitry Andric class HLSLResourceBindingAttr;
60bdd1243dSDimitry Andric class Type;
61bdd1243dSDimitry Andric class DeclContext;
62bdd1243dSDimitry Andric 
63bdd1243dSDimitry Andric class FunctionDecl;
6481ad6265SDimitry Andric 
6581ad6265SDimitry Andric namespace CodeGen {
6681ad6265SDimitry Andric 
6781ad6265SDimitry Andric class CodeGenModule;
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric class CGHLSLRuntime {
70bdd1243dSDimitry Andric public:
71*0fca6ea1SDimitry Andric   //===----------------------------------------------------------------------===//
72*0fca6ea1SDimitry Andric   // Start of reserved area for HLSL intrinsic getters.
73*0fca6ea1SDimitry Andric   //===----------------------------------------------------------------------===//
74*0fca6ea1SDimitry Andric 
75*0fca6ea1SDimitry Andric   GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
76*0fca6ea1SDimitry Andric   GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
77*0fca6ea1SDimitry Andric   GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
78*0fca6ea1SDimitry Andric   GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
79*0fca6ea1SDimitry Andric   GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
80*0fca6ea1SDimitry Andric 
81*0fca6ea1SDimitry Andric   //===----------------------------------------------------------------------===//
82*0fca6ea1SDimitry Andric   // End of reserved area for HLSL intrinsic getters.
83*0fca6ea1SDimitry Andric   //===----------------------------------------------------------------------===//
84*0fca6ea1SDimitry Andric 
85bdd1243dSDimitry Andric   struct BufferResBinding {
86bdd1243dSDimitry Andric     // The ID like 2 in register(b2, space1).
87bdd1243dSDimitry Andric     std::optional<unsigned> Reg;
88bdd1243dSDimitry Andric     // The Space like 1 is register(b2, space1).
89bdd1243dSDimitry Andric     // Default value is 0.
90bdd1243dSDimitry Andric     unsigned Space;
91bdd1243dSDimitry Andric     BufferResBinding(HLSLResourceBindingAttr *Attr);
92bdd1243dSDimitry Andric   };
93bdd1243dSDimitry Andric   struct Buffer {
94bdd1243dSDimitry Andric     Buffer(const HLSLBufferDecl *D);
95bdd1243dSDimitry Andric     llvm::StringRef Name;
96bdd1243dSDimitry Andric     // IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
97bdd1243dSDimitry Andric     bool IsCBuffer;
98bdd1243dSDimitry Andric     BufferResBinding Binding;
99bdd1243dSDimitry Andric     // Global variable and offset for each constant.
100bdd1243dSDimitry Andric     std::vector<std::pair<llvm::GlobalVariable *, unsigned>> Constants;
101bdd1243dSDimitry Andric     llvm::StructType *LayoutStruct = nullptr;
102bdd1243dSDimitry Andric   };
103bdd1243dSDimitry Andric 
10481ad6265SDimitry Andric protected:
10581ad6265SDimitry Andric   CodeGenModule &CGM;
10681ad6265SDimitry Andric 
107bdd1243dSDimitry Andric   llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D,
108bdd1243dSDimitry Andric                                  llvm::Type *Ty);
109bdd1243dSDimitry Andric 
11081ad6265SDimitry Andric public:
11181ad6265SDimitry Andric   CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
11281ad6265SDimitry Andric   virtual ~CGHLSLRuntime() {}
11381ad6265SDimitry Andric 
114bdd1243dSDimitry Andric   void annotateHLSLResource(const VarDecl *D, llvm::GlobalVariable *GV);
115bdd1243dSDimitry Andric   void generateGlobalCtorDtorCalls();
116bdd1243dSDimitry Andric 
117bdd1243dSDimitry Andric   void addBuffer(const HLSLBufferDecl *D);
11881ad6265SDimitry Andric   void finishCodeGen();
119bdd1243dSDimitry Andric 
120bdd1243dSDimitry Andric   void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);
121bdd1243dSDimitry Andric 
122bdd1243dSDimitry Andric   void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
123bdd1243dSDimitry Andric   void setHLSLFunctionAttributes(llvm::Function *, const FunctionDecl *);
124bdd1243dSDimitry Andric 
125bdd1243dSDimitry Andric private:
126bdd1243dSDimitry Andric   void addBufferResourceAnnotation(llvm::GlobalVariable *GV,
127bdd1243dSDimitry Andric                                    llvm::hlsl::ResourceClass RC,
1285f757f3fSDimitry Andric                                    llvm::hlsl::ResourceKind RK, bool IsROV,
129cb14a3feSDimitry Andric                                    llvm::hlsl::ElementType ET,
130bdd1243dSDimitry Andric                                    BufferResBinding &Binding);
131bdd1243dSDimitry Andric   void addConstant(VarDecl *D, Buffer &CB);
132bdd1243dSDimitry Andric   void addBufferDecls(const DeclContext *DC, Buffer &CB);
133*0fca6ea1SDimitry Andric   llvm::Triple::ArchType getArch();
134bdd1243dSDimitry Andric   llvm::SmallVector<Buffer> Buffers;
13581ad6265SDimitry Andric };
13681ad6265SDimitry Andric 
13781ad6265SDimitry Andric } // namespace CodeGen
13881ad6265SDimitry Andric } // namespace clang
13981ad6265SDimitry Andric 
14081ad6265SDimitry Andric #endif
141