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(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 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("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(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 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, "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, "kernel_arg_type_qual"); 83 } 84 85 } // namespace llvm 86