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 "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/AST/Attr.h"
25#include "clang/AST/Decl.h"
28
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/Frontend/HLSL/HLSLResource.h"
32
33#include <optional>
34#include <vector>
35
36// A function generator macro for picking the right intrinsic
37// for the target backend
38#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix) \
39 llvm::Intrinsic::ID get##FunctionName##Intrinsic() { \
40 llvm::Triple::ArchType Arch = getArch(); \
41 switch (Arch) { \
42 case llvm::Triple::dxil: \
43 return llvm::Intrinsic::dx_##IntrinsicPostfix; \
44 case llvm::Triple::spirv: \
45 return llvm::Intrinsic::spv_##IntrinsicPostfix; \
46 default: \
47 llvm_unreachable("Intrinsic " #IntrinsicPostfix \
48 " not supported by target architecture"); \
49 } \
50 }
51
52using ResourceClass = llvm::dxil::ResourceClass;
53
54namespace llvm {
55class GlobalVariable;
56class Function;
57class StructType;
58class Metadata;
59} // namespace llvm
60
61namespace clang {
62class NamedDecl;
63class VarDecl;
64class ParmVarDecl;
65class InitListExpr;
66class HLSLBufferDecl;
68class HLSLVkBindingAttr;
69class HLSLResourceBindingAttr;
70class Type;
71class RecordType;
72class DeclContext;
73class HLSLPackOffsetAttr;
75
76class FunctionDecl;
77
78namespace CodeGen {
79
80class CodeGenModule;
81class CodeGenFunction;
82class LValue;
83
86
87public:
88 static const uint32_t Unspecified = ~0U;
89
90 /// Iterates over all declarations in the HLSL buffer and based on the
91 /// packoffset or register(c#) annotations it fills outs the Offsets vector
92 /// with the user-specified layout offsets. The buffer offsets can be
93 /// specified 2 ways: 1. declarations in cbuffer {} block can have a
94 /// packoffset annotation (translates to HLSLPackOffsetAttr) 2. default
95 /// constant buffer declarations at global scope can have register(c#)
96 /// annotations (translates to HLSLResourceBindingAttr with RegisterType::C)
97 /// It is not guaranteed that all declarations in a buffer have an annotation.
98 /// For those where it is not specified a `~0U` value is added to the Offsets
99 /// vector. In the final layout these declarations will be placed at the end
100 /// of the HLSL buffer after all of the elements with specified offset.
101 static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl);
102
103 /// Get the given offset, or `~0U` if there is no offset for the member.
104 uint32_t operator[](size_t I) const {
105 if (Offsets.empty())
106 return Unspecified;
107 return Offsets[I];
108 }
109};
110
112public:
113 //===----------------------------------------------------------------------===//
114 // Start of reserved area for HLSL intrinsic getters.
115 //===----------------------------------------------------------------------===//
116
122 GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,
123 flattened_thread_id_in_group)
129 GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)
133 GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
134 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupThreadId, thread_id_in_group)
135 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupId, group_id)
139 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
140 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)
141 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)
142 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)
143 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)
144 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
145 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveGetLaneCount, wave_get_lane_count)
146 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
147 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
148 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
149 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
153
154 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer,
155 resource_getpointer)
156 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding,
157 resource_handlefrombinding)
158 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding,
159 resource_handlefromimplicitbinding)
160 GENERATE_HLSL_INTRINSIC_FUNCTION(NonUniformResourceIndex,
161 resource_nonuniformindex)
162 GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
163 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
164 group_memory_barrier_with_group_sync)
165 GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
166
167 //===----------------------------------------------------------------------===//
168 // End of reserved area for HLSL intrinsic getters.
169 //===----------------------------------------------------------------------===//
170
171protected:
173
174 llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
175 const clang::DeclaratorDecl *Decl,
176 HLSLAppliedSemanticAttr *Semantic,
177 std::optional<unsigned> Index);
178
179 llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B,
180 const FunctionDecl *FD,
181 llvm::Type *Type,
182 const clang::DeclaratorDecl *Decl,
183 HLSLAppliedSemanticAttr *Semantic);
184
185 std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
187 llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
188 const clang::DeclaratorDecl *Decl,
189 specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
190 specific_attr_iterator<HLSLAppliedSemanticAttr> end);
191
192 std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
193 handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD,
195 specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
196 specific_attr_iterator<HLSLAppliedSemanticAttr> end);
197
198public:
200 virtual ~CGHLSLRuntime() {}
201
202 llvm::Type *convertHLSLSpecificType(const Type *T,
203 const CGHLSLOffsetInfo &OffsetInfo);
204 llvm::Type *convertHLSLSpecificType(const Type *T) {
206 }
207
209
210 void addBuffer(const HLSLBufferDecl *D);
212 void finishCodeGen();
213
214 void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);
215
216 void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
217 void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);
218 void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var);
219
220 llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);
221
222 llvm::TargetExtType *
223 getHLSLBufferLayoutType(const RecordType *LayoutStructTy);
224 void addHLSLBufferLayoutType(const RecordType *LayoutStructTy,
225 llvm::TargetExtType *LayoutTy);
227
228 std::optional<LValue>
230 CodeGenFunction &CGF);
231
232private:
233 void emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
234 llvm::GlobalVariable *BufGV);
235 void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
236 llvm::GlobalVariable *GV);
237 void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
238 llvm::GlobalVariable *GV,
239 HLSLResourceBindingAttr *RBA);
240
241 llvm::Value *emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
242 HLSLAppliedSemanticAttr *Semantic,
243 std::optional<unsigned> Index);
244 llvm::Value *emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
245 HLSLAppliedSemanticAttr *Semantic,
246 std::optional<unsigned> Index);
247 llvm::Value *emitUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
249 HLSLAppliedSemanticAttr *Semantic,
250 std::optional<unsigned> Index);
251
252 llvm::Triple::ArchType getArch();
253
254 llvm::DenseMap<const clang::RecordType *, llvm::TargetExtType *> LayoutTypes;
255 unsigned SPIRVLastAssignedInputSemanticLocation = 0;
256};
257
258} // namespace CodeGen
259} // namespace clang
260
261#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
static const uint32_t Unspecified
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)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::TargetExtType *LayoutTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
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)
llvm::TargetExtType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, 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 > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
llvm::Type * convertHLSLSpecificType(const Type *T)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
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)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
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:182
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
Represents a function declaration or definition.
Definition Decl.h:2000
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5176
Describes an C or C++ initializer list.
Definition Expr.h:5233
This represents a decl that may have a name.
Definition Decl.h:274
Represents a parameter to a function.
Definition Decl.h:1790
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:154
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:145
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.