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/Basic/Builtins.h" 25 #include "clang/Basic/HLSLRuntime.h" 26 27 #include "llvm/ADT/SmallVector.h" 28 #include "llvm/ADT/StringRef.h" 29 #include "llvm/Frontend/HLSL/HLSLResource.h" 30 31 #include <optional> 32 #include <vector> 33 34 // A function generator macro for picking the right intrinsic 35 // for the target backend 36 #define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix) \ 37 llvm::Intrinsic::ID get##FunctionName##Intrinsic() { \ 38 llvm::Triple::ArchType Arch = getArch(); \ 39 switch (Arch) { \ 40 case llvm::Triple::dxil: \ 41 return llvm::Intrinsic::dx_##IntrinsicPostfix; \ 42 case llvm::Triple::spirv: \ 43 return llvm::Intrinsic::spv_##IntrinsicPostfix; \ 44 default: \ 45 llvm_unreachable("Intrinsic " #IntrinsicPostfix \ 46 " not supported by target architecture"); \ 47 } \ 48 } 49 50 using ResourceClass = llvm::dxil::ResourceClass; 51 52 namespace llvm { 53 class GlobalVariable; 54 class Function; 55 class StructType; 56 class Metadata; 57 } // namespace llvm 58 59 namespace clang { 60 class NamedDecl; 61 class VarDecl; 62 class ParmVarDecl; 63 class InitListExpr; 64 class HLSLBufferDecl; 65 class HLSLResourceBindingAttr; 66 class Type; 67 class RecordType; 68 class DeclContext; 69 class HLSLPackOffsetAttr; 70 71 class FunctionDecl; 72 73 namespace CodeGen { 74 75 class CodeGenModule; 76 class CodeGenFunction; 77 78 class CGHLSLRuntime { 79 public: 80 //===----------------------------------------------------------------------===// 81 // Start of reserved area for HLSL intrinsic getters. 82 //===----------------------------------------------------------------------===// 83 84 GENERATE_HLSL_INTRINSIC_FUNCTION(All, all) 85 GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any) 86 GENERATE_HLSL_INTRINSIC_FUNCTION(Cross, cross) 87 GENERATE_HLSL_INTRINSIC_FUNCTION(Degrees, degrees) 88 GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac) 89 GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup, 90 flattened_thread_id_in_group) 91 GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp) 92 GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize) 93 GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt) 94 GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate) 95 GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign) 96 GENERATE_HLSL_INTRINSIC_FUNCTION(Step, step) 97 GENERATE_HLSL_INTRINSIC_FUNCTION(Radians, radians) 98 GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id) 99 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupThreadId, thread_id_in_group) 100 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupId, group_id) 101 GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot) 102 GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot) 103 GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) 104 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed) 105 GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed) 106 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all) 107 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any) 108 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) 109 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) 110 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveGetLaneCount, wave_get_lane_count) 111 GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) 112 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) 113 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) 114 GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow) 115 GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp) 116 GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp) 117 GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp) 118 119 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer, 120 resource_getpointer) 121 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, 122 resource_handlefrombinding) 123 GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding, 124 resource_handlefromimplicitbinding) 125 GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) 126 GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, 127 group_memory_barrier_with_group_sync) 128 129 //===----------------------------------------------------------------------===// 130 // End of reserved area for HLSL intrinsic getters. 131 //===----------------------------------------------------------------------===// 132 133 protected: 134 CodeGenModule &CGM; 135 136 llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D, 137 llvm::Type *Ty); 138 139 public: CGHLSLRuntime(CodeGenModule & CGM)140 CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} ~CGHLSLRuntime()141 virtual ~CGHLSLRuntime() {} 142 143 llvm::Type * 144 convertHLSLSpecificType(const Type *T, 145 SmallVector<int32_t> *Packoffsets = nullptr); 146 147 void generateGlobalCtorDtorCalls(); 148 149 void addBuffer(const HLSLBufferDecl *D); 150 void finishCodeGen(); 151 152 void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn); 153 154 void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn); 155 void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn); 156 void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var); 157 158 llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB); 159 160 llvm::TargetExtType * 161 getHLSLBufferLayoutType(const RecordType *LayoutStructTy); 162 void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, 163 llvm::TargetExtType *LayoutTy); 164 void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E); 165 166 private: 167 void emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl, 168 llvm::GlobalVariable *BufGV); 169 void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl, 170 llvm::GlobalVariable *GV, 171 HLSLResourceBindingAttr *RBA); 172 llvm::Triple::ArchType getArch(); 173 174 llvm::DenseMap<const clang::RecordType *, llvm::TargetExtType *> LayoutTypes; 175 }; 176 177 } // namespace CodeGen 178 } // namespace clang 179 180 #endif 181