//===--- 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, const 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(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(Operand); if (MaybeValue && dyn_cast(MaybeValue->getValue())->getName() == F.getName()) { FoundLoweredKernelFunction = true; continue; } if (MaybeValue && FoundLoweredKernelFunction) return nullptr; MDNode *MaybeNode = dyn_cast(Operand); if (FoundLoweredKernelFunction && MaybeNode && cast(MaybeNode->getOperand(0))->getString() == AttributeName && MDArgIdx < MaybeNode->getNumOperands()) return cast(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"); } MDString *getOCLKernelArgTypeQual(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_type_qual"); } } // namespace llvm