xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CodeGenSYCL.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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