David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 1 | // Copyright 2017-2018 The Clspv Authors. All rights reserved. |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 2 | // |
| 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 Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 15 | #include "ArgKind.h" |
| 16 | |
| 17 | #include <cstring> |
| 18 | |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 19 | #include "llvm/ADT/StringRef.h" |
Diego Novillo | 3cc8d7a | 2019-04-10 13:30:34 -0400 | [diff] [blame] | 20 | #include "llvm/ADT/StringSwitch.h" |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 21 | #include "llvm/IR/CallingConv.h" |
| 22 | #include "llvm/IR/Constants.h" |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 23 | #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 Baker | fcda948 | 2018-10-02 17:09:59 -0400 | [diff] [blame] | 29 | #include "clspv/Option.h" |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 30 | |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 31 | #include "Constants.h" |
alan-baker | ce179f1 | 2019-12-06 19:02:22 -0500 | [diff] [blame] | 32 | #include "Types.h" |
| 33 | |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 34 | using namespace llvm; |
| 35 | |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 36 | namespace { |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 37 | |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 38 | // Maps an LLVM type for a kernel argument to an argument kind. |
| 39 | clspv::ArgKind GetArgKindForType(Type *type); |
| 40 | |
| 41 | // Maps an LLVM type for a kernel argument to an argument |
alan-baker | 86ce19c | 2020-08-05 13:09:19 -0400 | [diff] [blame] | 42 | // kind suitable for embedded reflection. The result is one of: |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 43 | // 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-baker | f6bc825 | 2020-09-23 14:58:55 -0400 | [diff] [blame] | 48 | // ro_image - sampled image |
| 49 | // wo_image - storage image |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 50 | // sampler - sampler |
| 51 | inline const char *GetArgKindNameForType(llvm::Type *type) { |
| 52 | return GetArgKindName(GetArgKindForType(type)); |
| 53 | } |
| 54 | |
| 55 | clspv::ArgKind GetArgKindForType(Type *type) { |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 56 | if (type->isPointerTy()) { |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 57 | if (clspv::IsSamplerType(type)) { |
| 58 | return clspv::ArgKind::Sampler; |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 59 | } |
| 60 | llvm::Type *image_type = nullptr; |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 61 | if (clspv::IsImageType(type, &image_type)) { |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 62 | StringRef name = dyn_cast<StructType>(image_type)->getName(); |
alan-baker | f6bc825 | 2020-09-23 14:58:55 -0400 | [diff] [blame] | 63 | // 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 Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 69 | } |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 70 | switch (type->getPointerAddressSpace()) { |
| 71 | // Pointer to constant and pointer to global are both in |
| 72 | // storage buffers. |
| 73 | case clspv::AddressSpace::Global: |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 74 | return clspv::ArgKind::Buffer; |
Alan Baker | fcda948 | 2018-10-02 17:09:59 -0400 | [diff] [blame] | 75 | case clspv::AddressSpace::Constant: |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 76 | return clspv::Option::ConstantArgsInUniformBuffer() |
| 77 | ? clspv::ArgKind::BufferUBO |
| 78 | : clspv::ArgKind::Buffer; |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 79 | case clspv::AddressSpace::Local: |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 80 | return clspv::ArgKind::Local; |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 81 | default: |
| 82 | break; |
| 83 | } |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 84 | } else { |
alan-baker | 9b0ec3c | 2020-04-06 14:45:34 -0400 | [diff] [blame] | 85 | if (clspv::Option::PodArgsInUniformBuffer()) |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 86 | return clspv::ArgKind::PodUBO; |
alan-baker | 9b0ec3c | 2020-04-06 14:45:34 -0400 | [diff] [blame] | 87 | else if (clspv::Option::PodArgsInPushConstants()) |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 88 | return clspv::ArgKind::PodPushConstant; |
alan-baker | 9b0ec3c | 2020-04-06 14:45:34 -0400 | [diff] [blame] | 89 | else |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 90 | return clspv::ArgKind::Pod; |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 91 | } |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 92 | errs() << "Unhandled case in clspv::GetArgKindNameForType: " << *type << "\n"; |
| 93 | llvm_unreachable("Unhandled case in clspv::GetArgKindNameForType"); |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 94 | return clspv::ArgKind::Buffer; |
| 95 | } |
| 96 | } // namespace |
| 97 | |
| 98 | namespace clspv { |
| 99 | |
| 100 | PodArgImpl 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 | |
| 109 | ArgKind 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 Petit | 229c366 | 2021-01-12 16:18:54 +0000 | [diff] [blame^] | 120 | errs() << "Unhandled case in clspv::GetArgKindForPodArgs: " << impl << "\n"; |
| 121 | llvm_unreachable("Unhandled case in clspv::GetArgKindForPodArgs"); |
alan-baker | c4579bb | 2020-04-29 14:15:50 -0400 | [diff] [blame] | 122 | } |
| 123 | |
| 124 | ArgKind 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 Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 131 | } |
| 132 | |
| 133 | const char *GetArgKindName(ArgKind kind) { |
| 134 | switch (kind) { |
| 135 | case ArgKind::Buffer: |
| 136 | return "buffer"; |
Alan Baker | fcda948 | 2018-10-02 17:09:59 -0400 | [diff] [blame] | 137 | case ArgKind::BufferUBO: |
| 138 | return "buffer_ubo"; |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 139 | case ArgKind::Local: |
| 140 | return "local"; |
| 141 | case ArgKind::Pod: |
| 142 | return "pod"; |
alan-baker | f5e5f69 | 2018-11-27 08:33:24 -0500 | [diff] [blame] | 143 | case ArgKind::PodUBO: |
| 144 | return "pod_ubo"; |
alan-baker | 9b0ec3c | 2020-04-06 14:45:34 -0400 | [diff] [blame] | 145 | case ArgKind::PodPushConstant: |
| 146 | return "pod_pushconstant"; |
alan-baker | f6bc825 | 2020-09-23 14:58:55 -0400 | [diff] [blame] | 147 | case ArgKind::SampledImage: |
| 148 | // For historical purposes this string still refers to read-only images. |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 149 | return "ro_image"; |
alan-baker | f6bc825 | 2020-09-23 14:58:55 -0400 | [diff] [blame] | 150 | case ArgKind::StorageImage: |
| 151 | // For historical purposes this string still refers to write-only images. |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 152 | return "wo_image"; |
| 153 | case ArgKind::Sampler: |
| 154 | return "sampler"; |
| 155 | } |
| 156 | errs() << "Unhandled case in clspv::GetArgKindForType: " << int(kind) << "\n"; |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 157 | llvm_unreachable("Unhandled case in clspv::GetArgKindForType"); |
David Neto | 862b7d8 | 2018-06-14 18:48:37 -0400 | [diff] [blame] | 158 | return ""; |
David Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 159 | } |
| 160 | |
alan-baker | f5e5f69 | 2018-11-27 08:33:24 -0500 | [diff] [blame] | 161 | ArgKind 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-baker | 9b0ec3c | 2020-04-06 14:45:34 -0400 | [diff] [blame] | 172 | } else if (name == "pod_pushconstant") { |
| 173 | return ArgKind::PodPushConstant; |
alan-baker | f5e5f69 | 2018-11-27 08:33:24 -0500 | [diff] [blame] | 174 | } else if (name == "ro_image") { |
alan-baker | f6bc825 | 2020-09-23 14:58:55 -0400 | [diff] [blame] | 175 | return ArgKind::SampledImage; |
alan-baker | f5e5f69 | 2018-11-27 08:33:24 -0500 | [diff] [blame] | 176 | } else if (name == "wo_image") { |
alan-baker | f6bc825 | 2020-09-23 14:58:55 -0400 | [diff] [blame] | 177 | return ArgKind::StorageImage; |
alan-baker | f5e5f69 | 2018-11-27 08:33:24 -0500 | [diff] [blame] | 178 | } 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 Neto | c6f3ab2 | 2018-04-06 18:02:31 -0400 | [diff] [blame] | 186 | bool IsLocalPtr(llvm::Type *type) { |
| 187 | return type->isPointerTy() && |
| 188 | type->getPointerAddressSpace() == clspv::AddressSpace::Local; |
| 189 | } |
| 190 | |
David Neto | 48f56a4 | 2017-10-06 16:44:25 -0400 | [diff] [blame] | 191 | } // namespace clspv |