1 //===----- CGHLSLRuntime.h - Interface to HLSL Runtimes -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This provides an abstract class for HLSL code generation. Concrete
10 // subclasses of this implement code generation for specific HLSL
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
16 #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/Intrinsics.h"
20 #include "llvm/IR/IntrinsicsDirectX.h"
21 #include "llvm/IR/IntrinsicsSPIRV.h"
23 #include "clang/Basic/Builtins.h"
24 #include "clang/Basic/HLSLRuntime.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Frontend/HLSL/HLSLResource.h"
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(); \
39 case llvm::Triple::dxil: \
40 return llvm::Intrinsic::dx_##IntrinsicPostfix; \
41 case llvm::Triple::spirv: \
42 return llvm::Intrinsic::spv_##IntrinsicPostfix; \
44 llvm_unreachable("Intrinsic " #IntrinsicPostfix \
45 " not supported by target architecture"); \
59 class HLSLResourceBindingAttr
;
71 //===----------------------------------------------------------------------===//
72 // Start of reserved area for HLSL intrinsic getters.
73 //===----------------------------------------------------------------------===//
75 GENERATE_HLSL_INTRINSIC_FUNCTION(All
, all
)
76 GENERATE_HLSL_INTRINSIC_FUNCTION(Any
, any
)
77 GENERATE_HLSL_INTRINSIC_FUNCTION(Cross
, cross
)
78 GENERATE_HLSL_INTRINSIC_FUNCTION(Degrees
, degrees
)
79 GENERATE_HLSL_INTRINSIC_FUNCTION(Frac
, frac
)
80 GENERATE_HLSL_INTRINSIC_FUNCTION(Length
, length
)
81 GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp
, lerp
)
82 GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize
, normalize
)
83 GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt
, rsqrt
)
84 GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate
, saturate
)
85 GENERATE_HLSL_INTRINSIC_FUNCTION(Sign
, sign
)
86 GENERATE_HLSL_INTRINSIC_FUNCTION(Step
, step
)
87 GENERATE_HLSL_INTRINSIC_FUNCTION(Radians
, radians
)
88 GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId
, thread_id
)
89 GENERATE_HLSL_INTRINSIC_FUNCTION(FDot
, fdot
)
90 GENERATE_HLSL_INTRINSIC_FUNCTION(SDot
, sdot
)
91 GENERATE_HLSL_INTRINSIC_FUNCTION(UDot
, udot
)
92 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed
, dot4add_i8packed
)
93 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed
, dot4add_u8packed
)
94 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue
, wave_any
)
95 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits
, wave_active_countbits
)
96 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane
, wave_is_first_lane
)
97 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt
, wave_readlane
)
98 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh
, firstbituhigh
)
99 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh
, firstbitshigh
)
100 GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp
, nclamp
)
101 GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp
, sclamp
)
102 GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp
, uclamp
)
104 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding
, handle_fromBinding
)
106 //===----------------------------------------------------------------------===//
107 // End of reserved area for HLSL intrinsic getters.
108 //===----------------------------------------------------------------------===//
110 struct BufferResBinding
{
111 // The ID like 2 in register(b2, space1).
112 std::optional
<unsigned> Reg
;
113 // The Space like 1 is register(b2, space1).
114 // Default value is 0.
116 BufferResBinding(HLSLResourceBindingAttr
*Attr
);
119 Buffer(const HLSLBufferDecl
*D
);
120 llvm::StringRef Name
;
121 // IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
123 BufferResBinding Binding
;
124 // Global variable and offset for each constant.
125 std::vector
<std::pair
<llvm::GlobalVariable
*, unsigned>> Constants
;
126 llvm::StructType
*LayoutStruct
= nullptr;
132 llvm::Value
*emitInputSemantic(llvm::IRBuilder
<> &B
, const ParmVarDecl
&D
,
136 CGHLSLRuntime(CodeGenModule
&CGM
) : CGM(CGM
) {}
137 virtual ~CGHLSLRuntime() {}
139 llvm::Type
*convertHLSLSpecificType(const Type
*T
);
141 void annotateHLSLResource(const VarDecl
*D
, llvm::GlobalVariable
*GV
);
142 void generateGlobalCtorDtorCalls();
144 void addBuffer(const HLSLBufferDecl
*D
);
145 void finishCodeGen();
147 void setHLSLEntryAttributes(const FunctionDecl
*FD
, llvm::Function
*Fn
);
149 void emitEntryFunction(const FunctionDecl
*FD
, llvm::Function
*Fn
);
150 void setHLSLFunctionAttributes(const FunctionDecl
*FD
, llvm::Function
*Fn
);
151 void handleGlobalVarDefinition(const VarDecl
*VD
, llvm::GlobalVariable
*Var
);
153 bool needsResourceBindingInitFn();
154 llvm::Function
*createResourceBindingInitFn();
155 llvm::Instruction
*getConvergenceToken(llvm::BasicBlock
&BB
);
158 void addBufferResourceAnnotation(llvm::GlobalVariable
*GV
,
159 llvm::hlsl::ResourceClass RC
,
160 llvm::hlsl::ResourceKind RK
, bool IsROV
,
161 llvm::hlsl::ElementType ET
,
162 BufferResBinding
&Binding
);
163 void addConstant(VarDecl
*D
, Buffer
&CB
);
164 void addBufferDecls(const DeclContext
*DC
, Buffer
&CB
);
165 llvm::Triple::ArchType
getArch();
166 llvm::SmallVector
<Buffer
> Buffers
;
168 llvm::SmallVector
<std::pair
<const VarDecl
*, llvm::GlobalVariable
*>>
172 } // namespace CodeGen