blob: 85690df755bed99b54e19f048306cc7e2108b8e4 [file] [log] [blame]
David Netoc6f3ab22018-04-06 18:02:31 -04001// Copyright 2017-2018 The Clspv Authors. All rights reserved.
David Neto48f56a42017-10-06 16:44:25 -04002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
David Netoc6f3ab22018-04-06 18:02:31 -040015#include "ArgKind.h"
16
17#include <cstring>
18
David Netoc6f3ab22018-04-06 18:02:31 -040019#include "llvm/ADT/StringRef.h"
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040020#include "llvm/ADT/StringSwitch.h"
alan-bakerc4579bb2020-04-29 14:15:50 -040021#include "llvm/IR/CallingConv.h"
22#include "llvm/IR/Constants.h"
David Netoc6f3ab22018-04-06 18:02:31 -040023#include "llvm/IR/DerivedTypes.h"
24#include "llvm/IR/Type.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/raw_ostream.h"
27
28#include "clspv/AddressSpace.h"
Alan Bakerfcda9482018-10-02 17:09:59 -040029#include "clspv/Option.h"
David Netoc6f3ab22018-04-06 18:02:31 -040030
alan-bakerc4579bb2020-04-29 14:15:50 -040031#include "Constants.h"
alan-bakerce179f12019-12-06 19:02:22 -050032#include "Types.h"
33
David Neto48f56a42017-10-06 16:44:25 -040034using namespace llvm;
35
alan-bakerc4579bb2020-04-29 14:15:50 -040036namespace {
David Neto48f56a42017-10-06 16:44:25 -040037
alan-bakerc4579bb2020-04-29 14:15:50 -040038// Maps an LLVM type for a kernel argument to an argument kind.
39clspv::ArgKind GetArgKindForType(Type *type);
40
41// Maps an LLVM type for a kernel argument to an argument
alan-baker86ce19c2020-08-05 13:09:19 -040042// kind suitable for embedded reflection. The result is one of:
alan-bakerc4579bb2020-04-29 14:15:50 -040043// buffer - storage buffer
44// buffer_ubo - uniform buffer
45// local - array in Workgroup storage, number of elements given by
46// a specialization constant
47// pod - plain-old-data
alan-bakerf6bc8252020-09-23 14:58:55 -040048// ro_image - sampled image
49// wo_image - storage image
alan-bakerc4579bb2020-04-29 14:15:50 -040050// sampler - sampler
51inline const char *GetArgKindNameForType(llvm::Type *type) {
52 return GetArgKindName(GetArgKindForType(type));
53}
54
55clspv::ArgKind GetArgKindForType(Type *type) {
David Neto48f56a42017-10-06 16:44:25 -040056 if (type->isPointerTy()) {
alan-bakerc4579bb2020-04-29 14:15:50 -040057 if (clspv::IsSamplerType(type)) {
58 return clspv::ArgKind::Sampler;
David Neto862b7d82018-06-14 18:48:37 -040059 }
60 llvm::Type *image_type = nullptr;
alan-bakerc4579bb2020-04-29 14:15:50 -040061 if (clspv::IsImageType(type, &image_type)) {
David Neto862b7d82018-06-14 18:48:37 -040062 StringRef name = dyn_cast<StructType>(image_type)->getName();
alan-bakerf6bc8252020-09-23 14:58:55 -040063 // OpenCL 1.2 only has read-only and write-only images.
64 // OpenCL 2.0 (and later) also has read-write images.
65 // Read-only images are translated to sampled images, while write-only
66 // and read-write images are translated as storage images.
67 return name.contains("_ro_t") ? clspv::ArgKind::SampledImage
68 : clspv::ArgKind::StorageImage;
David Neto48f56a42017-10-06 16:44:25 -040069 }
David Netoc6f3ab22018-04-06 18:02:31 -040070 switch (type->getPointerAddressSpace()) {
71 // Pointer to constant and pointer to global are both in
72 // storage buffers.
73 case clspv::AddressSpace::Global:
alan-bakerc4579bb2020-04-29 14:15:50 -040074 return clspv::ArgKind::Buffer;
Alan Bakerfcda9482018-10-02 17:09:59 -040075 case clspv::AddressSpace::Constant:
alan-bakerc4579bb2020-04-29 14:15:50 -040076 return clspv::Option::ConstantArgsInUniformBuffer()
77 ? clspv::ArgKind::BufferUBO
78 : clspv::ArgKind::Buffer;
David Netoc6f3ab22018-04-06 18:02:31 -040079 case clspv::AddressSpace::Local:
alan-bakerc4579bb2020-04-29 14:15:50 -040080 return clspv::ArgKind::Local;
David Netoc6f3ab22018-04-06 18:02:31 -040081 default:
82 break;
83 }
David Neto48f56a42017-10-06 16:44:25 -040084 } else {
alan-baker9b0ec3c2020-04-06 14:45:34 -040085 if (clspv::Option::PodArgsInUniformBuffer())
alan-bakerc4579bb2020-04-29 14:15:50 -040086 return clspv::ArgKind::PodUBO;
alan-baker9b0ec3c2020-04-06 14:45:34 -040087 else if (clspv::Option::PodArgsInPushConstants())
alan-bakerc4579bb2020-04-29 14:15:50 -040088 return clspv::ArgKind::PodPushConstant;
alan-baker9b0ec3c2020-04-06 14:45:34 -040089 else
alan-bakerc4579bb2020-04-29 14:15:50 -040090 return clspv::ArgKind::Pod;
David Neto48f56a42017-10-06 16:44:25 -040091 }
David Neto862b7d82018-06-14 18:48:37 -040092 errs() << "Unhandled case in clspv::GetArgKindNameForType: " << *type << "\n";
93 llvm_unreachable("Unhandled case in clspv::GetArgKindNameForType");
alan-bakerc4579bb2020-04-29 14:15:50 -040094 return clspv::ArgKind::Buffer;
95}
96} // namespace
97
98namespace clspv {
99
100PodArgImpl GetPodArgsImpl(Function &F) {
101 auto md = F.getMetadata(PodArgsImplMetadataName());
102 auto impl = static_cast<PodArgImpl>(
103 cast<ConstantInt>(
104 cast<ConstantAsMetadata>(md->getOperand(0).get())->getValue())
105 ->getZExtValue());
106 return impl;
107}
108
109ArgKind GetArgKindForPodArgs(Function &F) {
110 auto impl = GetPodArgsImpl(F);
111 switch (impl) {
112 case kUBO:
113 return ArgKind::PodUBO;
114 case kPushConstant:
115 case kGlobalPushConstant:
116 return ArgKind::PodPushConstant;
117 case kSSBO:
118 return ArgKind::Pod;
119 }
Kévin Petit229c3662021-01-12 16:18:54 +0000120 errs() << "Unhandled case in clspv::GetArgKindForPodArgs: " << impl << "\n";
121 llvm_unreachable("Unhandled case in clspv::GetArgKindForPodArgs");
alan-bakerc4579bb2020-04-29 14:15:50 -0400122}
123
124ArgKind GetArgKind(Argument &Arg) {
125 if (!isa<PointerType>(Arg.getType()) &&
126 Arg.getParent()->getCallingConv() == CallingConv::SPIR_KERNEL) {
127 return GetArgKindForPodArgs(*Arg.getParent());
128 }
129
130 return GetArgKindForType(Arg.getType());
David Neto862b7d82018-06-14 18:48:37 -0400131}
132
133const char *GetArgKindName(ArgKind kind) {
134 switch (kind) {
135 case ArgKind::Buffer:
136 return "buffer";
Alan Bakerfcda9482018-10-02 17:09:59 -0400137 case ArgKind::BufferUBO:
138 return "buffer_ubo";
David Neto862b7d82018-06-14 18:48:37 -0400139 case ArgKind::Local:
140 return "local";
141 case ArgKind::Pod:
142 return "pod";
alan-bakerf5e5f692018-11-27 08:33:24 -0500143 case ArgKind::PodUBO:
144 return "pod_ubo";
alan-baker9b0ec3c2020-04-06 14:45:34 -0400145 case ArgKind::PodPushConstant:
146 return "pod_pushconstant";
alan-bakerf6bc8252020-09-23 14:58:55 -0400147 case ArgKind::SampledImage:
148 // For historical purposes this string still refers to read-only images.
David Neto862b7d82018-06-14 18:48:37 -0400149 return "ro_image";
alan-bakerf6bc8252020-09-23 14:58:55 -0400150 case ArgKind::StorageImage:
151 // For historical purposes this string still refers to write-only images.
David Neto862b7d82018-06-14 18:48:37 -0400152 return "wo_image";
153 case ArgKind::Sampler:
154 return "sampler";
155 }
156 errs() << "Unhandled case in clspv::GetArgKindForType: " << int(kind) << "\n";
David Netoc6f3ab22018-04-06 18:02:31 -0400157 llvm_unreachable("Unhandled case in clspv::GetArgKindForType");
David Neto862b7d82018-06-14 18:48:37 -0400158 return "";
David Netoc6f3ab22018-04-06 18:02:31 -0400159}
160
alan-bakerf5e5f692018-11-27 08:33:24 -0500161ArgKind GetArgKindFromName(const std::string &name) {
162 if (name == "buffer") {
163 return ArgKind::Buffer;
164 } else if (name == "buffer_ubo") {
165 return ArgKind::BufferUBO;
166 } else if (name == "local") {
167 return ArgKind::Local;
168 } else if (name == "pod") {
169 return ArgKind::Pod;
170 } else if (name == "pod_ubo") {
171 return ArgKind::PodUBO;
alan-baker9b0ec3c2020-04-06 14:45:34 -0400172 } else if (name == "pod_pushconstant") {
173 return ArgKind::PodPushConstant;
alan-bakerf5e5f692018-11-27 08:33:24 -0500174 } else if (name == "ro_image") {
alan-bakerf6bc8252020-09-23 14:58:55 -0400175 return ArgKind::SampledImage;
alan-bakerf5e5f692018-11-27 08:33:24 -0500176 } else if (name == "wo_image") {
alan-bakerf6bc8252020-09-23 14:58:55 -0400177 return ArgKind::StorageImage;
alan-bakerf5e5f692018-11-27 08:33:24 -0500178 } else if (name == "sampler") {
179 return ArgKind::Sampler;
180 }
181
182 llvm_unreachable("Unhandled case in clspv::GetArgKindFromName");
183 return ArgKind::Buffer;
184}
185
David Netoc6f3ab22018-04-06 18:02:31 -0400186bool IsLocalPtr(llvm::Type *type) {
187 return type->isPointerTy() &&
188 type->getPointerAddressSpace() == clspv::AddressSpace::Local;
189}
190
David Neto48f56a42017-10-06 16:44:25 -0400191} // namespace clspv