clang 22.0.0git
CGHLSLRuntime.h
Go to the documentation of this file.
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 "Address.h"
19#include "clang/AST/Attr.h"
20#include "clang/AST/Decl.h"
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/Frontend/HLSL/HLSLResource.h"
27#include "llvm/IR/IRBuilder.h"
28#include "llvm/IR/Intrinsics.h"
29#include "llvm/IR/IntrinsicsDirectX.h"
30#include "llvm/IR/IntrinsicsSPIRV.h"
31
32#include <optional>
33#include <vector>
34
35// A function generator macro for picking the right intrinsic
36// for the target backend
37#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix) \
38 llvm::Intrinsic::ID get##FunctionName##Intrinsic() { \
39 llvm::Triple::ArchType Arch = getArch(); \
40 switch (Arch) { \
41 case llvm::Triple::dxil: \
42 return llvm::Intrinsic::dx_##IntrinsicPostfix; \
43 case llvm::Triple::spirv: \
44 return llvm::Intrinsic::spv_##IntrinsicPostfix; \
45 default: \
46 llvm_unreachable("Intrinsic " #IntrinsicPostfix \
47 " not supported by target architecture"); \
48 } \
49 }
50
51using ResourceClass = llvm::dxil::ResourceClass;
52
53namespace llvm {
54class GlobalVariable;
55class Function;
56class StructType;
57class Metadata;
58} // namespace llvm
59
60namespace clang {
61class NamedDecl;
62class VarDecl;
63class ParmVarDecl;
64class InitListExpr;
65class HLSLBufferDecl;
67class HLSLVkBindingAttr;
68class HLSLResourceBindingAttr;
69class Type;
70class RecordType;
71class DeclContext;
72class HLSLPackOffsetAttr;
74
75class FunctionDecl;
76
77namespace CodeGen {
78
79class CodeGenModule;
80class CodeGenFunction;
81class LValue;
82
85
86public:
87 static const uint32_t Unspecified = ~0U;
88
89 /// Iterates over all declarations in the HLSL buffer and based on the
90 /// packoffset or register(c#) annotations it fills outs the Offsets vector
91 /// with the user-specified layout offsets. The buffer offsets can be
92 /// specified 2 ways: 1. declarations in cbuffer {} block can have a
93 /// packoffset annotation (translates to HLSLPackOffsetAttr) 2. default
94 /// constant buffer declarations at global scope can have register(c#)
95 /// annotations (translates to HLSLResourceBindingAttr with RegisterType::C)
96 /// It is not guaranteed that all declarations in a buffer have an annotation.
97 /// For those where it is not specified a `~0U` value is added to the Offsets
98 /// vector. In the final layout these declarations will be placed at the end
99 /// of the HLSL buffer after all of the elements with specified offset.
100 static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl);
101
102 /// Comparison function for offsets received from `operator[]` suitable for
103 /// use in a `stable_sort`. This will order implicit bindings after explicit
104 /// offsets.
105 static bool compareOffsets(uint32_t LHS, uint32_t RHS) { return LHS < RHS; }
106
107 /// Get the given offset, or `~0U` if there is no offset for the member.
108 uint32_t operator[](size_t I) const {
109 if (Offsets.empty())
110 return Unspecified;
111 return Offsets[I];
112 }
113
114 bool empty() const { return Offsets.empty(); }
115};
116
118public:
119 //===----------------------------------------------------------------------===//
120 // Start of reserved area for HLSL intrinsic getters.
121 //===----------------------------------------------------------------------===//
122
128 GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,
129 flattened_thread_id_in_group)
135 GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)
139 GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
140 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupThreadId, thread_id_in_group)
141 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupId, group_id)
145 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
146 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)
147 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)
148 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)
149 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)
150 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
151 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveGetLaneCount, wave_get_lane_count)
152 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
153 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
154 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
155 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
159
160 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer,
161 resource_getpointer)
162 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding,
163 resource_handlefrombinding)
164 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding,
165 resource_handlefromimplicitbinding)
166 GENERATE_HLSL_INTRINSIC_FUNCTION(NonUniformResourceIndex,
167 resource_nonuniformindex)
168 GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
169 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
170 group_memory_barrier_with_group_sync)
171 GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
172 GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
173 GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
174 GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
175 GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
176
177 //===----------------------------------------------------------------------===//
178 // End of reserved area for HLSL intrinsic getters.
179 //===----------------------------------------------------------------------===//
180
181protected:
183
184 llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B,
185 const FunctionDecl *FD, llvm::Type *Type,
186 const clang::DeclaratorDecl *Decl,
187 HLSLAppliedSemanticAttr *Semantic,
188 std::optional<unsigned> Index);
189
190 void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
191 const clang::DeclaratorDecl *Decl,
192 HLSLAppliedSemanticAttr *Semantic,
193 std::optional<unsigned> Index);
194
195 llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B,
196 const FunctionDecl *FD,
197 llvm::Type *Type,
198 const clang::DeclaratorDecl *Decl,
199 HLSLAppliedSemanticAttr *Semantic);
200
201 void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
202 llvm::Value *Source,
203 const clang::DeclaratorDecl *Decl,
204 HLSLAppliedSemanticAttr *Semantic);
205
206 std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
208 llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
209 const clang::DeclaratorDecl *Decl,
210 specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
211 specific_attr_iterator<HLSLAppliedSemanticAttr> end);
212
213 specific_attr_iterator<HLSLAppliedSemanticAttr> handleStructSemanticStore(
214 llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
215 const clang::DeclaratorDecl *Decl,
216 specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
217 specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
218
219 std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
220 handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD,
222 specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
223 specific_attr_iterator<HLSLAppliedSemanticAttr> end);
224
225 specific_attr_iterator<HLSLAppliedSemanticAttr>
226 handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
227 llvm::Value *Source, const clang::DeclaratorDecl *Decl,
228 specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
229 specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
230
231public:
233 virtual ~CGHLSLRuntime() {}
234
235 llvm::Type *convertHLSLSpecificType(const Type *T,
236 const CGHLSLOffsetInfo &OffsetInfo);
237 llvm::Type *convertHLSLSpecificType(const Type *T) {
239 }
240
242
243 void addBuffer(const HLSLBufferDecl *D);
245 void finishCodeGen();
246
247 void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);
248
249 void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
250 void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);
251 void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var);
252
253 llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);
254
255 llvm::StructType *getHLSLBufferLayoutType(const RecordType *LayoutStructTy);
256 void addHLSLBufferLayoutType(const RecordType *LayoutStructTy,
257 llvm::StructType *LayoutTy);
259
260 std::optional<LValue>
262 CodeGenFunction &CGF);
263 bool emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr, CodeGenFunction &CGF);
264
265 std::optional<LValue> emitBufferArraySubscriptExpr(
266 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
267 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase);
268
269 bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
270 QualType CType);
271
273
274private:
275 void emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
276 llvm::GlobalVariable *BufGV,
277 const CGHLSLOffsetInfo &OffsetInfo);
278 void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
279 llvm::GlobalVariable *GV);
280 void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
281 llvm::GlobalVariable *GV,
282 HLSLResourceBindingAttr *RBA);
283
284 llvm::Value *emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
286 HLSLAppliedSemanticAttr *Semantic,
287 std::optional<unsigned> Index);
288 llvm::Value *emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
289 HLSLAppliedSemanticAttr *Semantic,
290 std::optional<unsigned> Index);
291 llvm::Value *emitUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
293 HLSLAppliedSemanticAttr *Semantic,
294 std::optional<unsigned> Index);
295
296 void emitSPIRVUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
298 HLSLAppliedSemanticAttr *Semantic,
299 std::optional<unsigned> Index);
300 void emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
301 HLSLAppliedSemanticAttr *Semantic,
302 std::optional<unsigned> Index);
303 void emitUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
305 HLSLAppliedSemanticAttr *Semantic,
306 std::optional<unsigned> Index);
307
308 llvm::Triple::ArchType getArch();
309
310 llvm::DenseMap<const clang::RecordType *, llvm::StructType *> LayoutTypes;
311 unsigned SPIRVLastAssignedInputSemanticLocation = 0;
312 unsigned SPIRVLastAssignedOutputSemanticLocation = 0;
313};
314
315} // namespace CodeGen
316} // namespace clang
317
318#endif
Defines enum values for all the target-independent builtin functions.
#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix)
llvm::dxil::ResourceClass ResourceClass
Defines helper utilities for supporting the HLSL runtime environment.
__DEVICE__ bool isnan(float __x)
Test for a NaN.
__DEVICE__ bool isinf(float __x)
Test for infinity value (+ve or -ve) .
__DEVICE__ double rsqrt(double __a)
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2721
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition Address.h:128
static const uint32_t Unspecified
static bool compareOffsets(uint32_t LHS, uint32_t RHS)
Comparison function for offsets received from operator[] suitable for use in a stable_sort.
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl)
Iterates over all declarations in the HLSL buffer and based on the packoffset or register(c#) annotat...
uint32_t operator[](size_t I) const
Get the given offset, or ~0U if there is no offset for the member.
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleStructSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
CGHLSLRuntime(CodeGenModule &CGM)
std::optional< LValue > emitBufferArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF, llvm::function_ref< llvm::Value *(bool Promote)> EmitIdxAfterBase)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
bool emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr, CodeGenFunction &CGF)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, QualType CType)
llvm::Type * convertHLSLSpecificType(const Type *T)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup, flattened_thread_id_in_group) GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer
void addBuffer(const HLSLBufferDecl *D)
void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
This class organizes the cross-function state that is used while generating LLVM code.
LValue - This represents an lvalue references.
Definition CGValue.h:183
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
This represents one expression.
Definition Expr.h:112
Represents a function declaration or definition.
Definition Decl.h:2000
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5190
Describes an C or C++ initializer list.
Definition Expr.h:5233
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3298
This represents a decl that may have a name.
Definition Decl.h:274
Represents a parameter to a function.
Definition Decl.h:1790
A (possibly-)qualified type.
Definition TypeBase.h:937
The base class of the type hierarchy.
Definition TypeBase.h:1833
Represents a variable declaration or definition.
Definition Decl.h:926
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:146
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
float __ovld __cnfn step(float, float)
Returns 0.0 if x < edge, otherwise it returns 1.0.
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn radians(float)
Converts degrees to radians, i.e.
float __ovld __cnfn degrees(float)
Converts radians to degrees, i.e.
int __ovld __cnfn all(char)
Returns 1 if the most significant bit in all components of x is set; otherwise returns 0.
float __ovld __cnfn normalize(float)
Returns a vector in the same direction as p but with a length of 1.
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
float4 __ovld __cnfn cross(float4, float4)
Returns the cross product of p0.xyz and p1.xyz.