xref: /llvm-project/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp (revision 43222bd3091db5403e3320d23a241a534c1eefec)
1*0fbaf03fSMichal Paszkowski //===--- SPIRVMetadata.cpp ---- IR Metadata Parsing Funcs -------*- C++ -*-===//
2*0fbaf03fSMichal Paszkowski //
3*0fbaf03fSMichal Paszkowski // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fbaf03fSMichal Paszkowski // See https://llvm.org/LICENSE.txt for license information.
5*0fbaf03fSMichal Paszkowski // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fbaf03fSMichal Paszkowski //
7*0fbaf03fSMichal Paszkowski //===----------------------------------------------------------------------===//
8*0fbaf03fSMichal Paszkowski //
9*0fbaf03fSMichal Paszkowski // This file contains functions needed for parsing LLVM IR metadata relevant
10*0fbaf03fSMichal Paszkowski // to the SPIR-V target.
11*0fbaf03fSMichal Paszkowski //
12*0fbaf03fSMichal Paszkowski //===----------------------------------------------------------------------===//
13*0fbaf03fSMichal Paszkowski 
14*0fbaf03fSMichal Paszkowski #include "SPIRVMetadata.h"
15*0fbaf03fSMichal Paszkowski 
16*0fbaf03fSMichal Paszkowski using namespace llvm;
17*0fbaf03fSMichal Paszkowski 
getOCLKernelArgAttribute(const Function & F,unsigned ArgIdx,const StringRef AttributeName)18*0fbaf03fSMichal Paszkowski static MDString *getOCLKernelArgAttribute(const Function &F, unsigned ArgIdx,
19*0fbaf03fSMichal Paszkowski                                           const StringRef AttributeName) {
20*0fbaf03fSMichal Paszkowski   assert(
21*0fbaf03fSMichal Paszkowski       F.getCallingConv() == CallingConv::SPIR_KERNEL &&
22*0fbaf03fSMichal Paszkowski       "Kernel attributes are attached/belong only to OpenCL kernel functions");
23*0fbaf03fSMichal Paszkowski 
24*0fbaf03fSMichal Paszkowski   // Lookup the argument attribute in metadata attached to the kernel function.
25*0fbaf03fSMichal Paszkowski   MDNode *Node = F.getMetadata(AttributeName);
26*0fbaf03fSMichal Paszkowski   if (Node && ArgIdx < Node->getNumOperands())
27*0fbaf03fSMichal Paszkowski     return cast<MDString>(Node->getOperand(ArgIdx));
28*0fbaf03fSMichal Paszkowski 
29*0fbaf03fSMichal Paszkowski   // Sometimes metadata containing kernel attributes is not attached to the
30*0fbaf03fSMichal Paszkowski   // function, but can be found in the named module-level metadata instead.
31*0fbaf03fSMichal Paszkowski   // For example:
32*0fbaf03fSMichal Paszkowski   //   !opencl.kernels = !{!0}
33*0fbaf03fSMichal Paszkowski   //   !0 = !{void ()* @someKernelFunction, !1, ...}
34*0fbaf03fSMichal Paszkowski   //   !1 = !{!"kernel_arg_addr_space", ...}
35*0fbaf03fSMichal Paszkowski   // In this case the actual index of searched argument attribute is ArgIdx + 1,
36*0fbaf03fSMichal Paszkowski   // since the first metadata node operand is occupied by attribute name
37*0fbaf03fSMichal Paszkowski   // ("kernel_arg_addr_space" in the example above).
38*0fbaf03fSMichal Paszkowski   unsigned MDArgIdx = ArgIdx + 1;
39*0fbaf03fSMichal Paszkowski   NamedMDNode *OpenCLKernelsMD =
40*0fbaf03fSMichal Paszkowski       F.getParent()->getNamedMetadata("opencl.kernels");
41*0fbaf03fSMichal Paszkowski   if (!OpenCLKernelsMD || OpenCLKernelsMD->getNumOperands() == 0)
42*0fbaf03fSMichal Paszkowski     return nullptr;
43*0fbaf03fSMichal Paszkowski 
44*0fbaf03fSMichal Paszkowski   // KernelToMDNodeList contains kernel function declarations followed by
45*0fbaf03fSMichal Paszkowski   // corresponding MDNodes for each attribute. Search only MDNodes "belonging"
46*0fbaf03fSMichal Paszkowski   // to the currently lowered kernel function.
47*0fbaf03fSMichal Paszkowski   MDNode *KernelToMDNodeList = OpenCLKernelsMD->getOperand(0);
48*0fbaf03fSMichal Paszkowski   bool FoundLoweredKernelFunction = false;
49*0fbaf03fSMichal Paszkowski   for (const MDOperand &Operand : KernelToMDNodeList->operands()) {
50*0fbaf03fSMichal Paszkowski     ValueAsMetadata *MaybeValue = dyn_cast<ValueAsMetadata>(Operand);
51*0fbaf03fSMichal Paszkowski     if (MaybeValue &&
52*0fbaf03fSMichal Paszkowski         dyn_cast<Function>(MaybeValue->getValue())->getName() == F.getName()) {
53*0fbaf03fSMichal Paszkowski       FoundLoweredKernelFunction = true;
54*0fbaf03fSMichal Paszkowski       continue;
55*0fbaf03fSMichal Paszkowski     }
56*0fbaf03fSMichal Paszkowski     if (MaybeValue && FoundLoweredKernelFunction)
57*0fbaf03fSMichal Paszkowski       return nullptr;
58*0fbaf03fSMichal Paszkowski 
59*0fbaf03fSMichal Paszkowski     MDNode *MaybeNode = dyn_cast<MDNode>(Operand);
60*0fbaf03fSMichal Paszkowski     if (FoundLoweredKernelFunction && MaybeNode &&
61*0fbaf03fSMichal Paszkowski         cast<MDString>(MaybeNode->getOperand(0))->getString() ==
62*0fbaf03fSMichal Paszkowski             AttributeName &&
63*0fbaf03fSMichal Paszkowski         MDArgIdx < MaybeNode->getNumOperands())
64*0fbaf03fSMichal Paszkowski       return cast<MDString>(MaybeNode->getOperand(MDArgIdx));
65*0fbaf03fSMichal Paszkowski   }
66*0fbaf03fSMichal Paszkowski   return nullptr;
67*0fbaf03fSMichal Paszkowski }
68*0fbaf03fSMichal Paszkowski 
69*0fbaf03fSMichal Paszkowski namespace llvm {
70*0fbaf03fSMichal Paszkowski 
getOCLKernelArgAccessQual(const Function & F,unsigned ArgIdx)71*0fbaf03fSMichal Paszkowski MDString *getOCLKernelArgAccessQual(const Function &F, unsigned ArgIdx) {
72*0fbaf03fSMichal Paszkowski   assert(
73*0fbaf03fSMichal Paszkowski       F.getCallingConv() == CallingConv::SPIR_KERNEL &&
74*0fbaf03fSMichal Paszkowski       "Kernel attributes are attached/belong only to OpenCL kernel functions");
75*0fbaf03fSMichal Paszkowski   return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_access_qual");
76*0fbaf03fSMichal Paszkowski }
77*0fbaf03fSMichal Paszkowski 
getOCLKernelArgTypeQual(const Function & F,unsigned ArgIdx)78*0fbaf03fSMichal Paszkowski MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx) {
79*0fbaf03fSMichal Paszkowski   assert(
80*0fbaf03fSMichal Paszkowski       F.getCallingConv() == CallingConv::SPIR_KERNEL &&
81*0fbaf03fSMichal Paszkowski       "Kernel attributes are attached/belong only to OpenCL kernel functions");
82*0fbaf03fSMichal Paszkowski   return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type_qual");
83*0fbaf03fSMichal Paszkowski }
84*0fbaf03fSMichal Paszkowski 
85*0fbaf03fSMichal Paszkowski } // namespace llvm
86