1 //===--------- CodeGenSYCL.cpp - Code for SYCL kernel generation ----------===// 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 contains code required for generation of SYCL kernel caller offload 10 // entry point functions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CodeGenFunction.h" 15 #include "CodeGenModule.h" 16 17 using namespace clang; 18 using namespace CodeGen; 19 20 static void SetSYCLKernelAttributes(llvm::Function *Fn, CodeGenFunction &CGF) { 21 // SYCL 2020 device language restrictions require forward progress and 22 // disallow recursion. 23 Fn->setDoesNotRecurse(); 24 if (CGF.checkIfFunctionMustProgress()) 25 Fn->addFnAttr(llvm::Attribute::MustProgress); 26 } 27 28 void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl *KernelEntryPointFn, 29 ASTContext &Ctx) { 30 assert(Ctx.getLangOpts().SYCLIsDevice && 31 "SYCL kernel caller offload entry point functions can only be emitted" 32 " during device compilation"); 33 34 const auto *KernelEntryPointAttr = 35 KernelEntryPointFn->getAttr<SYCLKernelEntryPointAttr>(); 36 assert(KernelEntryPointAttr && "Missing sycl_kernel_entry_point attribute"); 37 assert(!KernelEntryPointAttr->isInvalidAttr() && 38 "sycl_kernel_entry_point attribute is invalid"); 39 40 // Find the SYCLKernelCallStmt. 41 SYCLKernelCallStmt *KernelCallStmt = 42 cast<SYCLKernelCallStmt>(KernelEntryPointFn->getBody()); 43 44 // Retrieve the SYCL kernel caller parameters from the OutlinedFunctionDecl. 45 FunctionArgList Args; 46 const OutlinedFunctionDecl *OutlinedFnDecl = 47 KernelCallStmt->getOutlinedFunctionDecl(); 48 Args.append(OutlinedFnDecl->param_begin(), OutlinedFnDecl->param_end()); 49 50 // Compute the function info and LLVM function type. 51 const CGFunctionInfo &FnInfo = 52 getTypes().arrangeSYCLKernelCallerDeclaration(Ctx.VoidTy, Args); 53 llvm::FunctionType *FnTy = getTypes().GetFunctionType(FnInfo); 54 55 // Retrieve the generated name for the SYCL kernel caller function. 56 CanQualType KernelNameType = 57 Ctx.getCanonicalType(KernelEntryPointAttr->getKernelName()); 58 const SYCLKernelInfo &KernelInfo = Ctx.getSYCLKernelInfo(KernelNameType); 59 auto *Fn = llvm::Function::Create(FnTy, llvm::Function::ExternalLinkage, 60 KernelInfo.GetKernelName(), &getModule()); 61 62 // Emit the SYCL kernel caller function. 63 CodeGenFunction CGF(*this); 64 SetLLVMFunctionAttributes(GlobalDecl(), FnInfo, Fn, false); 65 SetSYCLKernelAttributes(Fn, CGF); 66 CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, FnInfo, Args, 67 SourceLocation(), SourceLocation()); 68 CGF.EmitFunctionBody(OutlinedFnDecl->getBody()); 69 setDSOLocal(Fn); 70 SetLLVMFunctionAttributesForDefinition(cast<Decl>(OutlinedFnDecl), Fn); 71 CGF.FinishFunction(); 72 } 73