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