11#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
12#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
13#include "mlir/IR/Builders.h"
15#include "llvm/ADT/TypeSwitch.h"
16#include "llvm/Support/ErrorHandling.h"
22class LLVMMetadataNodeBuilder {
24 explicit LLVMMetadataNodeBuilder(mlir::MLIRContext *ctx) : ctx(ctx) {}
26 mlir::LLVM::MDConstantAttr getI32(
unsigned value)
const {
27 mlir::IntegerType intTy = mlir::IntegerType::get(ctx, 32);
28 mlir::IntegerAttr intAttr = mlir::IntegerAttr::get(intTy, value);
29 return mlir::LLVM::MDConstantAttr::get(ctx, intAttr);
32 mlir::LLVM::MDStringAttr getString(llvm::StringRef value)
const {
33 return mlir::LLVM::MDStringAttr::get(ctx,
34 mlir::StringAttr::get(ctx, value));
37 mlir::LLVM::MDNodeAttr
38 getNode(llvm::ArrayRef<mlir::Attribute> metadata)
const {
39 return mlir::LLVM::MDNodeAttr::get(ctx, metadata);
42 mlir::LLVM::MDNodeAttr getI32Node(llvm::ArrayRef<unsigned> values)
const {
43 llvm::SmallVector<mlir::Attribute> metadata;
44 for (
unsigned value : values)
45 metadata.push_back(getI32(value));
49 mlir::LLVM::MDNodeAttr getStringNode(mlir::ArrayAttr attrs)
const {
50 llvm::SmallVector<mlir::Attribute> metadata;
51 for (mlir::StringAttr attr : attrs.getAsRange<mlir::StringAttr>())
52 metadata.push_back(getString(
attr.getValue()));
57 mlir::MLIRContext *ctx;
60using KernelArgStringMetadataGetter =
61 mlir::ArrayAttr (cir::OpenCLKernelArgMetadataAttr::*)()
const;
63struct KernelArgStringMetadataMapping {
64 llvm::StringLiteral metadataName;
65 KernelArgStringMetadataGetter getMetadata;
69static unsigned getOpenCLArgInfoAddressSpace(cir::LangAddressSpace as) {
71 case cir::LangAddressSpace::Default:
72 case cir::LangAddressSpace::OffloadPrivate:
74 case cir::LangAddressSpace::OffloadGlobal:
76 case cir::LangAddressSpace::OffloadConstant:
78 case cir::LangAddressSpace::OffloadLocal:
80 case cir::LangAddressSpace::OffloadGeneric:
82 case cir::LangAddressSpace::OffloadGlobalDevice:
84 case cir::LangAddressSpace::OffloadGlobalHost:
87 llvm_unreachable(
"unknown CIR language address space");
90static mlir::LLVM::MDNodeAttr
91getAddrSpaceMetadataNode(cir::OpenCLKernelArgMetadataAttr clArgMetadata,
92 const LLVMMetadataNodeBuilder &metadataBuilder) {
93 llvm::SmallVector<unsigned> addrSpaces;
94 for (cir::LangAddressSpaceAttr addressSpace :
95 clArgMetadata.getAddrSpace().getAsRange<cir::LangAddressSpaceAttr>())
96 addrSpaces.push_back(getOpenCLArgInfoAddressSpace(addressSpace.getValue()));
97 return metadataBuilder.getI32Node(addrSpaces);
100static void addOpenCLKernelArgFunctionMetadata(
101 mlir::MLIRContext *ctx, llvm::SmallVectorImpl<mlir::Attribute> &entries,
102 llvm::StringRef name, mlir::LLVM::MDNodeAttr node) {
103 entries.push_back(mlir::LLVM::FunctionMetadataAttr::get(
104 ctx, mlir::StringAttr::get(ctx, name), node));
110 cir::OpenCLKernelArgMetadataAttr clArgMetadata,
112 mlir::MLIRContext *ctx = clArgMetadata.getContext();
113 LLVMMetadataNodeBuilder metadataBuilder(ctx);
115 addOpenCLKernelArgFunctionMetadata(
116 ctx, entries,
"kernel_arg_addr_space",
117 getAddrSpaceMetadataNode(clArgMetadata, metadataBuilder));
119 static constexpr KernelArgStringMetadataMapping stringMetadataMappings[] = {
120 {
"kernel_arg_access_qual",
121 &cir::OpenCLKernelArgMetadataAttr::getAccessQual,
123 {
"kernel_arg_type", &cir::OpenCLKernelArgMetadataAttr::getType,
125 {
"kernel_arg_base_type", &cir::OpenCLKernelArgMetadataAttr::getBaseType,
127 {
"kernel_arg_type_qual", &cir::OpenCLKernelArgMetadataAttr::getTypeQual,
129 {
"kernel_arg_name", &cir::OpenCLKernelArgMetadataAttr::getName,
133 for (
const KernelArgStringMetadataMapping &mapping : stringMetadataMappings) {
134 mlir::ArrayAttr metadata = (clArgMetadata.*mapping.getMetadata)();
135 if (mapping.optional && !metadata)
137 addOpenCLKernelArgFunctionMetadata(ctx, entries, mapping.metadataName,
138 metadataBuilder.getStringNode(metadata));
143 mlir::MLIRContext *ctx)
147 bool includeFunctionOnlyAttrs) {
148 return llvm::TypeSwitch<mlir::Attribute, bool>(attr.getValue())
149 .Case<cir::OpenCLKernelArgMetadataAttr>(
150 [&](cir::OpenCLKernelArgMetadataAttr clArgMetadata) {
151 if (!includeFunctionOnlyAttrs)
153 lower(clArgMetadata);
161 if (!functionMetadata.empty()) {
162 result.push_back(mlir::NamedAttribute(
163 mlir::LLVM::LLVMFuncOp::getFunctionMetadataAttrName(mlir::OperationName(
164 mlir::LLVM::LLVMFuncOp::getOperationName(), ctx)),
165 mlir::ArrayAttr::get(ctx, functionMetadata)));
170 cir::OpenCLKernelArgMetadataAttr clArgMetadata) {
static Expected< DynTypedNode > getNode(const ast_matchers::BoundNodes &Nodes, StringRef ID)
static void convertOpenCLKernelArgMetadata(cir::OpenCLKernelArgMetadataAttr clArgMetadata, llvm::SmallVectorImpl< mlir::Attribute > &entries)
const internal::VariadicAllOfMatcher< Attr > attr