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