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
SetSYCLKernelAttributes(llvm::Function * Fn,CodeGenFunction & CGF)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
EmitSYCLKernelCaller(const FunctionDecl * KernelEntryPointFn,ASTContext & Ctx)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