blob: 1d08153586d1b407d0c593c8e74dd99ceebbda7a [file] [log] [blame]
alan-bakerfec0a472018-11-08 18:09:40 -05001// Copyright 2018 The Clspv Authors. All rights reserved.
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
15#include "clang/AST/RecordLayout.h"
16#include "clang/AST/RecursiveASTVisitor.h"
17#include "clang/Basic/TargetInfo.h"
18#include "clang/CodeGen/CodeGenAction.h"
19#include "clang/Frontend/CompilerInstance.h"
20#include "clang/Frontend/FrontendPluginRegistry.h"
21#include "clang/Frontend/TextDiagnosticPrinter.h"
22
23#include "clspv/Option.h"
24
25#include "FrontendPlugin.h"
26
27using namespace clang;
28
29namespace {
30struct ExtraValidationConsumer final : public ASTConsumer {
31private:
32 CompilerInstance &Instance;
33 llvm::StringRef InFile;
34
alan-baker9bb09792019-03-25 11:25:13 -040035 enum Layout {
36 UBO,
37 SSBO
38 };
39
alan-bakerfec0a472018-11-08 18:09:40 -050040 enum CustomDiagnosticType {
41 CustomDiagnosticVectorsMoreThan4Elements = 0,
42 CustomDiagnosticVoidPointer = 1,
alan-baker9bb09792019-03-25 11:25:13 -040043 CustomDiagnosticUnalignedScalar = 2,
44 CustomDiagnosticUnalignedVec2 = 3,
45 CustomDiagnosticUnalignedVec4 = 4,
alan-bakerfec0a472018-11-08 18:09:40 -050046 CustomDiagnosticUBOUnalignedArray = 5,
47 CustomDiagnosticUBOUnalignedStruct = 6,
alan-baker9bb09792019-03-25 11:25:13 -040048 CustomDiagnosticSmallStraddle = 7,
49 CustomDiagnosticLargeStraddle = 8,
50 CustomDiagnosticUnalignedStructMember = 9,
alan-bakerfec0a472018-11-08 18:09:40 -050051 CustomDiagnosticUBORestrictedSize = 10,
52 CustomDiagnosticUBORestrictedStruct = 11,
alan-baker3d9e2012019-01-11 14:55:30 -050053 CustomDiagnosticUBOArrayStride = 12,
54 CustomDiagnosticLocationInfo = 13,
alan-baker9bb09792019-03-25 11:25:13 -040055 CustomDiagnosticSSBOUnalignedArray = 14,
56 CustomDiagnosticSSBOUnalignedStruct = 15,
alan-bakerfec0a472018-11-08 18:09:40 -050057 CustomDiagnosticTotal
58 };
59 std::vector<unsigned> CustomDiagnosticsIDMap;
60
61 bool IsSupportedType(QualType QT, SourceRange SR) {
62 auto *Ty = QT.getTypePtr();
63
64 // First check if we have a pointer type.
65 if (Ty->isPointerType()) {
66 const Type *pointeeTy = Ty->getPointeeType().getTypePtr();
67 if (pointeeTy && pointeeTy->isVoidType()) {
68 // We don't support void pointers.
69 Instance.getDiagnostics().Report(
70 SR.getBegin(), CustomDiagnosticsIDMap[CustomDiagnosticVoidPointer]);
71 return false;
72 }
73 // Otherwise check recursively.
74 return IsSupportedType(Ty->getPointeeType(), SR);
75 }
76
77 const auto &canonicalType = QT.getCanonicalType();
78 if (auto *VT = llvm::dyn_cast<ExtVectorType>(canonicalType)) {
79 // We don't support vectors with more than 4 elements.
80 if (4 < VT->getNumElements()) {
81 Instance.getDiagnostics().Report(
82 SR.getBegin(),
83 CustomDiagnosticsIDMap[CustomDiagnosticVectorsMoreThan4Elements]);
84 return false;
85 }
86 }
87
88 return true;
89 }
90
alan-baker3d9e2012019-01-11 14:55:30 -050091 // Report a diagnostic using |diag|. If |arg_range| and |specific_range|
92 // differ, also issue a note with the specific location of the error.
93 void Report(const CustomDiagnosticType &diag, SourceRange arg_range,
94 SourceRange specific_range) {
95 Instance.getDiagnostics().Report(arg_range.getBegin(),
96 CustomDiagnosticsIDMap[diag]);
97 if (arg_range != specific_range) {
98 Instance.getDiagnostics().Report(
99 specific_range.getBegin(),
100 CustomDiagnosticsIDMap[CustomDiagnosticLocationInfo]);
101 }
102 }
103
alan-baker9bb09792019-03-25 11:25:13 -0400104 // Returns the alignment of |QT| to satisfy |layout|'s rules.
105 uint64_t GetAlignment(const QualType QT, const Layout &layout,
106 const ASTContext &context) const {
alan-bakerfec0a472018-11-08 18:09:40 -0500107 const auto canonical = QT.getCanonicalType();
108 uint64_t alignment = context.getTypeAlignInChars(canonical).getQuantity();
alan-baker9bb09792019-03-25 11:25:13 -0400109 if (layout == UBO &&
110 (canonical->isRecordType() || canonical->isArrayType())) {
alan-bakerfec0a472018-11-08 18:09:40 -0500111 return llvm::alignTo(alignment, 16);
112 }
113 return alignment;
114 }
115
116 // Returns true if |QT| is a valid layout for a Uniform buffer. Refer to
117 // 14.5.4 in the Vulkan specification.
alan-baker9bb09792019-03-25 11:25:13 -0400118 bool IsSupportedLayout(QualType QT, uint64_t offset, const Layout &layout,
119 ASTContext &context, SourceRange arg_range,
120 SourceRange specific_range) {
alan-bakerfec0a472018-11-08 18:09:40 -0500121 const auto canonical = QT.getCanonicalType();
122 if (canonical->isScalarType()) {
alan-baker9bb09792019-03-25 11:25:13 -0400123 if (!IsSupportedScalarLayout(canonical, offset, layout, context,
124 arg_range, specific_range))
alan-bakerfec0a472018-11-08 18:09:40 -0500125 return false;
126 } else if (canonical->isExtVectorType()) {
alan-baker9bb09792019-03-25 11:25:13 -0400127 if (!IsSupportedVectorLayout(canonical, offset, layout, context,
128 arg_range, specific_range))
alan-bakerfec0a472018-11-08 18:09:40 -0500129 return false;
130 } else if (canonical->isArrayType()) {
alan-baker9bb09792019-03-25 11:25:13 -0400131 if (!IsSupportedArrayLayout(canonical, offset, layout, context, arg_range,
132 specific_range))
alan-bakerfec0a472018-11-08 18:09:40 -0500133 return false;
134 } else if (canonical->isRecordType()) {
alan-baker9bb09792019-03-25 11:25:13 -0400135 if (!IsSupportedRecordLayout(canonical, offset, layout, context,
136 arg_range, specific_range))
alan-bakerfec0a472018-11-08 18:09:40 -0500137 return false;
138 }
139
140 // TODO(alan-baker): Find a way to avoid this restriction.
141 // Don't allow padding. This prevents structs like:
142 // struct {
143 // int x[2];
144 // int y __attribute((aligned(16)));
145 // };
146 //
147 // This would map in LLVM to { [2 x i32], [8 x i8], i32, [12 xi8] }.
148 // There is no easy way to manipulate the padding after the array to
149 // satisfy the standard Uniform buffer layout rules in this case. The usual
150 // trick is replacing the i8 arrays with an i32 element, but the i32 would
151 // still be laid out too close to the array.
152 const auto type_size = context.getTypeSizeInChars(canonical).getQuantity();
alan-baker9bb09792019-03-25 11:25:13 -0400153 const auto type_align = GetAlignment(canonical, layout, context);
154 if (layout == UBO && (type_size % type_align != 0)) {
alan-baker3d9e2012019-01-11 14:55:30 -0500155 Report(CustomDiagnosticUBORestrictedSize, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500156 return false;
157 }
158
159 return true;
160 }
161
alan-baker9bb09792019-03-25 11:25:13 -0400162 bool IsSupportedScalarLayout(QualType QT, uint64_t offset,
163 const Layout & /*layout*/, ASTContext &context,
164 SourceRange arg_range,
165 SourceRange specific_range) {
alan-bakerfec0a472018-11-08 18:09:40 -0500166 // A scalar type of size N has a base alignment on N.
167 const unsigned type_size = context.getTypeSizeInChars(QT).getQuantity();
168 if (offset % type_size != 0) {
alan-baker9bb09792019-03-25 11:25:13 -0400169 Report(CustomDiagnosticUnalignedScalar, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500170 return false;
171 }
172
173 return true;
174 }
175
alan-baker9bb09792019-03-25 11:25:13 -0400176 bool IsSupportedVectorLayout(QualType QT, uint64_t offset,
177 const Layout &layout, ASTContext &context,
178 SourceRange arg_range,
179 SourceRange specific_range) {
alan-bakerfec0a472018-11-08 18:09:40 -0500180 // 2-component vectors have a base alignment of 2 * (size of element).
181 // 3- and 4-component vectors hae a base alignment of 4 * (size of
182 // element).
183 const auto *VT = llvm::cast<VectorType>(QT);
184 const auto ele_size =
185 context.getTypeSizeInChars(VT->getElementType()).getQuantity();
186 if (VT->getNumElements() == 2) {
187 if (offset % (ele_size * 2) != 0) {
alan-baker9bb09792019-03-25 11:25:13 -0400188 Report(CustomDiagnosticUnalignedVec2, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500189 return false;
190 }
191 } else if (offset % (ele_size * 4) != 0) {
192 // Other vector sizes cause errors elsewhere.
alan-baker9bb09792019-03-25 11:25:13 -0400193 Report(CustomDiagnosticUnalignedVec4, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500194 return false;
195 }
196
197 // Straddling rules:
198 // * If total vector size is less than 16 bytes, the offset must place the
199 // entire vector within the same 16 bytes.
200 // * If total vector size is greater than 16 bytes, the offset must be a
201 // multiple of 16.
202 const auto size = context.getTypeSizeInChars(QT).getQuantity();
203 if (size <= 16 && (offset / 16 != (offset + size - 1) / 16)) {
alan-baker9bb09792019-03-25 11:25:13 -0400204 Report(CustomDiagnosticSmallStraddle, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500205 return false;
206 } else if (size > 16 && (offset % 16 != 0)) {
alan-baker9bb09792019-03-25 11:25:13 -0400207 Report(CustomDiagnosticLargeStraddle, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500208 return false;
209 }
210
alan-baker9bb09792019-03-25 11:25:13 -0400211 return IsSupportedLayout(VT->getElementType(), offset, layout, context,
212 arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500213 }
214
alan-baker9bb09792019-03-25 11:25:13 -0400215 bool IsSupportedArrayLayout(QualType QT, uint64_t offset,
216 const Layout &layout, ASTContext &context,
217 SourceRange arg_range,
218 SourceRange specific_range) {
219 // An array has a base alignment of is element type.
220 // If the layout is UBO, the alignment is rounded up to a multiple of 16.
alan-bakerfec0a472018-11-08 18:09:40 -0500221 const auto *AT = llvm::cast<ArrayType>(QT);
alan-baker9bb09792019-03-25 11:25:13 -0400222 const auto element_align = GetAlignment(AT->getElementType(), layout, context);
223 const auto type_align =
224 layout == UBO ? llvm::alignTo(element_align, 16) : element_align;
alan-bakerfec0a472018-11-08 18:09:40 -0500225 if (offset % type_align != 0) {
alan-baker9bb09792019-03-25 11:25:13 -0400226 auto diag_id = layout == UBO ? CustomDiagnosticUBOUnalignedArray
227 : CustomDiagnosticSSBOUnalignedArray;
228 Report(diag_id, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500229 return false;
230 }
alan-baker9bb09792019-03-25 11:25:13 -0400231 if (layout == UBO && !clspv::Option::RelaxedUniformBufferLayout()) {
alan-baker3d9e2012019-01-11 14:55:30 -0500232 // The ArrayStride must be a multiple of the base alignment of the array
233 // (i.e. a multiple of 16). This means that the element size must be
234 // restricted to be the base alignment of the array.
235 const auto element_size =
236 context.getTypeSizeInChars(AT->getElementType()).getQuantity();
237 if (element_size % type_align != 0) {
238 Report(CustomDiagnosticUBOArrayStride, arg_range, specific_range);
239 return false;
240 }
241 }
alan-bakerfec0a472018-11-08 18:09:40 -0500242
alan-baker9bb09792019-03-25 11:25:13 -0400243 return IsSupportedLayout(AT->getElementType(), offset, layout, context,
244 arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500245 }
246
alan-baker9bb09792019-03-25 11:25:13 -0400247 bool IsSupportedRecordLayout(QualType QT, uint64_t offset,
248 const Layout &layout, ASTContext &context,
249 SourceRange arg_range,
250 SourceRange specific_range) {
251 // A structure has a base alignment of its largest member. For UBO layouts,
252 // alignment is rounded up to a multiple of 16.
alan-bakerfec0a472018-11-08 18:09:40 -0500253 const auto *RT = llvm::cast<RecordType>(QT);
alan-baker9bb09792019-03-25 11:25:13 -0400254 auto type_alignment = GetAlignment(QT, layout, context);
255 if (layout == UBO) llvm::alignTo(type_alignment, 16);
alan-bakerfec0a472018-11-08 18:09:40 -0500256 if (offset % type_alignment != 0) {
alan-baker9bb09792019-03-25 11:25:13 -0400257 auto diag_id = layout == UBO ? CustomDiagnosticUBOUnalignedStruct
258 : CustomDiagnosticSSBOUnalignedStruct;
259 Report(diag_id, arg_range, specific_range);
alan-bakerfec0a472018-11-08 18:09:40 -0500260 return false;
261 }
262
alan-baker9bb09792019-03-25 11:25:13 -0400263 const auto &record_layout = context.getASTRecordLayout(RT->getDecl());
alan-bakerfec0a472018-11-08 18:09:40 -0500264 const FieldDecl *prev = nullptr;
265 for (auto field_decl : RT->getDecl()->fields()) {
266 const auto field_type = field_decl->getType();
alan-baker9bb09792019-03-25 11:25:13 -0400267 const auto field_alignment = GetAlignment(field_type, layout, context);
alan-bakerfec0a472018-11-08 18:09:40 -0500268 const unsigned field_no = field_decl->getFieldIndex();
269 const uint64_t field_offset =
alan-baker9bb09792019-03-25 11:25:13 -0400270 record_layout.getFieldOffset(field_no) / context.getCharWidth();
alan-bakerfec0a472018-11-08 18:09:40 -0500271
272 // Rules must be checked recursively.
alan-baker9bb09792019-03-25 11:25:13 -0400273 if (!IsSupportedLayout(field_type, field_offset + offset, layout, context,
274 arg_range, field_decl->getSourceRange())) {
alan-bakerfec0a472018-11-08 18:09:40 -0500275 return false;
276 }
277
278 if (prev) {
279 const auto prev_canonical = prev->getType().getCanonicalType();
280 const uint64_t prev_offset =
alan-baker9bb09792019-03-25 11:25:13 -0400281 record_layout.getFieldOffset(field_no - 1) / context.getCharWidth();
alan-bakerfec0a472018-11-08 18:09:40 -0500282 const auto prev_size =
283 context.getTypeSizeInChars(prev_canonical).getQuantity();
alan-baker9bb09792019-03-25 11:25:13 -0400284 const auto prev_alignment = GetAlignment(prev_canonical, layout, context);
alan-bakerfec0a472018-11-08 18:09:40 -0500285 const auto next_available =
286 prev_offset + llvm::alignTo(prev_size, prev_alignment);
287 if (prev_canonical->isArrayType() || prev_canonical->isRecordType()) {
288 // The next element after an array or struct must be placed on or
289 // after the next multiple of the alignment of that array or
290 // struct.
alan-baker9bb09792019-03-25 11:25:13 -0400291 // For UBO layouts, both arrays and structs must be aligned to a
292 // multiple of 16 bytes.
293 const uint64_t final_align = layout == UBO
294 ? llvm::alignTo(next_available, 16)
295 : next_available;
296 if (final_align > field_offset) {
297 Report(CustomDiagnosticUnalignedStructMember, arg_range,
alan-baker3d9e2012019-01-11 14:55:30 -0500298 field_decl->getSourceRange());
alan-bakerfec0a472018-11-08 18:09:40 -0500299 return false;
300 }
301 }
302 }
303
304 prev = field_decl;
305 }
306
307 return true;
308 }
309
310 // This will be used to check the inside of function bodies.
311 class DeclVisitor : public RecursiveASTVisitor<DeclVisitor> {
312 private:
313 ExtraValidationConsumer &consumer;
314
315 public:
316 explicit DeclVisitor(ExtraValidationConsumer &VC) : consumer(VC) {}
317
318 // Visits a declaration. Emits a diagnostic and returns false if the
319 // declaration represents an unsupported vector value or vector type.
320 // Otherwise returns true.
321 bool VisitDecl(Decl *D) {
322 // Looking at the Decl class hierarchy, it seems ValueDecl and TypeDecl
323 // are the only two that might represent an unsupported vector type.
324 if (auto *VD = dyn_cast<ValueDecl>(D)) {
325 return consumer.IsSupportedType(VD->getType(), D->getSourceRange());
326 } else if (auto *TD = dyn_cast<TypeDecl>(D)) {
327 QualType DefinedType = TD->getASTContext().getTypeDeclType(TD);
328 return consumer.IsSupportedType(DefinedType, TD->getSourceRange());
329 }
330 return true;
331 }
332 };
333
334 DeclVisitor Visitor;
335
336public:
337 explicit ExtraValidationConsumer(CompilerInstance &Instance,
338 llvm::StringRef InFile)
339 : Instance(Instance), InFile(InFile),
340 CustomDiagnosticsIDMap(CustomDiagnosticTotal), Visitor(*this) {
341 auto &DE = Instance.getDiagnostics();
342
343 CustomDiagnosticsIDMap[CustomDiagnosticVectorsMoreThan4Elements] =
344 DE.getCustomDiagID(
345 DiagnosticsEngine::Error,
346 "vectors with more than 4 elements are not supported");
347 CustomDiagnosticsIDMap[CustomDiagnosticVoidPointer] = DE.getCustomDiagID(
348 DiagnosticsEngine::Error, "pointer-to-void is not supported");
alan-baker9bb09792019-03-25 11:25:13 -0400349 CustomDiagnosticsIDMap[CustomDiagnosticUnalignedScalar] =
alan-bakerfec0a472018-11-08 18:09:40 -0500350 DE.getCustomDiagID(
351 DiagnosticsEngine::Error,
alan-baker9bb09792019-03-25 11:25:13 -0400352 "scalar elements must be aligned to their size");
353 CustomDiagnosticsIDMap[CustomDiagnosticUnalignedVec2] = DE.getCustomDiagID(
354 DiagnosticsEngine::Error,
355 "two-component vectors must be aligned to 2 times their element size");
356 CustomDiagnosticsIDMap[CustomDiagnosticUnalignedVec4] =
alan-bakerfec0a472018-11-08 18:09:40 -0500357 DE.getCustomDiagID(DiagnosticsEngine::Error,
alan-baker9bb09792019-03-25 11:25:13 -0400358 "three- and four-component vectors must be aligned "
359 "to 4 times their element size");
alan-bakerfec0a472018-11-08 18:09:40 -0500360 CustomDiagnosticsIDMap[CustomDiagnosticUBOUnalignedArray] =
361 DE.getCustomDiagID(DiagnosticsEngine::Error,
362 "in an UBO, arrays must be aligned to their element "
363 "alignment, rounded up to a multiple of 16 bytes");
364 CustomDiagnosticsIDMap[CustomDiagnosticUBOUnalignedStruct] =
365 DE.getCustomDiagID(
366 DiagnosticsEngine::Error,
367 "in an UBO, structs must be aligned to their "
368 "largest element alignment, rounded up to a multiple of "
369 "16 bytes");
alan-baker9bb09792019-03-25 11:25:13 -0400370 CustomDiagnosticsIDMap[CustomDiagnosticSmallStraddle] =
alan-bakerfec0a472018-11-08 18:09:40 -0500371 DE.getCustomDiagID(DiagnosticsEngine::Error,
alan-baker9bb09792019-03-25 11:25:13 -0400372 "vectors with a total size less than or equal to 16 "
373 "bytes must be placed entirely within a 16 byte "
374 "aligned region");
375 CustomDiagnosticsIDMap[CustomDiagnosticLargeStraddle] =
alan-bakerfec0a472018-11-08 18:09:40 -0500376 DE.getCustomDiagID(DiagnosticsEngine::Error,
alan-baker9bb09792019-03-25 11:25:13 -0400377 "vectors with a total size greater than 16 bytes "
378 "must aligned to 16 bytes");
379 CustomDiagnosticsIDMap[CustomDiagnosticUnalignedStructMember] =
alan-bakerfec0a472018-11-08 18:09:40 -0500380 DE.getCustomDiagID(DiagnosticsEngine::Error,
alan-baker9bb09792019-03-25 11:25:13 -0400381 "a structure member must not be placed between the "
382 "end of a structure or array and the next multiple "
383 "of the base alignment of that structure or array");
alan-bakerfec0a472018-11-08 18:09:40 -0500384 CustomDiagnosticsIDMap[CustomDiagnosticUBORestrictedSize] =
385 DE.getCustomDiagID(DiagnosticsEngine::Error,
386 "clspv restriction: UBO element size must be a "
387 "multiple of that element's alignment");
388 CustomDiagnosticsIDMap[CustomDiagnosticUBORestrictedStruct] =
389 DE.getCustomDiagID(
390 DiagnosticsEngine::Error,
391 "clspv restriction: UBO structures may not have implicit padding");
alan-baker3d9e2012019-01-11 14:55:30 -0500392 CustomDiagnosticsIDMap[CustomDiagnosticUBOArrayStride] = DE.getCustomDiagID(
393 DiagnosticsEngine::Error,
394 "clspv restriction: to satisfy UBO ArrayStride restrictions, element "
395 "size must be a multiple of array alignment");
396 CustomDiagnosticsIDMap[CustomDiagnosticLocationInfo] =
397 DE.getCustomDiagID(DiagnosticsEngine::Note, "here");
alan-baker9bb09792019-03-25 11:25:13 -0400398 CustomDiagnosticsIDMap[CustomDiagnosticSSBOUnalignedArray] =
399 DE.getCustomDiagID(
400 DiagnosticsEngine::Error,
401 "in a SSBO, arrays must be aligned to their element alignment");
402 CustomDiagnosticsIDMap[CustomDiagnosticSSBOUnalignedStruct] =
403 DE.getCustomDiagID(DiagnosticsEngine::Error,
404 "in a SSBO, structs must be aligned to their "
405 "largest element alignment");
alan-bakerfec0a472018-11-08 18:09:40 -0500406 }
407
408 virtual bool HandleTopLevelDecl(DeclGroupRef DG) override {
409 for (auto *D : DG) {
410 if (auto *FD = llvm::dyn_cast<FunctionDecl>(D)) {
411 // If the function has a body it means we are not an OpenCL builtin
412 // function.
413 if (FD->hasBody()) {
414 if (!IsSupportedType(FD->getReturnType(),
415 FD->getReturnTypeSourceRange())) {
416 return false;
417 }
418
419 bool is_opencl_kernel = false;
420 if (FD->hasAttrs()) {
421 for (auto *attr : FD->attrs()) {
422 if (attr->getKind() == attr::Kind::OpenCLKernel) {
423 is_opencl_kernel = true;
424 }
425 }
426 }
427
428 for (auto *P : FD->parameters()) {
429 auto type = P->getType();
430 if (!IsSupportedType(P->getOriginalType(), P->getSourceRange())) {
431 return false;
432 }
433
alan-baker9bb09792019-03-25 11:25:13 -0400434 if (is_opencl_kernel && type->isPointerType() &&
435 ((type->getPointeeType().getAddressSpace() ==
436 LangAS::opencl_constant) ||
437 (type->getPointeeType().getAddressSpace() ==
438 LangAS::opencl_global))) {
alan-baker3d9e2012019-01-11 14:55:30 -0500439 // The argument will be generated as an array within a block.
440 // Generate an array type to check the validity for the generated
441 // case.
alan-baker9bb09792019-03-25 11:25:13 -0400442 Layout layout = SSBO;
443 if (clspv::Option::ConstantArgsInUniformBuffer() &&
444 !clspv::Option::Std430UniformBufferLayout() &&
445 type->getPointeeType().getAddressSpace() ==
446 LangAS::opencl_constant) {
447 layout = UBO;
448 }
alan-baker3d9e2012019-01-11 14:55:30 -0500449 auto array_type = FD->getASTContext().getIncompleteArrayType(
450 type->getPointeeType(), clang::ArrayType::Normal, 0);
alan-baker9bb09792019-03-25 11:25:13 -0400451 if (!IsSupportedLayout(array_type, 0, layout, FD->getASTContext(),
452 P->getSourceRange(),
453 P->getSourceRange())) {
alan-bakerfec0a472018-11-08 18:09:40 -0500454 return false;
455 }
456 }
457 }
458
459 // Check for unsupported vector types.
460 Visitor.TraverseDecl(FD);
461 }
462 }
463 }
464
465 return true;
466 }
467};
468} // namespace
469
470namespace clspv {
471std::unique_ptr<ASTConsumer>
472ExtraValidationASTAction::CreateASTConsumer(CompilerInstance &CI,
473 llvm::StringRef InFile) {
474 return std::unique_ptr<ASTConsumer>(new ExtraValidationConsumer(CI, InFile));
475}
476} // namespace clspv