| //===--- SPIRVMetadata.cpp ---- IR Metadata Parsing Funcs -------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains functions needed for parsing LLVM IR metadata relevant | |
| // to the SPIR-V target. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "SPIRVMetadata.h" | |
| using namespace llvm; | |
| static MDString *getOCLKernelArgAttribute(const Function &F, unsigned ArgIdx, | |
| StringRef AttributeName) { | |
| assert( | |
| F.getCallingConv() == CallingConv::SPIR_KERNEL && | |
| "Kernel attributes are attached/belong only to OpenCL kernel functions"); | |
| // Lookup the argument attribute in metadata attached to the kernel function. | |
| MDNode *Node = F.getMetadata(AttributeName); | |
| if (Node && ArgIdx < Node->getNumOperands()) | |
| return cast<MDString>(Node->getOperand(ArgIdx)); | |
| // Sometimes metadata containing kernel attributes is not attached to the | |
| // function, but can be found in the named module-level metadata instead. | |
| // For example: | |
| // !opencl.kernels = !{!0} | |
| // !0 = !{void ()* @someKernelFunction, !1, ...} | |
| // !1 = !{!"kernel_arg_addr_space", ...} | |
| // In this case the actual index of searched argument attribute is ArgIdx + 1, | |
| // since the first metadata node operand is occupied by attribute name | |
| // ("kernel_arg_addr_space" in the example above). | |
| unsigned MDArgIdx = ArgIdx + 1; | |
| NamedMDNode *OpenCLKernelsMD = | |
| F.getParent()->getNamedMetadata("opencl.kernels"); | |
| if (!OpenCLKernelsMD || OpenCLKernelsMD->getNumOperands() == 0) | |
| return nullptr; | |
| // KernelToMDNodeList contains kernel function declarations followed by | |
| // corresponding MDNodes for each attribute. Search only MDNodes "belonging" | |
| // to the currently lowered kernel function. | |
| MDNode *KernelToMDNodeList = OpenCLKernelsMD->getOperand(0); | |
| bool FoundLoweredKernelFunction = false; | |
| for (const MDOperand &Operand : KernelToMDNodeList->operands()) { | |
| ValueAsMetadata *MaybeValue = dyn_cast<ValueAsMetadata>(Operand); | |
| if (MaybeValue && | |
| dyn_cast<Function>(MaybeValue->getValue())->getName() == F.getName()) { | |
| FoundLoweredKernelFunction = true; | |
| continue; | |
| } | |
| if (MaybeValue && FoundLoweredKernelFunction) | |
| return nullptr; | |
| MDNode *MaybeNode = dyn_cast<MDNode>(Operand); | |
| if (FoundLoweredKernelFunction && MaybeNode && | |
| cast<MDString>(MaybeNode->getOperand(0))->getString() == | |
| AttributeName && | |
| MDArgIdx < MaybeNode->getNumOperands()) | |
| return cast<MDString>(MaybeNode->getOperand(MDArgIdx)); | |
| } | |
| return nullptr; | |
| } | |
| namespace llvm { | |
| MDString *getOCLKernelArgAccessQual(const Function &F, unsigned ArgIdx) { | |
| assert( | |
| F.getCallingConv() == CallingConv::SPIR_KERNEL && | |
| "Kernel attributes are attached/belong only to OpenCL kernel functions"); | |
| return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_access_qual"); | |
| } | |
| } // namespace llvm |