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
17using namespace clang;
18using namespace CodeGen;
19
20static 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(Kind: llvm::Attribute::MustProgress);
26}
27
28void 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>(Val: 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(in_start: OutlinedFnDecl->param_begin(), in_end: OutlinedFnDecl->param_end());
49
50 // Compute the function info and LLVM function type.
51 const CGFunctionInfo &FnInfo =
52 getTypes().arrangeSYCLKernelCallerDeclaration(resultType: Ctx.VoidTy, args: Args);
53 llvm::FunctionType *FnTy = getTypes().GetFunctionType(Info: FnInfo);
54
55 // Retrieve the generated name for the SYCL kernel caller function.
56 CanQualType KernelNameType =
57 Ctx.getCanonicalType(T: KernelEntryPointAttr->getKernelName());
58 const SYCLKernelInfo &KernelInfo = Ctx.getSYCLKernelInfo(T: KernelNameType);
59 auto *Fn = llvm::Function::Create(Ty: FnTy, Linkage: llvm::Function::ExternalLinkage,
60 N: KernelInfo.GetKernelName(), M: &getModule());
61
62 // Emit the SYCL kernel caller function.
63 CodeGenFunction CGF(*this);
64 SetLLVMFunctionAttributes(GD: GlobalDecl(), Info: FnInfo, F: Fn, IsThunk: false);
65 SetSYCLKernelAttributes(Fn, CGF);
66 CGF.StartFunction(GD: GlobalDecl(), RetTy: Ctx.VoidTy, Fn, FnInfo, Args,
67 Loc: SourceLocation(), StartLoc: SourceLocation());
68 CGF.EmitFunctionBody(Body: OutlinedFnDecl->getBody());
69 setDSOLocal(Fn);
70 SetLLVMFunctionAttributesForDefinition(D: cast<Decl>(Val: OutlinedFnDecl), F: Fn);
71 CGF.FinishFunction();
72}
73