10b57cec5SDimitry Andric //===----- CGCUDARuntime.h - Interface to CUDA Runtimes ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This provides an abstract class for CUDA code generation.  Concrete
100b57cec5SDimitry Andric // subclasses of this implement code generation for specific CUDA
110b57cec5SDimitry Andric // runtime libraries.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H
160b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H
170b57cec5SDimitry Andric 
18fe6060f1SDimitry Andric #include "clang/AST/GlobalDecl.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
205f757f3fSDimitry Andric #include "llvm/Frontend/Offloading/Utility.h"
21fe6060f1SDimitry Andric #include "llvm/IR/GlobalValue.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace llvm {
240b57cec5SDimitry Andric class Function;
250b57cec5SDimitry Andric class GlobalVariable;
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace clang {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric class CUDAKernelCallExpr;
315ffd83dbSDimitry Andric class NamedDecl;
320b57cec5SDimitry Andric class VarDecl;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric namespace CodeGen {
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric class CodeGenFunction;
370b57cec5SDimitry Andric class CodeGenModule;
380b57cec5SDimitry Andric class FunctionArgList;
390b57cec5SDimitry Andric class ReturnValueSlot;
400b57cec5SDimitry Andric class RValue;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric class CGCUDARuntime {
430b57cec5SDimitry Andric protected:
440b57cec5SDimitry Andric   CodeGenModule &CGM;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric public:
470b57cec5SDimitry Andric   // Global variable properties that must be passed to CUDA runtime.
485ffd83dbSDimitry Andric   class DeviceVarFlags {
495ffd83dbSDimitry Andric   public:
505ffd83dbSDimitry Andric     enum DeviceVarKind {
515ffd83dbSDimitry Andric       Variable, // Variable
525ffd83dbSDimitry Andric       Surface,  // Builtin surface
535ffd83dbSDimitry Andric       Texture,  // Builtin texture
545ffd83dbSDimitry Andric     };
555ffd83dbSDimitry Andric 
565ffd83dbSDimitry Andric   private:
575ffd83dbSDimitry Andric     unsigned Kind : 2;
585ffd83dbSDimitry Andric     unsigned Extern : 1;
595ffd83dbSDimitry Andric     unsigned Constant : 1;   // Constant variable.
60e8d8bef9SDimitry Andric     unsigned Managed : 1;    // Managed variable.
615ffd83dbSDimitry Andric     unsigned Normalized : 1; // Normalized texture.
625ffd83dbSDimitry Andric     int SurfTexType;         // Type of surface/texutre.
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric   public:
DeviceVarFlags(DeviceVarKind K,bool E,bool C,bool M,bool N,int T)65e8d8bef9SDimitry Andric     DeviceVarFlags(DeviceVarKind K, bool E, bool C, bool M, bool N, int T)
66e8d8bef9SDimitry Andric         : Kind(K), Extern(E), Constant(C), Managed(M), Normalized(N),
67e8d8bef9SDimitry Andric           SurfTexType(T) {}
685ffd83dbSDimitry Andric 
getKind()695ffd83dbSDimitry Andric     DeviceVarKind getKind() const { return static_cast<DeviceVarKind>(Kind); }
isExtern()705ffd83dbSDimitry Andric     bool isExtern() const { return Extern; }
isConstant()715ffd83dbSDimitry Andric     bool isConstant() const { return Constant; }
isManaged()72e8d8bef9SDimitry Andric     bool isManaged() const { return Managed; }
isNormalized()735ffd83dbSDimitry Andric     bool isNormalized() const { return Normalized; }
getSurfTexType()745ffd83dbSDimitry Andric     int getSurfTexType() const { return SurfTexType; }
750b57cec5SDimitry Andric   };
760b57cec5SDimitry Andric 
CGCUDARuntime(CodeGenModule & CGM)770b57cec5SDimitry Andric   CGCUDARuntime(CodeGenModule &CGM) : CGM(CGM) {}
780b57cec5SDimitry Andric   virtual ~CGCUDARuntime();
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   virtual RValue EmitCUDAKernelCallExpr(CodeGenFunction &CGF,
810b57cec5SDimitry Andric                                         const CUDAKernelCallExpr *E,
820b57cec5SDimitry Andric                                         ReturnValueSlot ReturnValue);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   /// Emits a kernel launch stub.
850b57cec5SDimitry Andric   virtual void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) = 0;
860b57cec5SDimitry Andric 
87fe6060f1SDimitry Andric   /// Check whether a variable is a device variable and register it if true.
88fe6060f1SDimitry Andric   virtual void handleVarRegistration(const VarDecl *VD,
89fe6060f1SDimitry Andric                                      llvm::GlobalVariable &Var) = 0;
900b57cec5SDimitry Andric 
91fe6060f1SDimitry Andric   /// Finalize generated LLVM module. Returns a module constructor function
92fe6060f1SDimitry Andric   /// to be added or a null pointer.
93fe6060f1SDimitry Andric   virtual llvm::Function *finalizeModule() = 0;
940b57cec5SDimitry Andric 
955ffd83dbSDimitry Andric   /// Returns function or variable name on device side even if the current
965ffd83dbSDimitry Andric   /// compilation is for host.
975ffd83dbSDimitry Andric   virtual std::string getDeviceSideName(const NamedDecl *ND) = 0;
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric   /// Get kernel handle by stub function.
100fe6060f1SDimitry Andric   virtual llvm::GlobalValue *getKernelHandle(llvm::Function *Stub,
101fe6060f1SDimitry Andric                                              GlobalDecl GD) = 0;
102fe6060f1SDimitry Andric 
103fe6060f1SDimitry Andric   /// Get kernel stub by kernel handle.
104fe6060f1SDimitry Andric   virtual llvm::Function *getKernelStub(llvm::GlobalValue *Handle) = 0;
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric   /// Adjust linkage of shadow variables in host compilation.
107fe6060f1SDimitry Andric   virtual void
108fe6060f1SDimitry Andric   internalizeDeviceSideVar(const VarDecl *D,
109fe6060f1SDimitry Andric                            llvm::GlobalValue::LinkageTypes &Linkage) = 0;
1100b57cec5SDimitry Andric };
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric /// Creates an instance of a CUDA runtime class.
1130b57cec5SDimitry Andric CGCUDARuntime *CreateNVCUDARuntime(CodeGenModule &CGM);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric #endif
119