86 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains functions needed for parsing LLVM IR metadata relevant10// to the SPIR-V target.11//12//===----------------------------------------------------------------------===//13 14#include "SPIRVMetadata.h"15 16using namespace llvm;17 18static 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(AttributeName);26 if (Node && ArgIdx < Node->getNumOperands())27 return cast<MDString>(Node->getOperand(ArgIdx));28 29 // Sometimes metadata containing kernel attributes is not attached to the30 // 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 name37 // ("kernel_arg_addr_space" in the example above).38 unsigned MDArgIdx = ArgIdx + 1;39 NamedMDNode *OpenCLKernelsMD =40 F.getParent()->getNamedMetadata("opencl.kernels");41 if (!OpenCLKernelsMD || OpenCLKernelsMD->getNumOperands() == 0)42 return nullptr;43 44 // KernelToMDNodeList contains kernel function declarations followed by45 // corresponding MDNodes for each attribute. Search only MDNodes "belonging"46 // to the currently lowered kernel function.47 MDNode *KernelToMDNodeList = OpenCLKernelsMD->getOperand(0);48 bool FoundLoweredKernelFunction = false;49 for (const MDOperand &Operand : KernelToMDNodeList->operands()) {50 ValueAsMetadata *MaybeValue = dyn_cast<ValueAsMetadata>(Operand);51 if (MaybeValue &&52 dyn_cast<Function>(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>(Operand);60 if (FoundLoweredKernelFunction && MaybeNode &&61 cast<MDString>(MaybeNode->getOperand(0))->getString() ==62 AttributeName &&63 MDArgIdx < MaybeNode->getNumOperands())64 return cast<MDString>(MaybeNode->getOperand(MDArgIdx));65 }66 return nullptr;67}68 69namespace llvm {70 71MDString *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, "kernel_arg_access_qual");76}77 78MDString *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, "kernel_arg_type_qual");83}84 85} // namespace llvm86