brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 9c831b2 Raw
152 lines · cpp
1//===----- CGCUDARuntime.cpp - Interface to CUDA Runtimes -----------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This provides an abstract class for CUDA code generation.  Concrete10// subclasses of this implement code generation for specific CUDA11// runtime libraries.12//13//===----------------------------------------------------------------------===//14 15#include "CGCUDARuntime.h"16#include "CGCall.h"17#include "CodeGenFunction.h"18#include "clang/AST/ExprCXX.h"19 20using namespace clang;21using namespace CodeGen;22 23CGCUDARuntime::~CGCUDARuntime() {}24 25static llvm::Value *emitGetParamBuf(CodeGenFunction &CGF,26                                    const CUDAKernelCallExpr *E) {27  auto *GetParamBuf = CGF.getContext().getcudaGetParameterBufferDecl();28  const FunctionProtoType *GetParamBufProto =29      GetParamBuf->getType()->getAs<FunctionProtoType>();30 31  DeclRefExpr *DRE = DeclRefExpr::Create(32      CGF.getContext(), {}, {}, GetParamBuf,33      /*RefersToEnclosingVariableOrCapture=*/false, GetParamBuf->getNameInfo(),34      GetParamBuf->getType(), VK_PRValue);35  auto *ImpCast = ImplicitCastExpr::Create(36      CGF.getContext(), CGF.getContext().getPointerType(GetParamBuf->getType()),37      CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());38 39  CGCallee Callee = CGF.EmitCallee(ImpCast);40  CallArgList Args;41  // Use 64B alignment.42  Args.add(RValue::get(CGF.CGM.getSize(CharUnits::fromQuantity(64))),43           CGF.getContext().getSizeType());44  // Calculate parameter sizes.45  const PointerType *PT = E->getCallee()->getType()->getAs<PointerType>();46  const FunctionProtoType *FTP =47      PT->getPointeeType()->getAs<FunctionProtoType>();48  CharUnits Offset = CharUnits::Zero();49  for (auto ArgTy : FTP->getParamTypes()) {50    auto TInfo = CGF.CGM.getContext().getTypeInfoInChars(ArgTy);51    Offset = Offset.alignTo(TInfo.Align) + TInfo.Width;52  }53  Args.add(RValue::get(CGF.CGM.getSize(Offset)),54           CGF.getContext().getSizeType());55  const CGFunctionInfo &CallInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall(56      Args, GetParamBufProto, /*ChainCall=*/false);57  auto Ret = CGF.EmitCall(CallInfo, Callee, /*ReturnValue=*/{}, Args);58 59  return Ret.getScalarVal();60}61 62RValue CGCUDARuntime::EmitCUDADeviceKernelCallExpr(63    CodeGenFunction &CGF, const CUDAKernelCallExpr *E,64    ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke) {65  assert(CGM.getContext().getcudaLaunchDeviceDecl() ==66         E->getConfig()->getDirectCallee());67 68  llvm::BasicBlock *ConfigOKBlock = CGF.createBasicBlock("dkcall.configok");69  llvm::BasicBlock *ContBlock = CGF.createBasicBlock("dkcall.end");70 71  llvm::Value *Config = emitGetParamBuf(CGF, E);72  CGF.Builder.CreateCondBr(73      CGF.Builder.CreateICmpNE(Config,74                               llvm::Constant::getNullValue(Config->getType())),75      ConfigOKBlock, ContBlock);76 77  CodeGenFunction::ConditionalEvaluation eval(CGF);78 79  eval.begin(CGF);80  CGF.EmitBlock(ConfigOKBlock);81 82  QualType KernelCalleeFuncTy =83      E->getCallee()->getType()->getAs<PointerType>()->getPointeeType();84  CGCallee KernelCallee = CGF.EmitCallee(E->getCallee());85  // Emit kernel arguments.86  CallArgList KernelCallArgs;87  CGF.EmitCallArgs(KernelCallArgs,88                   KernelCalleeFuncTy->getAs<FunctionProtoType>(),89                   E->arguments(), E->getDirectCallee());90  // Copy emitted kernel arguments into that parameter buffer.91  RawAddress CfgBase(Config, CGM.Int8Ty,92                     /*Alignment=*/CharUnits::fromQuantity(64));93  CharUnits Offset = CharUnits::Zero();94  for (auto &Arg : KernelCallArgs) {95    auto TInfo = CGM.getContext().getTypeInfoInChars(Arg.getType());96    Offset = Offset.alignTo(TInfo.Align);97    Address Addr =98        CGF.Builder.CreateConstInBoundsGEP(CfgBase, Offset.getQuantity());99    Arg.copyInto(CGF, Addr);100    Offset += TInfo.Width;101  }102  // Make `cudaLaunchDevice` call, i.e. E->getConfig().103  const CallExpr *LaunchCall = E->getConfig();104  QualType LaunchCalleeFuncTy = LaunchCall->getCallee()105                                    ->getType()106                                    ->getAs<PointerType>()107                                    ->getPointeeType();108  CGCallee LaunchCallee = CGF.EmitCallee(LaunchCall->getCallee());109  CallArgList LaunchCallArgs;110  CGF.EmitCallArgs(LaunchCallArgs,111                   LaunchCalleeFuncTy->getAs<FunctionProtoType>(),112                   LaunchCall->arguments(), LaunchCall->getDirectCallee());113  // Replace func and paramterbuffer arguments.114  LaunchCallArgs[0] = CallArg(RValue::get(KernelCallee.getFunctionPointer()),115                              CGM.getContext().VoidPtrTy);116  LaunchCallArgs[1] = CallArg(RValue::get(Config), CGM.getContext().VoidPtrTy);117  const CGFunctionInfo &LaunchCallInfo = CGM.getTypes().arrangeFreeFunctionCall(118      LaunchCallArgs, LaunchCalleeFuncTy->getAs<FunctionProtoType>(),119      /*ChainCall=*/false);120  CGF.EmitCall(LaunchCallInfo, LaunchCallee, ReturnValue, LaunchCallArgs,121               CallOrInvoke,122               /*IsMustTail=*/false, E->getExprLoc());123  CGF.EmitBranch(ContBlock);124 125  CGF.EmitBlock(ContBlock);126  eval.end(CGF);127 128  return RValue::get(nullptr);129}130 131RValue CGCUDARuntime::EmitCUDAKernelCallExpr(CodeGenFunction &CGF,132                                             const CUDAKernelCallExpr *E,133                                             ReturnValueSlot ReturnValue,134                                             llvm::CallBase **CallOrInvoke) {135  llvm::BasicBlock *ConfigOKBlock = CGF.createBasicBlock("kcall.configok");136  llvm::BasicBlock *ContBlock = CGF.createBasicBlock("kcall.end");137 138  CodeGenFunction::ConditionalEvaluation eval(CGF);139  CGF.EmitBranchOnBoolExpr(E->getConfig(), ContBlock, ConfigOKBlock,140                           /*TrueCount=*/0);141 142  eval.begin(CGF);143  CGF.EmitBlock(ConfigOKBlock);144  CGF.EmitSimpleCallExpr(E, ReturnValue, CallOrInvoke);145  CGF.EmitBranch(ContBlock);146 147  CGF.EmitBlock(ContBlock);148  eval.end(CGF);149 150  return RValue::get(nullptr);151}152