blob: 7ad14d42952789d34f614c74b35b8facfa9ba60c [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
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/IR/DerivedTypes.h"
22#include "llvm/IR/Type.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/raw_ostream.h"
25
26#include "clspv/AddressSpace.h"
Alan Bakerfcda9482018-10-02 17:09:59 -040027#include "clspv/Option.h"
David Netoc6f3ab22018-04-06 18:02:31 -040028
David Neto48f56a42017-10-06 16:44:25 -040029
30using namespace llvm;
31
32namespace clspv {
33
David Neto862b7d82018-06-14 18:48:37 -040034ArgKind GetArgKindForType(Type *type) {
David Neto48f56a42017-10-06 16:44:25 -040035 if (type->isPointerTy()) {
David Neto862b7d82018-06-14 18:48:37 -040036 if (IsSamplerType(type)) {
37 return ArgKind::Sampler;
38 }
39 llvm::Type *image_type = nullptr;
40 if (IsImageType(type, &image_type)) {
41 StringRef name = dyn_cast<StructType>(image_type)->getName();
42 // OpenCL 1.2 only has read-only or write-only images.
43 return name.endswith("_ro_t") ? ArgKind::ReadOnlyImage
44 : ArgKind::WriteOnlyImage;
David Neto48f56a42017-10-06 16:44:25 -040045 }
David Netoc6f3ab22018-04-06 18:02:31 -040046 switch (type->getPointerAddressSpace()) {
47 // Pointer to constant and pointer to global are both in
48 // storage buffers.
49 case clspv::AddressSpace::Global:
David Neto862b7d82018-06-14 18:48:37 -040050 return ArgKind::Buffer;
Alan Bakerfcda9482018-10-02 17:09:59 -040051 case clspv::AddressSpace::Constant:
52 return Option::ConstantArgsInUniformBuffer() ? ArgKind::BufferUBO
53 : ArgKind::Buffer;
David Netoc6f3ab22018-04-06 18:02:31 -040054 case clspv::AddressSpace::Local:
David Neto862b7d82018-06-14 18:48:37 -040055 return ArgKind::Local;
David Netoc6f3ab22018-04-06 18:02:31 -040056 default:
57 break;
58 }
David Neto48f56a42017-10-06 16:44:25 -040059 } else {
David Neto862b7d82018-06-14 18:48:37 -040060 return ArgKind::Pod;
David Neto48f56a42017-10-06 16:44:25 -040061 }
David Neto862b7d82018-06-14 18:48:37 -040062 errs() << "Unhandled case in clspv::GetArgKindNameForType: " << *type << "\n";
63 llvm_unreachable("Unhandled case in clspv::GetArgKindNameForType");
64 return ArgKind::Buffer;
65}
66
67const char *GetArgKindName(ArgKind kind) {
68 switch (kind) {
69 case ArgKind::Buffer:
70 return "buffer";
Alan Bakerfcda9482018-10-02 17:09:59 -040071 case ArgKind::BufferUBO:
72 return "buffer_ubo";
David Neto862b7d82018-06-14 18:48:37 -040073 case ArgKind::Local:
74 return "local";
75 case ArgKind::Pod:
76 return "pod";
77 case ArgKind::ReadOnlyImage:
78 return "ro_image";
79 case ArgKind::WriteOnlyImage:
80 return "wo_image";
81 case ArgKind::Sampler:
82 return "sampler";
83 }
84 errs() << "Unhandled case in clspv::GetArgKindForType: " << int(kind) << "\n";
David Netoc6f3ab22018-04-06 18:02:31 -040085 llvm_unreachable("Unhandled case in clspv::GetArgKindForType");
David Neto862b7d82018-06-14 18:48:37 -040086 return "";
David Netoc6f3ab22018-04-06 18:02:31 -040087}
88
89bool IsLocalPtr(llvm::Type *type) {
90 return type->isPointerTy() &&
91 type->getPointerAddressSpace() == clspv::AddressSpace::Local;
92}
93
David Neto862b7d82018-06-14 18:48:37 -040094bool IsSamplerType(llvm::Type *type, llvm::Type **struct_type_ptr) {
95 bool isSamplerType = false;
96 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(type)) {
97 if (StructType *STy = dyn_cast<StructType>(TmpArgPTy->getElementType())) {
98 if (STy->isOpaque()) {
99 if (STy->getName().equals("opencl.sampler_t")) {
100 isSamplerType = true;
101 if (struct_type_ptr)
102 *struct_type_ptr = STy;
103 }
104 }
105 }
106 }
107 return isSamplerType;
108}
109
110bool IsImageType(llvm::Type *type, llvm::Type **struct_type_ptr) {
111 bool isImageType = false;
112 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(type)) {
113 if (StructType *STy = dyn_cast<StructType>(TmpArgPTy->getElementType())) {
114 if (STy->isOpaque()) {
115 if (STy->getName().equals("opencl.image2d_ro_t") ||
116 STy->getName().equals("opencl.image2d_wo_t") ||
117 STy->getName().equals("opencl.image3d_ro_t") ||
118 STy->getName().equals("opencl.image3d_wo_t")) {
119 isImageType = true;
120 if (struct_type_ptr)
121 *struct_type_ptr = STy;
122 }
123 }
124 }
125 }
126 return isImageType;
127}
128
David Netoc6f3ab22018-04-06 18:02:31 -0400129ArgIdMapType AllocateArgSpecIds(Module &M) {
130 ArgIdMapType result;
131
132 int next_spec_id = 3; // Reserve space for workgroup size spec ids.
133 for (Function &F : M) {
134 if (F.isDeclaration() || F.getCallingConv() != CallingConv::SPIR_KERNEL) {
135 continue;
136 }
137 for (const auto &Arg : F.args()) {
138 if (IsLocalPtr(Arg.getType())) {
139 result[&Arg] = next_spec_id++;
140 }
141 }
142 }
143
144 return result;
David Neto48f56a42017-10-06 16:44:25 -0400145}
146
147} // namespace clspv