clang 22.0.0git
SemaHLSL.cpp
Go to the documentation of this file.
1//===- SemaHLSL.cpp - Semantic Analysis for HLSL constructs ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This implements Semantic Analysis for HLSL constructs.
9//===----------------------------------------------------------------------===//
10
11#include "clang/Sema/SemaHLSL.h"
14#include "clang/AST/Attr.h"
15#include "clang/AST/Attrs.inc"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclCXX.h"
21#include "clang/AST/Expr.h"
22#include "clang/AST/Type.h"
23#include "clang/AST/TypeLoc.h"
27#include "clang/Basic/LLVM.h"
32#include "clang/Sema/Lookup.h"
34#include "clang/Sema/Sema.h"
35#include "clang/Sema/Template.h"
36#include "llvm/ADT/ArrayRef.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/SmallVector.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/ADT/StringRef.h"
41#include "llvm/ADT/Twine.h"
42#include "llvm/Frontend/HLSL/HLSLBinding.h"
43#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
44#include "llvm/Support/Casting.h"
45#include "llvm/Support/DXILABI.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/FormatVariadic.h"
48#include "llvm/TargetParser/Triple.h"
49#include <cmath>
50#include <cstddef>
51#include <iterator>
52#include <utility>
53
54using namespace clang;
55using RegisterType = HLSLResourceBindingAttr::RegisterType;
56
58 CXXRecordDecl *StructDecl);
59
61 switch (RC) {
62 case ResourceClass::SRV:
63 return RegisterType::SRV;
64 case ResourceClass::UAV:
65 return RegisterType::UAV;
66 case ResourceClass::CBuffer:
67 return RegisterType::CBuffer;
68 case ResourceClass::Sampler:
69 return RegisterType::Sampler;
70 }
71 llvm_unreachable("unexpected ResourceClass value");
72}
73
74static RegisterType getRegisterType(const HLSLAttributedResourceType *ResTy) {
75 return getRegisterType(ResTy->getAttrs().ResourceClass);
76}
77
78// Converts the first letter of string Slot to RegisterType.
79// Returns false if the letter does not correspond to a valid register type.
80static bool convertToRegisterType(StringRef Slot, RegisterType *RT) {
81 assert(RT != nullptr);
82 switch (Slot[0]) {
83 case 't':
84 case 'T':
85 *RT = RegisterType::SRV;
86 return true;
87 case 'u':
88 case 'U':
89 *RT = RegisterType::UAV;
90 return true;
91 case 'b':
92 case 'B':
93 *RT = RegisterType::CBuffer;
94 return true;
95 case 's':
96 case 'S':
97 *RT = RegisterType::Sampler;
98 return true;
99 case 'c':
100 case 'C':
101 *RT = RegisterType::C;
102 return true;
103 case 'i':
104 case 'I':
105 *RT = RegisterType::I;
106 return true;
107 default:
108 return false;
109 }
110}
111
113 switch (RT) {
114 case RegisterType::SRV:
115 return ResourceClass::SRV;
116 case RegisterType::UAV:
117 return ResourceClass::UAV;
118 case RegisterType::CBuffer:
119 return ResourceClass::CBuffer;
120 case RegisterType::Sampler:
121 return ResourceClass::Sampler;
122 case RegisterType::C:
123 case RegisterType::I:
124 // Deliberately falling through to the unreachable below.
125 break;
126 }
127 llvm_unreachable("unexpected RegisterType value");
128}
129
131 const auto *BT = dyn_cast<BuiltinType>(Type);
132 if (!BT) {
133 if (!Type->isEnumeralType())
134 return Builtin::NotBuiltin;
135 return Builtin::BI__builtin_get_spirv_spec_constant_int;
136 }
137
138 switch (BT->getKind()) {
139 case BuiltinType::Bool:
140 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
141 case BuiltinType::Short:
142 return Builtin::BI__builtin_get_spirv_spec_constant_short;
143 case BuiltinType::Int:
144 return Builtin::BI__builtin_get_spirv_spec_constant_int;
145 case BuiltinType::LongLong:
146 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
147 case BuiltinType::UShort:
148 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
149 case BuiltinType::UInt:
150 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
151 case BuiltinType::ULongLong:
152 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
153 case BuiltinType::Half:
154 return Builtin::BI__builtin_get_spirv_spec_constant_half;
155 case BuiltinType::Float:
156 return Builtin::BI__builtin_get_spirv_spec_constant_float;
157 case BuiltinType::Double:
158 return Builtin::BI__builtin_get_spirv_spec_constant_double;
159 default:
160 return Builtin::NotBuiltin;
161 }
162}
163
165 ResourceClass ResClass) {
166 assert(getDeclBindingInfo(VD, ResClass) == nullptr &&
167 "DeclBindingInfo already added");
168 assert(!hasBindingInfoForDecl(VD) || BindingsList.back().Decl == VD);
169 // VarDecl may have multiple entries for different resource classes.
170 // DeclToBindingListIndex stores the index of the first binding we saw
171 // for this decl. If there are any additional ones then that index
172 // shouldn't be updated.
173 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
174 return &BindingsList.emplace_back(VD, ResClass);
175}
176
178 ResourceClass ResClass) {
179 auto Entry = DeclToBindingListIndex.find(VD);
180 if (Entry != DeclToBindingListIndex.end()) {
181 for (unsigned Index = Entry->getSecond();
182 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
183 ++Index) {
184 if (BindingsList[Index].ResClass == ResClass)
185 return &BindingsList[Index];
186 }
187 }
188 return nullptr;
189}
190
192 return DeclToBindingListIndex.contains(VD);
193}
194
196
197Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
198 SourceLocation KwLoc, IdentifierInfo *Ident,
199 SourceLocation IdentLoc,
200 SourceLocation LBrace) {
201 // For anonymous namespace, take the location of the left brace.
202 DeclContext *LexicalParent = SemaRef.getCurLexicalContext();
204 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
205
206 // if CBuffer is false, then it's a TBuffer
207 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
208 : llvm::hlsl::ResourceClass::SRV;
209 Result->addAttr(HLSLResourceClassAttr::CreateImplicit(getASTContext(), RC));
210
211 SemaRef.PushOnScopeChains(Result, BufferScope);
212 SemaRef.PushDeclContext(BufferScope, Result);
213
214 return Result;
215}
216
217static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context,
218 QualType T) {
219 // Arrays and Structs are always aligned to new buffer rows
220 if (T->isArrayType() || T->isStructureType())
221 return 16;
222
223 // Vectors are aligned to the type they contain
224 if (const VectorType *VT = T->getAs<VectorType>())
225 return calculateLegacyCbufferFieldAlign(Context, VT->getElementType());
226
227 assert(Context.getTypeSize(T) <= 64 &&
228 "Scalar bit widths larger than 64 not supported");
229
230 // Scalar types are aligned to their byte width
231 return Context.getTypeSize(T) / 8;
232}
233
234// Calculate the size of a legacy cbuffer type in bytes based on
235// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
236static unsigned calculateLegacyCbufferSize(const ASTContext &Context,
237 QualType T) {
238 constexpr unsigned CBufferAlign = 16;
239 if (const auto *RD = T->getAsRecordDecl()) {
240 unsigned Size = 0;
241 for (const FieldDecl *Field : RD->fields()) {
242 QualType Ty = Field->getType();
243 unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty);
244 unsigned FieldAlign = calculateLegacyCbufferFieldAlign(Context, Ty);
245
246 // If the field crosses the row boundary after alignment it drops to the
247 // next row
248 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
249 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
250 FieldAlign = CBufferAlign;
251 }
252
253 Size = llvm::alignTo(Size, FieldAlign);
254 Size += FieldSize;
255 }
256 return Size;
257 }
258
259 if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
260 unsigned ElementCount = AT->getSize().getZExtValue();
261 if (ElementCount == 0)
262 return 0;
263
264 unsigned ElementSize =
265 calculateLegacyCbufferSize(Context, AT->getElementType());
266 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
267 return AlignedElementSize * (ElementCount - 1) + ElementSize;
268 }
269
270 if (const VectorType *VT = T->getAs<VectorType>()) {
271 unsigned ElementCount = VT->getNumElements();
272 unsigned ElementSize =
273 calculateLegacyCbufferSize(Context, VT->getElementType());
274 return ElementSize * ElementCount;
275 }
276
277 return Context.getTypeSize(T) / 8;
278}
279
280// Validate packoffset:
281// - if packoffset it used it must be set on all declarations inside the buffer
282// - packoffset ranges must not overlap
283static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl) {
285
286 // Make sure the packoffset annotations are either on all declarations
287 // or on none.
288 bool HasPackOffset = false;
289 bool HasNonPackOffset = false;
290 for (auto *Field : BufDecl->buffer_decls()) {
291 VarDecl *Var = dyn_cast<VarDecl>(Field);
292 if (!Var)
293 continue;
294 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
295 PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
296 HasPackOffset = true;
297 } else {
298 HasNonPackOffset = true;
299 }
300 }
301
302 if (!HasPackOffset)
303 return;
304
305 if (HasNonPackOffset)
306 S.Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);
307
308 // Make sure there is no overlap in packoffset - sort PackOffsetVec by offset
309 // and compare adjacent values.
310 bool IsValid = true;
311 ASTContext &Context = S.getASTContext();
312 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
313 [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
314 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
315 return LHS.second->getOffsetInBytes() <
316 RHS.second->getOffsetInBytes();
317 });
318 for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
319 VarDecl *Var = PackOffsetVec[i].first;
320 HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;
321 unsigned Size = calculateLegacyCbufferSize(Context, Var->getType());
322 unsigned Begin = Attr->getOffsetInBytes();
323 unsigned End = Begin + Size;
324 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
325 if (End > NextBegin) {
326 VarDecl *NextVar = PackOffsetVec[i + 1].first;
327 S.Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)
328 << NextVar << Var;
329 IsValid = false;
330 }
331 }
332 BufDecl->setHasValidPackoffset(IsValid);
333}
334
335// Returns true if the array has a zero size = if any of the dimensions is 0
336static bool isZeroSizedArray(const ConstantArrayType *CAT) {
337 while (CAT && !CAT->isZeroSize())
338 CAT = dyn_cast<ConstantArrayType>(
340 return CAT != nullptr;
341}
342
344 const Type *Ty = VD->getType().getTypePtr();
346}
347
348static const HLSLAttributedResourceType *
350 assert(VD->getType()->isHLSLResourceRecordArray() &&
351 "expected array of resource records");
352 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
353 while (const ArrayType *AT = dyn_cast<ArrayType>(Ty))
355 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
356}
357
358// Returns true if the type is a leaf element type that is not valid to be
359// included in HLSL Buffer, such as a resource class, empty struct, zero-sized
360// array, or a builtin intangible type. Returns false it is a valid leaf element
361// type or if it is a record type that needs to be inspected further.
365 return true;
366 if (const auto *RD = Ty->getAsCXXRecordDecl())
367 return RD->isEmpty();
368 if (Ty->isConstantArrayType() &&
370 return true;
372 return true;
373 return false;
374}
375
376// Returns true if the struct contains at least one element that prevents it
377// from being included inside HLSL Buffer as is, such as an intangible type,
378// empty struct, or zero-sized array. If it does, a new implicit layout struct
379// needs to be created for HLSL Buffer use that will exclude these unwanted
380// declarations (see createHostLayoutStruct function).
382 if (RD->isHLSLIntangible() || RD->isEmpty())
383 return true;
384 // check fields
385 for (const FieldDecl *Field : RD->fields()) {
386 QualType Ty = Field->getType();
388 return true;
389 if (const auto *RD = Ty->getAsCXXRecordDecl();
391 return true;
392 }
393 // check bases
394 for (const CXXBaseSpecifier &Base : RD->bases())
396 Base.getType()->castAsCXXRecordDecl()))
397 return true;
398 return false;
399}
400
402 DeclContext *DC) {
403 CXXRecordDecl *RD = nullptr;
404 for (NamedDecl *Decl :
406 if (CXXRecordDecl *FoundRD = dyn_cast<CXXRecordDecl>(Decl)) {
407 assert(RD == nullptr &&
408 "there should be at most 1 record by a given name in a scope");
409 RD = FoundRD;
410 }
411 }
412 return RD;
413}
414
415// Creates a name for buffer layout struct using the provide name base.
416// If the name must be unique (not previously defined), a suffix is added
417// until a unique name is found.
419 bool MustBeUnique) {
420 ASTContext &AST = S.getASTContext();
421
422 IdentifierInfo *NameBaseII = BaseDecl->getIdentifier();
423 llvm::SmallString<64> Name("__cblayout_");
424 if (NameBaseII) {
425 Name.append(NameBaseII->getName());
426 } else {
427 // anonymous struct
428 Name.append("anon");
429 MustBeUnique = true;
430 }
431
432 size_t NameLength = Name.size();
433 IdentifierInfo *II = &AST.Idents.get(Name, tok::TokenKind::identifier);
434 if (!MustBeUnique)
435 return II;
436
437 unsigned suffix = 0;
438 while (true) {
439 if (suffix != 0) {
440 Name.append("_");
441 Name.append(llvm::Twine(suffix).str());
442 II = &AST.Idents.get(Name, tok::TokenKind::identifier);
443 }
444 if (!findRecordDeclInContext(II, BaseDecl->getDeclContext()))
445 return II;
446 // declaration with that name already exists - increment suffix and try
447 // again until unique name is found
448 suffix++;
449 Name.truncate(NameLength);
450 };
451}
452
453// Creates a field declaration of given name and type for HLSL buffer layout
454// struct. Returns nullptr if the type cannot be use in HLSL Buffer layout.
456 IdentifierInfo *II,
457 CXXRecordDecl *LayoutStruct) {
459 return nullptr;
460
461 if (auto *RD = Ty->getAsCXXRecordDecl()) {
463 RD = createHostLayoutStruct(S, RD);
464 if (!RD)
465 return nullptr;
467 }
468 }
469
470 QualType QT = QualType(Ty, 0);
471 ASTContext &AST = S.getASTContext();
473 auto *Field = FieldDecl::Create(AST, LayoutStruct, SourceLocation(),
474 SourceLocation(), II, QT, TSI, nullptr, false,
476 Field->setAccess(AccessSpecifier::AS_public);
477 return Field;
478}
479
480// Creates host layout struct for a struct included in HLSL Buffer.
481// The layout struct will include only fields that are allowed in HLSL buffer.
482// These fields will be filtered out:
483// - resource classes
484// - empty structs
485// - zero-sized arrays
486// Returns nullptr if the resulting layout struct would be empty.
488 CXXRecordDecl *StructDecl) {
489 assert(requiresImplicitBufferLayoutStructure(StructDecl) &&
490 "struct is already HLSL buffer compatible");
491
492 ASTContext &AST = S.getASTContext();
493 DeclContext *DC = StructDecl->getDeclContext();
494 IdentifierInfo *II = getHostLayoutStructName(S, StructDecl, false);
495
496 // reuse existing if the layout struct if it already exists
497 if (CXXRecordDecl *RD = findRecordDeclInContext(II, DC))
498 return RD;
499
500 CXXRecordDecl *LS =
501 CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, DC, SourceLocation(),
502 SourceLocation(), II);
503 LS->setImplicit(true);
504 LS->addAttr(PackedAttr::CreateImplicit(AST));
505 LS->startDefinition();
506
507 // copy base struct, create HLSL Buffer compatible version if needed
508 if (unsigned NumBases = StructDecl->getNumBases()) {
509 assert(NumBases == 1 && "HLSL supports only one base type");
510 (void)NumBases;
511 CXXBaseSpecifier Base = *StructDecl->bases_begin();
512 CXXRecordDecl *BaseDecl = Base.getType()->castAsCXXRecordDecl();
514 BaseDecl = createHostLayoutStruct(S, BaseDecl);
515 if (BaseDecl) {
516 TypeSourceInfo *TSI =
518 Base = CXXBaseSpecifier(SourceRange(), false, StructDecl->isClass(),
519 AS_none, TSI, SourceLocation());
520 }
521 }
522 if (BaseDecl) {
523 const CXXBaseSpecifier *BasesArray[1] = {&Base};
524 LS->setBases(BasesArray, 1);
525 }
526 }
527
528 // filter struct fields
529 for (const FieldDecl *FD : StructDecl->fields()) {
530 const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();
531 if (FieldDecl *NewFD =
532 createFieldForHostLayoutStruct(S, Ty, FD->getIdentifier(), LS))
533 LS->addDecl(NewFD);
534 }
535 LS->completeDefinition();
536
537 if (LS->field_empty() && LS->getNumBases() == 0)
538 return nullptr;
539
540 DC->addDecl(LS);
541 return LS;
542}
543
544// Creates host layout struct for HLSL Buffer. The struct will include only
545// fields of types that are allowed in HLSL buffer and it will filter out:
546// - static or groupshared variable declarations
547// - resource classes
548// - empty structs
549// - zero-sized arrays
550// - non-variable declarations
551// The layout struct will be added to the HLSLBufferDecl declarations.
553 ASTContext &AST = S.getASTContext();
554 IdentifierInfo *II = getHostLayoutStructName(S, BufDecl, true);
555
556 CXXRecordDecl *LS =
557 CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, BufDecl,
559 LS->addAttr(PackedAttr::CreateImplicit(AST));
560 LS->setImplicit(true);
561 LS->startDefinition();
562
563 for (Decl *D : BufDecl->buffer_decls()) {
564 VarDecl *VD = dyn_cast<VarDecl>(D);
565 if (!VD || VD->getStorageClass() == SC_Static ||
567 continue;
568 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
569 if (FieldDecl *FD =
571 // add the field decl to the layout struct
572 LS->addDecl(FD);
573 // update address space of the original decl to hlsl_constant
574 QualType NewTy =
576 VD->setType(NewTy);
577 }
578 }
579 LS->completeDefinition();
580 BufDecl->addLayoutStruct(LS);
581}
582
584 uint32_t ImplicitBindingOrderID) {
585 auto *Attr =
586 HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {});
587 Attr->setBinding(RT, std::nullopt, 0);
588 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
589 D->addAttr(Attr);
590}
591
592// Handle end of cbuffer/tbuffer declaration
594 auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
595 BufDecl->setRBraceLoc(RBrace);
596
597 validatePackoffset(SemaRef, BufDecl);
598
599 // create buffer layout struct
601
602 HLSLVkBindingAttr *VkBinding = Dcl->getAttr<HLSLVkBindingAttr>();
603 HLSLResourceBindingAttr *RBA = Dcl->getAttr<HLSLResourceBindingAttr>();
604 if (!VkBinding && (!RBA || !RBA->hasRegisterSlot())) {
605 SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding);
606 // Use HLSLResourceBindingAttr to transfer implicit binding order_ID
607 // to codegen. If it does not exist, create an implicit attribute.
608 uint32_t OrderID = getNextImplicitBindingOrderID();
609 if (RBA)
610 RBA->setImplicitBindingOrderID(OrderID);
611 else
613 BufDecl->isCBuffer() ? RegisterType::CBuffer
614 : RegisterType::SRV,
615 OrderID);
616 }
617
618 SemaRef.PopDeclContext();
619}
620
621HLSLNumThreadsAttr *SemaHLSL::mergeNumThreadsAttr(Decl *D,
622 const AttributeCommonInfo &AL,
623 int X, int Y, int Z) {
624 if (HLSLNumThreadsAttr *NT = D->getAttr<HLSLNumThreadsAttr>()) {
625 if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) {
626 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
627 Diag(AL.getLoc(), diag::note_conflicting_attribute);
628 }
629 return nullptr;
630 }
631 return ::new (getASTContext())
632 HLSLNumThreadsAttr(getASTContext(), AL, X, Y, Z);
633}
634
636 const AttributeCommonInfo &AL,
637 int Min, int Max, int Preferred,
638 int SpelledArgsCount) {
639 if (HLSLWaveSizeAttr *WS = D->getAttr<HLSLWaveSizeAttr>()) {
640 if (WS->getMin() != Min || WS->getMax() != Max ||
641 WS->getPreferred() != Preferred ||
642 WS->getSpelledArgsCount() != SpelledArgsCount) {
643 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
644 Diag(AL.getLoc(), diag::note_conflicting_attribute);
645 }
646 return nullptr;
647 }
648 HLSLWaveSizeAttr *Result = ::new (getASTContext())
649 HLSLWaveSizeAttr(getASTContext(), AL, Min, Max, Preferred);
650 Result->setSpelledArgsCount(SpelledArgsCount);
651 return Result;
652}
653
654HLSLVkConstantIdAttr *
656 int Id) {
657
659 if (TargetInfo.getTriple().getArch() != llvm::Triple::spirv) {
660 Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
661 return nullptr;
662 }
663
664 auto *VD = cast<VarDecl>(D);
665
666 if (getSpecConstBuiltinId(VD->getType()->getUnqualifiedDesugaredType()) ==
668 Diag(VD->getLocation(), diag::err_specialization_const);
669 return nullptr;
670 }
671
672 if (!VD->getType().isConstQualified()) {
673 Diag(VD->getLocation(), diag::err_specialization_const);
674 return nullptr;
675 }
676
677 if (HLSLVkConstantIdAttr *CI = D->getAttr<HLSLVkConstantIdAttr>()) {
678 if (CI->getId() != Id) {
679 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
680 Diag(AL.getLoc(), diag::note_conflicting_attribute);
681 }
682 return nullptr;
683 }
684
685 HLSLVkConstantIdAttr *Result =
686 ::new (getASTContext()) HLSLVkConstantIdAttr(getASTContext(), AL, Id);
687 return Result;
688}
689
690HLSLShaderAttr *
692 llvm::Triple::EnvironmentType ShaderType) {
693 if (HLSLShaderAttr *NT = D->getAttr<HLSLShaderAttr>()) {
694 if (NT->getType() != ShaderType) {
695 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
696 Diag(AL.getLoc(), diag::note_conflicting_attribute);
697 }
698 return nullptr;
699 }
700 return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL);
701}
702
703HLSLParamModifierAttr *
705 HLSLParamModifierAttr::Spelling Spelling) {
706 // We can only merge an `in` attribute with an `out` attribute. All other
707 // combinations of duplicated attributes are ill-formed.
708 if (HLSLParamModifierAttr *PA = D->getAttr<HLSLParamModifierAttr>()) {
709 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
710 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
711 D->dropAttr<HLSLParamModifierAttr>();
712 SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()};
713 return HLSLParamModifierAttr::Create(
714 getASTContext(), /*MergedSpelling=*/true, AdjustedRange,
715 HLSLParamModifierAttr::Keyword_inout);
716 }
717 Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
718 Diag(PA->getLocation(), diag::note_conflicting_attribute);
719 return nullptr;
720 }
721 return HLSLParamModifierAttr::Create(getASTContext(), AL);
722}
723
726
728 return;
729
730 // If we have specified a root signature to override the entry function then
731 // attach it now
732 HLSLRootSignatureDecl *SignatureDecl =
734 if (SignatureDecl) {
735 FD->dropAttr<RootSignatureAttr>();
736 // We could look up the SourceRange of the macro here as well
737 AttributeCommonInfo AL(RootSigOverrideIdent, AttributeScopeInfo(),
738 SourceRange(), ParsedAttr::Form::Microsoft());
739 FD->addAttr(::new (getASTContext()) RootSignatureAttr(
740 getASTContext(), AL, RootSigOverrideIdent, SignatureDecl));
741 }
742
743 llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment();
744 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
745 if (const auto *Shader = FD->getAttr<HLSLShaderAttr>()) {
746 // The entry point is already annotated - check that it matches the
747 // triple.
748 if (Shader->getType() != Env) {
749 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
750 << Shader;
751 FD->setInvalidDecl();
752 }
753 } else {
754 // Implicitly add the shader attribute if the entry function isn't
755 // explicitly annotated.
756 FD->addAttr(HLSLShaderAttr::CreateImplicit(getASTContext(), Env,
757 FD->getBeginLoc()));
758 }
759 } else {
760 switch (Env) {
761 case llvm::Triple::UnknownEnvironment:
762 case llvm::Triple::Library:
763 break;
764 case llvm::Triple::RootSignature:
765 llvm_unreachable("rootsig environment has no functions");
766 default:
767 llvm_unreachable("Unhandled environment in triple");
768 }
769 }
770}
771
773 const auto *AnnotationAttr = D->getAttr<HLSLAnnotationAttr>();
774 if (AnnotationAttr) {
775 CheckSemanticAnnotation(FD, D, AnnotationAttr);
776 return true;
777 }
778
779 const Type *T = D->getType()->getUnqualifiedDesugaredType();
780 const RecordType *RT = dyn_cast<RecordType>(T);
781 if (!RT)
782 return false;
783
784 const RecordDecl *RD = RT->getOriginalDecl();
785 for (FieldDecl *Field : RD->fields()) {
786 if (!isSemanticValid(FD, Field))
787 return false;
788 }
789 return true;
790}
791
793 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
794 assert(ShaderAttr && "Entry point has no shader attribute");
795 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
797 VersionTuple Ver = TargetInfo.getTriple().getOSVersion();
798 switch (ST) {
799 case llvm::Triple::Pixel:
800 case llvm::Triple::Vertex:
801 case llvm::Triple::Geometry:
802 case llvm::Triple::Hull:
803 case llvm::Triple::Domain:
804 case llvm::Triple::RayGeneration:
805 case llvm::Triple::Intersection:
806 case llvm::Triple::AnyHit:
807 case llvm::Triple::ClosestHit:
808 case llvm::Triple::Miss:
809 case llvm::Triple::Callable:
810 if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {
812 {llvm::Triple::Compute,
813 llvm::Triple::Amplification,
814 llvm::Triple::Mesh});
815 FD->setInvalidDecl();
816 }
817 if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
819 {llvm::Triple::Compute,
820 llvm::Triple::Amplification,
821 llvm::Triple::Mesh});
822 FD->setInvalidDecl();
823 }
824 break;
825
826 case llvm::Triple::Compute:
827 case llvm::Triple::Amplification:
828 case llvm::Triple::Mesh:
829 if (!FD->hasAttr<HLSLNumThreadsAttr>()) {
830 Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)
831 << llvm::Triple::getEnvironmentTypeName(ST);
832 FD->setInvalidDecl();
833 }
834 if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
835 if (Ver < VersionTuple(6, 6)) {
836 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
837 << WS << "6.6";
838 FD->setInvalidDecl();
839 } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
840 Diag(
841 WS->getLocation(),
842 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
843 << WS << WS->getSpelledArgsCount() << "6.8";
844 FD->setInvalidDecl();
845 }
846 }
847 break;
848 case llvm::Triple::RootSignature:
849 llvm_unreachable("rootsig environment has no function entry point");
850 default:
851 llvm_unreachable("Unhandled environment in triple");
852 }
853
854 for (ParmVarDecl *Param : FD->parameters()) {
855 if (!isSemanticValid(FD, Param)) {
856 Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation);
857 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
858 FD->setInvalidDecl();
859 }
860 }
861 // FIXME: Verify return type semantic annotation.
862}
863
865 FunctionDecl *EntryPoint, const Decl *Param,
866 const HLSLAnnotationAttr *AnnotationAttr) {
867 auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>();
868 assert(ShaderAttr && "Entry point has no shader attribute");
869 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
870
871 switch (AnnotationAttr->getKind()) {
872 case attr::HLSLSV_DispatchThreadID:
873 case attr::HLSLSV_GroupIndex:
874 case attr::HLSLSV_GroupThreadID:
875 case attr::HLSLSV_GroupID:
876 if (ST == llvm::Triple::Compute)
877 return;
878 DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
879 break;
880 case attr::HLSLSV_Position:
881 // TODO(#143523): allow use on other shader types & output once the overall
882 // semantic logic is implemented.
883 if (ST == llvm::Triple::Pixel)
884 return;
885 DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel});
886 break;
887 default:
888 llvm_unreachable("Unknown HLSLAnnotationAttr");
889 }
890}
891
893 const Attr *A, llvm::Triple::EnvironmentType Stage,
894 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
895 SmallVector<StringRef, 8> StageStrings;
896 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
897 [](llvm::Triple::EnvironmentType ST) {
898 return StringRef(
899 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
900 });
901 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
902 << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
903 << (AllowedStages.size() != 1) << join(StageStrings, ", ");
904}
905
906template <CastKind Kind>
907static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
908 if (const auto *VTy = Ty->getAs<VectorType>())
909 Ty = VTy->getElementType();
910 Ty = S.getASTContext().getExtVectorType(Ty, Sz);
911 E = S.ImpCastExprToType(E.get(), Ty, Kind);
912}
913
914template <CastKind Kind>
916 E = S.ImpCastExprToType(E.get(), Ty, Kind);
917 return Ty;
918}
919
921 Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
922 QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
923 bool LHSFloat = LElTy->isRealFloatingType();
924 bool RHSFloat = RElTy->isRealFloatingType();
925
926 if (LHSFloat && RHSFloat) {
927 if (IsCompAssign ||
928 SemaRef.getASTContext().getFloatingTypeOrder(LElTy, RElTy) > 0)
929 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
930
931 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
932 }
933
934 if (LHSFloat)
935 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
936
937 assert(RHSFloat);
938 if (IsCompAssign)
939 return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
940
941 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
942}
943
945 Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
946 QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
947
948 int IntOrder = SemaRef.Context.getIntegerTypeOrder(LElTy, RElTy);
949 bool LHSSigned = LElTy->hasSignedIntegerRepresentation();
950 bool RHSSigned = RElTy->hasSignedIntegerRepresentation();
951 auto &Ctx = SemaRef.getASTContext();
952
953 // If both types have the same signedness, use the higher ranked type.
954 if (LHSSigned == RHSSigned) {
955 if (IsCompAssign || IntOrder >= 0)
956 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
957
958 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
959 }
960
961 // If the unsigned type has greater than or equal rank of the signed type, use
962 // the unsigned type.
963 if (IntOrder != (LHSSigned ? 1 : -1)) {
964 if (IsCompAssign || RHSSigned)
965 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
966 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
967 }
968
969 // At this point the signed type has higher rank than the unsigned type, which
970 // means it will be the same size or bigger. If the signed type is bigger, it
971 // can represent all the values of the unsigned type, so select it.
972 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
973 if (IsCompAssign || LHSSigned)
974 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
975 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
976 }
977
978 // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due
979 // to C/C++ leaking through. The place this happens today is long vs long
980 // long. When arguments are vector<unsigned long, N> and vector<long long, N>,
981 // the long long has higher rank than long even though they are the same size.
982
983 // If this is a compound assignment cast the right hand side to the left hand
984 // side's type.
985 if (IsCompAssign)
986 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
987
988 // If this isn't a compound assignment we convert to unsigned long long.
989 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
990 QualType NewTy = Ctx.getExtVectorType(
991 ElTy, RHSType->castAs<VectorType>()->getNumElements());
992 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
993
994 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
995}
996
998 QualType SrcTy) {
999 if (DestTy->isRealFloatingType() && SrcTy->isRealFloatingType())
1000 return CK_FloatingCast;
1001 if (DestTy->isIntegralType(Ctx) && SrcTy->isIntegralType(Ctx))
1002 return CK_IntegralCast;
1003 if (DestTy->isRealFloatingType())
1004 return CK_IntegralToFloating;
1005 assert(SrcTy->isRealFloatingType() && DestTy->isIntegralType(Ctx));
1006 return CK_FloatingToIntegral;
1007}
1008
1010 QualType LHSType,
1011 QualType RHSType,
1012 bool IsCompAssign) {
1013 const auto *LVecTy = LHSType->getAs<VectorType>();
1014 const auto *RVecTy = RHSType->getAs<VectorType>();
1015 auto &Ctx = getASTContext();
1016
1017 // If the LHS is not a vector and this is a compound assignment, we truncate
1018 // the argument to a scalar then convert it to the LHS's type.
1019 if (!LVecTy && IsCompAssign) {
1020 QualType RElTy = RHSType->castAs<VectorType>()->getElementType();
1021 RHS = SemaRef.ImpCastExprToType(RHS.get(), RElTy, CK_HLSLVectorTruncation);
1022 RHSType = RHS.get()->getType();
1023 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1024 return LHSType;
1025 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSType,
1026 getScalarCastKind(Ctx, LHSType, RHSType));
1027 return LHSType;
1028 }
1029
1030 unsigned EndSz = std::numeric_limits<unsigned>::max();
1031 unsigned LSz = 0;
1032 if (LVecTy)
1033 LSz = EndSz = LVecTy->getNumElements();
1034 if (RVecTy)
1035 EndSz = std::min(RVecTy->getNumElements(), EndSz);
1036 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1037 "one of the above should have had a value");
1038
1039 // In a compound assignment, the left operand does not change type, the right
1040 // operand is converted to the type of the left operand.
1041 if (IsCompAssign && LSz != EndSz) {
1042 Diag(LHS.get()->getBeginLoc(),
1043 diag::err_hlsl_vector_compound_assignment_truncation)
1044 << LHSType << RHSType;
1045 return QualType();
1046 }
1047
1048 if (RVecTy && RVecTy->getNumElements() > EndSz)
1049 castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);
1050 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1051 castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);
1052
1053 if (!RVecTy)
1054 castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);
1055 if (!IsCompAssign && !LVecTy)
1056 castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);
1057
1058 // If we're at the same type after resizing we can stop here.
1059 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1060 return Ctx.getCommonSugaredType(LHSType, RHSType);
1061
1062 QualType LElTy = LHSType->castAs<VectorType>()->getElementType();
1063 QualType RElTy = RHSType->castAs<VectorType>()->getElementType();
1064
1065 // Handle conversion for floating point vectors.
1066 if (LElTy->isRealFloatingType() || RElTy->isRealFloatingType())
1067 return handleFloatVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,
1068 LElTy, RElTy, IsCompAssign);
1069
1070 assert(LElTy->isIntegralType(Ctx) && RElTy->isIntegralType(Ctx) &&
1071 "HLSL Vectors can only contain integer or floating point types");
1072 return handleIntegerVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,
1073 LElTy, RElTy, IsCompAssign);
1074}
1075
1077 BinaryOperatorKind Opc) {
1078 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1079 "Called with non-logical operator");
1081 llvm::raw_svector_ostream OS(Buff);
1082 PrintingPolicy PP(SemaRef.getLangOpts());
1083 StringRef NewFnName = Opc == BO_LOr ? "or" : "and";
1084 OS << NewFnName << "(";
1085 LHS->printPretty(OS, nullptr, PP);
1086 OS << ", ";
1087 RHS->printPretty(OS, nullptr, PP);
1088 OS << ")";
1089 SourceRange FullRange = SourceRange(LHS->getBeginLoc(), RHS->getEndLoc());
1090 SemaRef.Diag(LHS->getBeginLoc(), diag::note_function_suggestion)
1091 << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
1092}
1093
1094std::pair<IdentifierInfo *, bool>
1096 llvm::hash_code Hash = llvm::hash_value(Signature);
1097 std::string IdStr = "__hlsl_rootsig_decl_" + std::to_string(Hash);
1098 IdentifierInfo *DeclIdent = &(getASTContext().Idents.get(IdStr));
1099
1100 // Check if we have already found a decl of the same name.
1101 LookupResult R(SemaRef, DeclIdent, SourceLocation(),
1103 bool Found = SemaRef.LookupQualifiedName(R, SemaRef.CurContext);
1104 return {DeclIdent, Found};
1105}
1106
1108 SourceLocation Loc, IdentifierInfo *DeclIdent,
1110
1111 if (handleRootSignatureElements(RootElements))
1112 return;
1113
1115 for (auto &RootSigElement : RootElements)
1116 Elements.push_back(RootSigElement.getElement());
1117
1118 auto *SignatureDecl = HLSLRootSignatureDecl::Create(
1119 SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc,
1120 DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1121
1122 SignatureDecl->setImplicit();
1123 SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());
1124}
1125
1128 if (RootSigOverrideIdent) {
1129 LookupResult R(SemaRef, RootSigOverrideIdent, SourceLocation(),
1131 if (SemaRef.LookupQualifiedName(R, DC))
1132 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1133 }
1134
1135 return nullptr;
1136}
1137
1138namespace {
1139
1140struct PerVisibilityBindingChecker {
1141 SemaHLSL *S;
1142 // We need one builder per `llvm::dxbc::ShaderVisibility` value.
1143 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1144
1145 struct ElemInfo {
1146 const hlsl::RootSignatureElement *Elem;
1147 llvm::dxbc::ShaderVisibility Vis;
1148 bool Diagnosed;
1149 };
1150 llvm::SmallVector<ElemInfo> ElemInfoMap;
1151
1152 PerVisibilityBindingChecker(SemaHLSL *S) : S(S) {}
1153
1154 void trackBinding(llvm::dxbc::ShaderVisibility Visibility,
1155 llvm::dxil::ResourceClass RC, uint32_t Space,
1156 uint32_t LowerBound, uint32_t UpperBound,
1157 const hlsl::RootSignatureElement *Elem) {
1158 uint32_t BuilderIndex = llvm::to_underlying(Visibility);
1159 assert(BuilderIndex < Builders.size() &&
1160 "Not enough builders for visibility type");
1161 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1162 static_cast<const void *>(Elem));
1163
1164 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1165 "'All' visibility must come first");
1166 if (Visibility == llvm::dxbc::ShaderVisibility::All)
1167 for (size_t I = 1, E = Builders.size(); I < E; ++I)
1168 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1169 static_cast<const void *>(Elem));
1170
1171 ElemInfoMap.push_back({Elem, Visibility, false});
1172 }
1173
1174 ElemInfo &getInfo(const hlsl::RootSignatureElement *Elem) {
1175 auto It = llvm::lower_bound(
1176 ElemInfoMap, Elem,
1177 [](const auto &LHS, const auto &RHS) { return LHS.Elem < RHS; });
1178 assert(It->Elem == Elem && "Element not in map");
1179 return *It;
1180 }
1181
1182 bool checkOverlap() {
1183 llvm::sort(ElemInfoMap, [](const auto &LHS, const auto &RHS) {
1184 return LHS.Elem < RHS.Elem;
1185 });
1186
1187 bool HadOverlap = false;
1188
1189 using llvm::hlsl::BindingInfoBuilder;
1190 auto ReportOverlap = [this,
1191 &HadOverlap](const BindingInfoBuilder &Builder,
1192 const llvm::hlsl::Binding &Reported) {
1193 HadOverlap = true;
1194
1195 const auto *Elem =
1196 static_cast<const hlsl::RootSignatureElement *>(Reported.Cookie);
1197 const llvm::hlsl::Binding &Previous = Builder.findOverlapping(Reported);
1198 const auto *PrevElem =
1199 static_cast<const hlsl::RootSignatureElement *>(Previous.Cookie);
1200
1201 ElemInfo &Info = getInfo(Elem);
1202 // We will have already diagnosed this binding if there's overlap in the
1203 // "All" visibility as well as any particular visibility.
1204 if (Info.Diagnosed)
1205 return;
1206 Info.Diagnosed = true;
1207
1208 ElemInfo &PrevInfo = getInfo(PrevElem);
1209 llvm::dxbc::ShaderVisibility CommonVis =
1210 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1211 : Info.Vis;
1212
1213 this->S->Diag(Elem->getLocation(), diag::err_hlsl_resource_range_overlap)
1214 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1215 << Reported.isUnbounded() << Reported.UpperBound
1216 << llvm::to_underlying(Previous.RC) << Previous.LowerBound
1217 << Previous.isUnbounded() << Previous.UpperBound << Reported.Space
1218 << CommonVis;
1219
1220 this->S->Diag(PrevElem->getLocation(),
1221 diag::note_hlsl_resource_range_here);
1222 };
1223
1224 for (BindingInfoBuilder &Builder : Builders)
1225 Builder.calculateBindingInfo(ReportOverlap);
1226
1227 return HadOverlap;
1228 }
1229};
1230
1231static CXXMethodDecl *lookupMethod(Sema &S, CXXRecordDecl *RecordDecl,
1232 StringRef Name, SourceLocation Loc) {
1233 DeclarationName DeclName(&S.getASTContext().Idents.get(Name));
1234 LookupResult Result(S, DeclName, Loc, Sema::LookupMemberName);
1235 if (!S.LookupQualifiedName(Result, static_cast<DeclContext *>(RecordDecl)))
1236 return nullptr;
1237 return cast<CXXMethodDecl>(Result.getFoundDecl());
1238}
1239
1240} // end anonymous namespace
1241
1244 // Define some common error handling functions
1245 bool HadError = false;
1246 auto ReportError = [this, &HadError](SourceLocation Loc, uint32_t LowerBound,
1247 uint32_t UpperBound) {
1248 HadError = true;
1249 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1250 << LowerBound << UpperBound;
1251 };
1252
1253 auto ReportFloatError = [this, &HadError](SourceLocation Loc,
1254 float LowerBound,
1255 float UpperBound) {
1256 HadError = true;
1257 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1258 << llvm::formatv("{0:f}", LowerBound).sstr<6>()
1259 << llvm::formatv("{0:f}", UpperBound).sstr<6>();
1260 };
1261
1262 auto VerifyRegister = [ReportError](SourceLocation Loc, uint32_t Register) {
1263 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1264 ReportError(Loc, 0, 0xfffffffe);
1265 };
1266
1267 auto VerifySpace = [ReportError](SourceLocation Loc, uint32_t Space) {
1268 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1269 ReportError(Loc, 0, 0xffffffef);
1270 };
1271
1272 const uint32_t Version =
1273 llvm::to_underlying(SemaRef.getLangOpts().HLSLRootSigVer);
1274 const uint32_t VersionEnum = Version - 1;
1275 auto ReportFlagError = [this, &HadError, VersionEnum](SourceLocation Loc) {
1276 HadError = true;
1277 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1278 << /*version minor*/ VersionEnum;
1279 };
1280
1281 // Iterate through the elements and do basic validations
1282 for (const hlsl::RootSignatureElement &RootSigElem : Elements) {
1283 SourceLocation Loc = RootSigElem.getLocation();
1284 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();
1285 if (const auto *Descriptor =
1286 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1287 VerifyRegister(Loc, Descriptor->Reg.Number);
1288 VerifySpace(Loc, Descriptor->Space);
1289
1290 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(
1291 Version, llvm::to_underlying(Descriptor->Flags)))
1292 ReportFlagError(Loc);
1293 } else if (const auto *Constants =
1294 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1295 VerifyRegister(Loc, Constants->Reg.Number);
1296 VerifySpace(Loc, Constants->Space);
1297 } else if (const auto *Sampler =
1298 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1299 VerifyRegister(Loc, Sampler->Reg.Number);
1300 VerifySpace(Loc, Sampler->Space);
1301
1302 assert(!std::isnan(Sampler->MaxLOD) && !std::isnan(Sampler->MinLOD) &&
1303 "By construction, parseFloatParam can't produce a NaN from a "
1304 "float_literal token");
1305
1306 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1307 ReportError(Loc, 0, 16);
1308 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1309 ReportFloatError(Loc, -16.f, 15.99f);
1310 } else if (const auto *Clause =
1311 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1312 &Elem)) {
1313 VerifyRegister(Loc, Clause->Reg.Number);
1314 VerifySpace(Loc, Clause->Space);
1315
1316 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1317 // NumDescriptor could techincally be ~0u but that is reserved for
1318 // unbounded, so the diagnostic will not report that as a valid int
1319 // value
1320 ReportError(Loc, 1, 0xfffffffe);
1321 }
1322
1323 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1324 Clause->Flags))
1325 ReportFlagError(Loc);
1326 }
1327 }
1328
1329 PerVisibilityBindingChecker BindingChecker(this);
1330 SmallVector<std::pair<const llvm::hlsl::rootsig::DescriptorTableClause *,
1332 UnboundClauses;
1333
1334 for (const hlsl::RootSignatureElement &RootSigElem : Elements) {
1335 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();
1336 if (const auto *Descriptor =
1337 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1338 uint32_t LowerBound(Descriptor->Reg.Number);
1339 uint32_t UpperBound(LowerBound); // inclusive range
1340
1341 BindingChecker.trackBinding(
1342 Descriptor->Visibility,
1343 static_cast<llvm::dxil::ResourceClass>(Descriptor->Type),
1344 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1345 } else if (const auto *Constants =
1346 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1347 uint32_t LowerBound(Constants->Reg.Number);
1348 uint32_t UpperBound(LowerBound); // inclusive range
1349
1350 BindingChecker.trackBinding(
1351 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1352 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1353 } else if (const auto *Sampler =
1354 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1355 uint32_t LowerBound(Sampler->Reg.Number);
1356 uint32_t UpperBound(LowerBound); // inclusive range
1357
1358 BindingChecker.trackBinding(
1359 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1360 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1361 } else if (const auto *Clause =
1362 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1363 &Elem)) {
1364 // We'll process these once we see the table element.
1365 UnboundClauses.emplace_back(Clause, &RootSigElem);
1366 } else if (const auto *Table =
1367 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1368 assert(UnboundClauses.size() == Table->NumClauses &&
1369 "Number of unbound elements must match the number of clauses");
1370 bool HasAnySampler = false;
1371 bool HasAnyNonSampler = false;
1372 uint32_t Offset = 0;
1373 for (const auto &[Clause, ClauseElem] : UnboundClauses) {
1374 SourceLocation Loc = ClauseElem->getLocation();
1375 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1376 HasAnySampler = true;
1377 else
1378 HasAnyNonSampler = true;
1379
1380 if (HasAnySampler && HasAnyNonSampler)
1381 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1382
1383 // Relevant error will have already been reported above and needs to be
1384 // fixed before we can conduct further analysis, so shortcut error
1385 // return
1386 if (Clause->NumDescriptors == 0)
1387 return true;
1388
1389 if (Clause->Offset !=
1390 llvm::hlsl::rootsig::DescriptorTableOffsetAppend) {
1391 // Manually specified the offset
1392 Offset = Clause->Offset;
1393 }
1394
1395 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1396 Offset, Clause->NumDescriptors);
1397
1398 if (!llvm::hlsl::rootsig::verifyBoundOffset(Offset)) {
1399 // Trying to append onto unbound offset
1400 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1401 } else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound)) {
1402 // Upper bound overflows maximum offset
1403 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1404 }
1405
1406 Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded
1407 ? uint32_t(RangeBound)
1408 : uint32_t(RangeBound + 1);
1409
1410 // Compute the register bounds and track resource binding
1411 uint32_t LowerBound(Clause->Reg.Number);
1412 uint32_t UpperBound = Clause->NumDescriptors == ~0u
1413 ? ~0u
1414 : LowerBound + Clause->NumDescriptors - 1;
1415
1416 BindingChecker.trackBinding(
1417 Table->Visibility,
1418 static_cast<llvm::dxil::ResourceClass>(Clause->Type), Clause->Space,
1419 LowerBound, UpperBound, ClauseElem);
1420 }
1421 UnboundClauses.clear();
1422 }
1423 }
1424
1425 return BindingChecker.checkOverlap();
1426}
1427
1429 if (AL.getNumArgs() != 1) {
1430 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1431 return;
1432 }
1433
1435 if (auto *RS = D->getAttr<RootSignatureAttr>()) {
1436 if (RS->getSignatureIdent() != Ident) {
1437 Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1438 return;
1439 }
1440
1441 Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1442 return;
1443 }
1444
1446 if (SemaRef.LookupQualifiedName(R, D->getDeclContext()))
1447 if (auto *SignatureDecl =
1448 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1449 D->addAttr(::new (getASTContext()) RootSignatureAttr(
1450 getASTContext(), AL, Ident, SignatureDecl));
1451 }
1452}
1453
1455 llvm::VersionTuple SMVersion =
1456 getASTContext().getTargetInfo().getTriple().getOSVersion();
1457 bool IsDXIL = getASTContext().getTargetInfo().getTriple().getArch() ==
1458 llvm::Triple::dxil;
1459
1460 uint32_t ZMax = 1024;
1461 uint32_t ThreadMax = 1024;
1462 if (IsDXIL && SMVersion.getMajor() <= 4) {
1463 ZMax = 1;
1464 ThreadMax = 768;
1465 } else if (IsDXIL && SMVersion.getMajor() == 5) {
1466 ZMax = 64;
1467 ThreadMax = 1024;
1468 }
1469
1470 uint32_t X;
1471 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), X))
1472 return;
1473 if (X > 1024) {
1474 Diag(AL.getArgAsExpr(0)->getExprLoc(),
1475 diag::err_hlsl_numthreads_argument_oor)
1476 << 0 << 1024;
1477 return;
1478 }
1479 uint32_t Y;
1480 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Y))
1481 return;
1482 if (Y > 1024) {
1483 Diag(AL.getArgAsExpr(1)->getExprLoc(),
1484 diag::err_hlsl_numthreads_argument_oor)
1485 << 1 << 1024;
1486 return;
1487 }
1488 uint32_t Z;
1489 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Z))
1490 return;
1491 if (Z > ZMax) {
1492 SemaRef.Diag(AL.getArgAsExpr(2)->getExprLoc(),
1493 diag::err_hlsl_numthreads_argument_oor)
1494 << 2 << ZMax;
1495 return;
1496 }
1497
1498 if (X * Y * Z > ThreadMax) {
1499 Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1500 return;
1501 }
1502
1503 HLSLNumThreadsAttr *NewAttr = mergeNumThreadsAttr(D, AL, X, Y, Z);
1504 if (NewAttr)
1505 D->addAttr(NewAttr);
1506}
1507
1508static bool isValidWaveSizeValue(unsigned Value) {
1509 return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;
1510}
1511
1513 // validate that the wavesize argument is a power of 2 between 4 and 128
1514 // inclusive
1515 unsigned SpelledArgsCount = AL.getNumArgs();
1516 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1517 return;
1518
1519 uint32_t Min;
1520 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Min))
1521 return;
1522
1523 uint32_t Max = 0;
1524 if (SpelledArgsCount > 1 &&
1525 !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Max))
1526 return;
1527
1528 uint32_t Preferred = 0;
1529 if (SpelledArgsCount > 2 &&
1530 !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Preferred))
1531 return;
1532
1533 if (SpelledArgsCount > 2) {
1534 if (!isValidWaveSizeValue(Preferred)) {
1535 Diag(AL.getArgAsExpr(2)->getExprLoc(),
1536 diag::err_attribute_power_of_two_in_range)
1537 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1538 << Preferred;
1539 return;
1540 }
1541 // Preferred not in range.
1542 if (Preferred < Min || Preferred > Max) {
1543 Diag(AL.getArgAsExpr(2)->getExprLoc(),
1544 diag::err_attribute_power_of_two_in_range)
1545 << AL << Min << Max << Preferred;
1546 return;
1547 }
1548 } else if (SpelledArgsCount > 1) {
1549 if (!isValidWaveSizeValue(Max)) {
1550 Diag(AL.getArgAsExpr(1)->getExprLoc(),
1551 diag::err_attribute_power_of_two_in_range)
1552 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;
1553 return;
1554 }
1555 if (Max < Min) {
1556 Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1557 return;
1558 } else if (Max == Min) {
1559 Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;
1560 }
1561 } else {
1562 if (!isValidWaveSizeValue(Min)) {
1563 Diag(AL.getArgAsExpr(0)->getExprLoc(),
1564 diag::err_attribute_power_of_two_in_range)
1565 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;
1566 return;
1567 }
1568 }
1569
1570 HLSLWaveSizeAttr *NewAttr =
1571 mergeWaveSizeAttr(D, AL, Min, Max, Preferred, SpelledArgsCount);
1572 if (NewAttr)
1573 D->addAttr(NewAttr);
1574}
1575
1577 uint32_t ID;
1578 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), ID))
1579 return;
1580 D->addAttr(::new (getASTContext())
1581 HLSLVkExtBuiltinInputAttr(getASTContext(), AL, ID));
1582}
1583
1585 uint32_t Id;
1586 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Id))
1587 return;
1588 HLSLVkConstantIdAttr *NewAttr = mergeVkConstantIdAttr(D, AL, Id);
1589 if (NewAttr)
1590 D->addAttr(NewAttr);
1591}
1592
1594 // The vk::binding attribute only applies to SPIR-V.
1595 if (!getASTContext().getTargetInfo().getTriple().isSPIRV())
1596 return;
1597
1598 uint32_t Binding = 0;
1599 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Binding))
1600 return;
1601 uint32_t Set = 0;
1602 if (AL.getNumArgs() > 1 &&
1603 !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Set))
1604 return;
1605
1606 D->addAttr(::new (getASTContext())
1607 HLSLVkBindingAttr(getASTContext(), AL, Binding, Set));
1608}
1609
1611 const auto *VT = T->getAs<VectorType>();
1612
1613 if (!T->hasUnsignedIntegerRepresentation() ||
1614 (VT && VT->getNumElements() > 3)) {
1615 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1616 << AL << "uint/uint2/uint3";
1617 return false;
1618 }
1619
1620 return true;
1621}
1622
1624 const auto *VT = T->getAs<VectorType>();
1625 if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1626 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1627 << AL << "float/float1/float2/float3/float4";
1628 return false;
1629 }
1630
1631 return true;
1632}
1633
1635 std::optional<unsigned> Index) {
1636 std::string SemanticName = AL.getAttrName()->getName().upper();
1637
1638 auto *VD = cast<ValueDecl>(D);
1639 QualType ValueType = VD->getType();
1640 if (auto *FD = dyn_cast<FunctionDecl>(D))
1641 ValueType = FD->getReturnType();
1642
1643 bool IsOutput = false;
1644 if (HLSLParamModifierAttr *MA = D->getAttr<HLSLParamModifierAttr>()) {
1645 if (MA->isOut()) {
1646 IsOutput = true;
1647 ValueType = cast<ReferenceType>(ValueType)->getPointeeType();
1648 }
1649 }
1650
1651 Attr *Attribute = nullptr;
1652 if (SemanticName == "SV_DISPATCHTHREADID") {
1653 diagnoseInputIDType(ValueType, AL);
1654 if (IsOutput)
1655 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1657 } else if (SemanticName == "SV_GROUPINDEX") {
1658 if (IsOutput)
1659 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1660 Attribute = createSemanticAttr<HLSLSV_GroupIndexAttr>(AL, Index);
1661 } else if (SemanticName == "SV_GROUPTHREADID") {
1662 diagnoseInputIDType(ValueType, AL);
1663 if (IsOutput)
1664 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1665 Attribute = createSemanticAttr<HLSLSV_GroupThreadIDAttr>(AL, Index);
1666 } else if (SemanticName == "SV_GROUPID") {
1667 diagnoseInputIDType(ValueType, AL);
1668 if (IsOutput)
1669 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1670 Attribute = createSemanticAttr<HLSLSV_GroupIDAttr>(AL, Index);
1671 } else if (SemanticName == "SV_POSITION") {
1672 const auto *VT = ValueType->getAs<VectorType>();
1673 if (!ValueType->hasFloatingRepresentation() ||
1674 (VT && VT->getNumElements() > 4))
1675 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1676 << AL << "float/float1/float2/float3/float4";
1677 Attribute = createSemanticAttr<HLSLSV_PositionAttr>(AL, Index);
1678 } else
1679 Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1680
1681 if (!Attribute)
1682 return;
1683 D->addAttr(Attribute);
1684}
1685
1687 uint32_t IndexValue, ExplicitIndex;
1688 SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), IndexValue);
1689 SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), ExplicitIndex);
1690 assert(IndexValue > 0 ? ExplicitIndex : true);
1691 std::optional<unsigned> Index =
1692 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1693
1694 if (AL.getAttrName()->getName().starts_with_insensitive("SV_"))
1695 diagnoseSystemSemanticAttr(D, AL, Index);
1696 else
1697 Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1698}
1699
1702 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1703 << AL << "shader constant in a constant buffer";
1704 return;
1705 }
1706
1707 uint32_t SubComponent;
1708 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), SubComponent))
1709 return;
1710 uint32_t Component;
1711 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Component))
1712 return;
1713
1714 QualType T = cast<VarDecl>(D)->getType().getCanonicalType();
1715 // Check if T is an array or struct type.
1716 // TODO: mark matrix type as aggregate type.
1717 bool IsAggregateTy = (T->isArrayType() || T->isStructureType());
1718
1719 // Check Component is valid for T.
1720 if (Component) {
1721 unsigned Size = getASTContext().getTypeSize(T);
1722 if (IsAggregateTy || Size > 128) {
1723 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1724 return;
1725 } else {
1726 // Make sure Component + sizeof(T) <= 4.
1727 if ((Component * 32 + Size) > 128) {
1728 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1729 return;
1730 }
1731 QualType EltTy = T;
1732 if (const auto *VT = T->getAs<VectorType>())
1733 EltTy = VT->getElementType();
1734 unsigned Align = getASTContext().getTypeAlign(EltTy);
1735 if (Align > 32 && Component == 1) {
1736 // NOTE: Component 3 will hit err_hlsl_packoffset_cross_reg_boundary.
1737 // So we only need to check Component 1 here.
1738 Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1739 << Align << EltTy;
1740 return;
1741 }
1742 }
1743 }
1744
1745 D->addAttr(::new (getASTContext()) HLSLPackOffsetAttr(
1746 getASTContext(), AL, SubComponent, Component));
1747}
1748
1750 StringRef Str;
1751 SourceLocation ArgLoc;
1752 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1753 return;
1754
1755 llvm::Triple::EnvironmentType ShaderType;
1756 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1757 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1758 << AL << Str << ArgLoc;
1759 return;
1760 }
1761
1762 // FIXME: check function match the shader stage.
1763
1764 HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);
1765 if (NewAttr)
1766 D->addAttr(NewAttr);
1767}
1768
1770 Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,
1771 QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo) {
1772 assert(AttrList.size() && "expected list of resource attributes");
1773
1774 QualType ContainedTy = QualType();
1775 TypeSourceInfo *ContainedTyInfo = nullptr;
1776 SourceLocation LocBegin = AttrList[0]->getRange().getBegin();
1777 SourceLocation LocEnd = AttrList[0]->getRange().getEnd();
1778
1779 HLSLAttributedResourceType::Attributes ResAttrs;
1780
1781 bool HasResourceClass = false;
1782 for (const Attr *A : AttrList) {
1783 if (!A)
1784 continue;
1785 LocEnd = A->getRange().getEnd();
1786 switch (A->getKind()) {
1787 case attr::HLSLResourceClass: {
1788 ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
1789 if (HasResourceClass) {
1790 S.Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1791 ? diag::warn_duplicate_attribute_exact
1792 : diag::warn_duplicate_attribute)
1793 << A;
1794 return false;
1795 }
1796 ResAttrs.ResourceClass = RC;
1797 HasResourceClass = true;
1798 break;
1799 }
1800 case attr::HLSLROV:
1801 if (ResAttrs.IsROV) {
1802 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1803 return false;
1804 }
1805 ResAttrs.IsROV = true;
1806 break;
1807 case attr::HLSLRawBuffer:
1808 if (ResAttrs.RawBuffer) {
1809 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1810 return false;
1811 }
1812 ResAttrs.RawBuffer = true;
1813 break;
1814 case attr::HLSLContainedType: {
1815 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
1816 QualType Ty = CTAttr->getType();
1817 if (!ContainedTy.isNull()) {
1818 S.Diag(A->getLocation(), ContainedTy == Ty
1819 ? diag::warn_duplicate_attribute_exact
1820 : diag::warn_duplicate_attribute)
1821 << A;
1822 return false;
1823 }
1824 ContainedTy = Ty;
1825 ContainedTyInfo = CTAttr->getTypeLoc();
1826 break;
1827 }
1828 default:
1829 llvm_unreachable("unhandled resource attribute type");
1830 }
1831 }
1832
1833 if (!HasResourceClass) {
1834 S.Diag(AttrList.back()->getRange().getEnd(),
1835 diag::err_hlsl_missing_resource_class);
1836 return false;
1837 }
1838
1840 Wrapped, ContainedTy, ResAttrs);
1841
1842 if (LocInfo && ContainedTyInfo) {
1843 LocInfo->Range = SourceRange(LocBegin, LocEnd);
1844 LocInfo->ContainedTyInfo = ContainedTyInfo;
1845 }
1846 return true;
1847}
1848
1849// Validates and creates an HLSL attribute that is applied as type attribute on
1850// HLSL resource. The attributes are collected in HLSLResourcesTypeAttrs and at
1851// the end of the declaration they are applied to the declaration type by
1852// wrapping it in HLSLAttributedResourceType.
1854 // only allow resource type attributes on intangible types
1855 if (!T->isHLSLResourceType()) {
1856 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1857 << AL << getASTContext().HLSLResourceTy;
1858 return false;
1859 }
1860
1861 // validate number of arguments
1862 if (!AL.checkExactlyNumArgs(SemaRef, AL.getMinArgs()))
1863 return false;
1864
1865 Attr *A = nullptr;
1866
1870 {
1871 AttributeCommonInfo::AS_CXX11, 0, false /*IsAlignas*/,
1872 false /*IsRegularKeywordAttribute*/
1873 });
1874
1875 switch (AL.getKind()) {
1876 case ParsedAttr::AT_HLSLResourceClass: {
1877 if (!AL.isArgIdent(0)) {
1878 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1879 << AL << AANT_ArgumentIdentifier;
1880 return false;
1881 }
1882
1883 IdentifierLoc *Loc = AL.getArgAsIdent(0);
1884 StringRef Identifier = Loc->getIdentifierInfo()->getName();
1885 SourceLocation ArgLoc = Loc->getLoc();
1886
1887 // Validate resource class value
1888 ResourceClass RC;
1889 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1890 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1891 << "ResourceClass" << Identifier;
1892 return false;
1893 }
1894 A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);
1895 break;
1896 }
1897
1898 case ParsedAttr::AT_HLSLROV:
1899 A = HLSLROVAttr::Create(getASTContext(), ACI);
1900 break;
1901
1902 case ParsedAttr::AT_HLSLRawBuffer:
1903 A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
1904 break;
1905
1906 case ParsedAttr::AT_HLSLContainedType: {
1907 if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {
1908 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1909 return false;
1910 }
1911
1912 TypeSourceInfo *TSI = nullptr;
1913 QualType QT = SemaRef.GetTypeFromParser(AL.getTypeArg(), &TSI);
1914 assert(TSI && "no type source info for attribute argument");
1915 if (SemaRef.RequireCompleteType(TSI->getTypeLoc().getBeginLoc(), QT,
1916 diag::err_incomplete_type))
1917 return false;
1918 A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);
1919 break;
1920 }
1921
1922 default:
1923 llvm_unreachable("unhandled HLSL attribute");
1924 }
1925
1926 HLSLResourcesTypeAttrs.emplace_back(A);
1927 return true;
1928}
1929
1930// Combines all resource type attributes and creates HLSLAttributedResourceType.
1932 if (!HLSLResourcesTypeAttrs.size())
1933 return CurrentType;
1934
1935 QualType QT = CurrentType;
1938 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1939 const HLSLAttributedResourceType *RT =
1941
1942 // Temporarily store TypeLoc information for the new type.
1943 // It will be transferred to HLSLAttributesResourceTypeLoc
1944 // shortly after the type is created by TypeSpecLocFiller which
1945 // will call the TakeLocForHLSLAttribute method below.
1946 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1947 }
1948 HLSLResourcesTypeAttrs.clear();
1949 return QT;
1950}
1951
1952// Returns source location for the HLSLAttributedResourceType
1954SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) {
1955 HLSLAttributedResourceLocInfo LocInfo = {};
1956 auto I = LocsForHLSLAttributedResources.find(RT);
1957 if (I != LocsForHLSLAttributedResources.end()) {
1958 LocInfo = I->second;
1959 LocsForHLSLAttributedResources.erase(I);
1960 return LocInfo;
1961 }
1962 LocInfo.Range = SourceRange();
1963 return LocInfo;
1964}
1965
1966// Walks though the global variable declaration, collects all resource binding
1967// requirements and adds them to Bindings
1968void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
1969 const RecordType *RT) {
1970 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1971 for (FieldDecl *FD : RD->fields()) {
1972 const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();
1973
1974 // Unwrap arrays
1975 // FIXME: Calculate array size while unwrapping
1976 assert(!Ty->isIncompleteArrayType() &&
1977 "incomplete arrays inside user defined types are not supported");
1978 while (Ty->isConstantArrayType()) {
1981 }
1982
1983 if (!Ty->isRecordType())
1984 continue;
1985
1986 if (const HLSLAttributedResourceType *AttrResType =
1987 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
1988 // Add a new DeclBindingInfo to Bindings if it does not already exist
1989 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1990 DeclBindingInfo *DBI = Bindings.getDeclBindingInfo(VD, RC);
1991 if (!DBI)
1992 Bindings.addDeclBindingInfo(VD, RC);
1993 } else if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1994 // Recursively scan embedded struct or class; it would be nice to do this
1995 // without recursion, but tricky to correctly calculate the size of the
1996 // binding, which is something we are probably going to need to do later
1997 // on. Hopefully nesting of structs in structs too many levels is
1998 // unlikely.
1999 collectResourceBindingsOnUserRecordDecl(VD, RT);
2000 }
2001 }
2002}
2003
2004// Diagnose localized register binding errors for a single binding; does not
2005// diagnose resource binding on user record types, that will be done later
2006// in processResourceBindingOnDecl based on the information collected in
2007// collectResourceBindingsOnVarDecl.
2008// Returns false if the register binding is not valid.
2010 Decl *D, RegisterType RegType,
2011 bool SpecifiedSpace) {
2012 int RegTypeNum = static_cast<int>(RegType);
2013
2014 // check if the decl type is groupshared
2015 if (D->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2016 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2017 return false;
2018 }
2019
2020 // Cbuffers and Tbuffers are HLSLBufferDecl types
2021 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2022 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2023 : ResourceClass::SRV;
2024 if (RegType == getRegisterType(RC))
2025 return true;
2026
2027 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
2028 << RegTypeNum;
2029 return false;
2030 }
2031
2032 // Samplers, UAVs, and SRVs are VarDecl types
2033 assert(isa<VarDecl>(D) && "D is expected to be VarDecl or HLSLBufferDecl");
2034 VarDecl *VD = cast<VarDecl>(D);
2035
2036 // Resource
2037 if (const HLSLAttributedResourceType *AttrResType =
2038 HLSLAttributedResourceType::findHandleTypeOnResource(
2039 VD->getType().getTypePtr())) {
2040 if (RegType == getRegisterType(AttrResType))
2041 return true;
2042
2043 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
2044 << RegTypeNum;
2045 return false;
2046 }
2047
2048 const clang::Type *Ty = VD->getType().getTypePtr();
2049 while (Ty->isArrayType())
2051
2052 // Basic types
2053 if (Ty->isArithmeticType() || Ty->isVectorType()) {
2054 bool DeclaredInCOrTBuffer = isa<HLSLBufferDecl>(D->getDeclContext());
2055 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2056 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2057
2058 if (!DeclaredInCOrTBuffer && (Ty->isIntegralType(S.getASTContext()) ||
2059 Ty->isFloatingType() || Ty->isVectorType())) {
2060 // Register annotation on default constant buffer declaration ($Globals)
2061 if (RegType == RegisterType::CBuffer)
2062 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2063 else if (RegType != RegisterType::C)
2064 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2065 else
2066 return true;
2067 } else {
2068 if (RegType == RegisterType::C)
2069 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2070 else
2071 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2072 }
2073 return false;
2074 }
2075 if (Ty->isRecordType())
2076 // RecordTypes will be diagnosed in processResourceBindingOnDecl
2077 // that is called from ActOnVariableDeclarator
2078 return true;
2079
2080 // Anything else is an error
2081 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2082 return false;
2083}
2084
2086 RegisterType regType) {
2087 // make sure that there are no two register annotations
2088 // applied to the decl with the same register type
2089 bool RegisterTypesDetected[5] = {false};
2090 RegisterTypesDetected[static_cast<int>(regType)] = true;
2091
2092 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {
2093 if (HLSLResourceBindingAttr *attr =
2094 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2095
2096 RegisterType otherRegType = attr->getRegisterType();
2097 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {
2098 int otherRegTypeNum = static_cast<int>(otherRegType);
2099 S.Diag(TheDecl->getLocation(),
2100 diag::err_hlsl_duplicate_register_annotation)
2101 << otherRegTypeNum;
2102 return false;
2103 }
2104 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;
2105 }
2106 }
2107 return true;
2108}
2109
2111 Decl *D, RegisterType RegType,
2112 bool SpecifiedSpace) {
2113
2114 // exactly one of these two types should be set
2115 assert(((isa<VarDecl>(D) && !isa<HLSLBufferDecl>(D)) ||
2116 (!isa<VarDecl>(D) && isa<HLSLBufferDecl>(D))) &&
2117 "expecting VarDecl or HLSLBufferDecl");
2118
2119 // check if the declaration contains resource matching the register type
2120 if (!DiagnoseLocalRegisterBinding(S, ArgLoc, D, RegType, SpecifiedSpace))
2121 return false;
2122
2123 // next, if multiple register annotations exist, check that none conflict.
2124 return ValidateMultipleRegisterAnnotations(S, D, RegType);
2125}
2126
2128 if (VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2129 QualType Ty = VD->getType();
2130 if (const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2131 Ty = IAT->getElementType();
2132 if (SemaRef.RequireCompleteType(TheDecl->getBeginLoc(), Ty,
2133 diag::err_incomplete_type))
2134 return;
2135 }
2136
2137 StringRef Slot = "";
2138 StringRef Space = "";
2139 SourceLocation SlotLoc, SpaceLoc;
2140
2141 if (!AL.isArgIdent(0)) {
2142 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2143 << AL << AANT_ArgumentIdentifier;
2144 return;
2145 }
2146 IdentifierLoc *Loc = AL.getArgAsIdent(0);
2147
2148 if (AL.getNumArgs() == 2) {
2149 Slot = Loc->getIdentifierInfo()->getName();
2150 SlotLoc = Loc->getLoc();
2151 if (!AL.isArgIdent(1)) {
2152 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2153 << AL << AANT_ArgumentIdentifier;
2154 return;
2155 }
2156 Loc = AL.getArgAsIdent(1);
2157 Space = Loc->getIdentifierInfo()->getName();
2158 SpaceLoc = Loc->getLoc();
2159 } else {
2160 StringRef Str = Loc->getIdentifierInfo()->getName();
2161 if (Str.starts_with("space")) {
2162 Space = Str;
2163 SpaceLoc = Loc->getLoc();
2164 } else {
2165 Slot = Str;
2166 SlotLoc = Loc->getLoc();
2167 Space = "space0";
2168 }
2169 }
2170
2171 RegisterType RegType = RegisterType::SRV;
2172 std::optional<unsigned> SlotNum;
2173 unsigned SpaceNum = 0;
2174
2175 // Validate slot
2176 if (!Slot.empty()) {
2177 if (!convertToRegisterType(Slot, &RegType)) {
2178 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2179 return;
2180 }
2181 if (RegType == RegisterType::I) {
2182 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2183 return;
2184 }
2185 StringRef SlotNumStr = Slot.substr(1);
2186 unsigned N;
2187 if (SlotNumStr.getAsInteger(10, N)) {
2188 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2189 return;
2190 }
2191 SlotNum = N;
2192 }
2193
2194 // Validate space
2195 if (!Space.starts_with("space")) {
2196 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2197 return;
2198 }
2199 StringRef SpaceNumStr = Space.substr(5);
2200 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2201 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2202 return;
2203 }
2204
2205 // If we have slot, diagnose it is the right register type for the decl
2206 if (SlotNum.has_value())
2207 if (!DiagnoseHLSLRegisterAttribute(SemaRef, SlotLoc, TheDecl, RegType,
2208 !SpaceLoc.isInvalid()))
2209 return;
2210
2211 HLSLResourceBindingAttr *NewAttr =
2212 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
2213 if (NewAttr) {
2214 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2215 TheDecl->addAttr(NewAttr);
2216 }
2217}
2218
2220 HLSLParamModifierAttr *NewAttr = mergeParamModifierAttr(
2221 D, AL,
2222 static_cast<HLSLParamModifierAttr::Spelling>(AL.getSemanticSpelling()));
2223 if (NewAttr)
2224 D->addAttr(NewAttr);
2225}
2226
2227namespace {
2228
2229/// This class implements HLSL availability diagnostics for default
2230/// and relaxed mode
2231///
2232/// The goal of this diagnostic is to emit an error or warning when an
2233/// unavailable API is found in code that is reachable from the shader
2234/// entry function or from an exported function (when compiling a shader
2235/// library).
2236///
2237/// This is done by traversing the AST of all shader entry point functions
2238/// and of all exported functions, and any functions that are referenced
2239/// from this AST. In other words, any functions that are reachable from
2240/// the entry points.
2241class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
2242 Sema &SemaRef;
2243
2244 // Stack of functions to be scaned
2246
2247 // Tracks which environments functions have been scanned in.
2248 //
2249 // Maps FunctionDecl to an unsigned number that represents the set of shader
2250 // environments the function has been scanned for.
2251 // The llvm::Triple::EnvironmentType enum values for shader stages guaranteed
2252 // to be numbered from llvm::Triple::Pixel to llvm::Triple::Amplification
2253 // (verified by static_asserts in Triple.cpp), we can use it to index
2254 // individual bits in the set, as long as we shift the values to start with 0
2255 // by subtracting the value of llvm::Triple::Pixel first.
2256 //
2257 // The N'th bit in the set will be set if the function has been scanned
2258 // in shader environment whose llvm::Triple::EnvironmentType integer value
2259 // equals (llvm::Triple::Pixel + N).
2260 //
2261 // For example, if a function has been scanned in compute and pixel stage
2262 // environment, the value will be 0x21 (100001 binary) because:
2263 //
2264 // (int)(llvm::Triple::Pixel - llvm::Triple::Pixel) == 0
2265 // (int)(llvm::Triple::Compute - llvm::Triple::Pixel) == 5
2266 //
2267 // A FunctionDecl is mapped to 0 (or not included in the map) if it has not
2268 // been scanned in any environment.
2269 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2270
2271 // Do not access these directly, use the get/set methods below to make
2272 // sure the values are in sync
2273 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2274 unsigned CurrentShaderStageBit;
2275
2276 // True if scanning a function that was already scanned in a different
2277 // shader stage context, and therefore we should not report issues that
2278 // depend only on shader model version because they would be duplicate.
2279 bool ReportOnlyShaderStageIssues;
2280
2281 // Helper methods for dealing with current stage context / environment
2282 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2283 static_assert(sizeof(unsigned) >= 4);
2284 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2285 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2286 "ShaderType is too big for this bitmap"); // 31 is reserved for
2287 // "unknown"
2288
2289 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2290 CurrentShaderEnvironment = ShaderType;
2291 CurrentShaderStageBit = (1 << bitmapIndex);
2292 }
2293
2294 void SetUnknownShaderStageContext() {
2295 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2296 CurrentShaderStageBit = (1 << 31);
2297 }
2298
2299 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
2300 return CurrentShaderEnvironment;
2301 }
2302
2303 bool InUnknownShaderStageContext() const {
2304 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2305 }
2306
2307 // Helper methods for dealing with shader stage bitmap
2308 void AddToScannedFunctions(const FunctionDecl *FD) {
2309 unsigned &ScannedStages = ScannedDecls[FD];
2310 ScannedStages |= CurrentShaderStageBit;
2311 }
2312
2313 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }
2314
2315 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
2316 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2317 }
2318
2319 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
2320 return ScannerStages & CurrentShaderStageBit;
2321 }
2322
2323 static bool NeverBeenScanned(unsigned ScannedStages) {
2324 return ScannedStages == 0;
2325 }
2326
2327 // Scanning methods
2328 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2329 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
2330 SourceRange Range);
2331 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
2332 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
2333
2334public:
2335 DiagnoseHLSLAvailability(Sema &SemaRef)
2336 : SemaRef(SemaRef),
2337 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2338 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
2339
2340 // AST traversal methods
2341 void RunOnTranslationUnit(const TranslationUnitDecl *TU);
2342 void RunOnFunction(const FunctionDecl *FD);
2343
2344 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
2345 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());
2346 if (FD)
2347 HandleFunctionOrMethodRef(FD, DRE);
2348 return true;
2349 }
2350
2351 bool VisitMemberExpr(MemberExpr *ME) override {
2352 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());
2353 if (FD)
2354 HandleFunctionOrMethodRef(FD, ME);
2355 return true;
2356 }
2357};
2358
2359void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
2360 Expr *RefExpr) {
2361 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
2362 "expected DeclRefExpr or MemberExpr");
2363
2364 // has a definition -> add to stack to be scanned
2365 const FunctionDecl *FDWithBody = nullptr;
2366 if (FD->hasBody(FDWithBody)) {
2367 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2368 DeclsToScan.push_back(FDWithBody);
2369 return;
2370 }
2371
2372 // no body -> diagnose availability
2373 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2374 if (AA)
2375 CheckDeclAvailability(
2376 FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));
2377}
2378
2379void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2380 const TranslationUnitDecl *TU) {
2381
2382 // Iterate over all shader entry functions and library exports, and for those
2383 // that have a body (definiton), run diag scan on each, setting appropriate
2384 // shader environment context based on whether it is a shader entry function
2385 // or an exported function. Exported functions can be in namespaces and in
2386 // export declarations so we need to scan those declaration contexts as well.
2388 DeclContextsToScan.push_back(TU);
2389
2390 while (!DeclContextsToScan.empty()) {
2391 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2392 for (auto &D : DC->decls()) {
2393 // do not scan implicit declaration generated by the implementation
2394 if (D->isImplicit())
2395 continue;
2396
2397 // for namespace or export declaration add the context to the list to be
2398 // scanned later
2399 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2400 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2401 continue;
2402 }
2403
2404 // skip over other decls or function decls without body
2405 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2406 if (!FD || !FD->isThisDeclarationADefinition())
2407 continue;
2408
2409 // shader entry point
2410 if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) {
2411 SetShaderStageContext(ShaderAttr->getType());
2412 RunOnFunction(FD);
2413 continue;
2414 }
2415 // exported library function
2416 // FIXME: replace this loop with external linkage check once issue #92071
2417 // is resolved
2418 bool isExport = FD->isInExportDeclContext();
2419 if (!isExport) {
2420 for (const auto *Redecl : FD->redecls()) {
2421 if (Redecl->isInExportDeclContext()) {
2422 isExport = true;
2423 break;
2424 }
2425 }
2426 }
2427 if (isExport) {
2428 SetUnknownShaderStageContext();
2429 RunOnFunction(FD);
2430 continue;
2431 }
2432 }
2433 }
2434}
2435
2436void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
2437 assert(DeclsToScan.empty() && "DeclsToScan should be empty");
2438 DeclsToScan.push_back(FD);
2439
2440 while (!DeclsToScan.empty()) {
2441 // Take one decl from the stack and check it by traversing its AST.
2442 // For any CallExpr found during the traversal add it's callee to the top of
2443 // the stack to be processed next. Functions already processed are stored in
2444 // ScannedDecls.
2445 const FunctionDecl *FD = DeclsToScan.pop_back_val();
2446
2447 // Decl was already scanned
2448 const unsigned ScannedStages = GetScannedStages(FD);
2449 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2450 continue;
2451
2452 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2453
2454 AddToScannedFunctions(FD);
2455 TraverseStmt(FD->getBody());
2456 }
2457}
2458
2459bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2460 const AvailabilityAttr *AA) {
2461 IdentifierInfo *IIEnvironment = AA->getEnvironment();
2462 if (!IIEnvironment)
2463 return true;
2464
2465 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2466 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2467 return false;
2468
2469 llvm::Triple::EnvironmentType AttrEnv =
2470 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
2471
2472 return CurrentEnv == AttrEnv;
2473}
2474
2475const AvailabilityAttr *
2476DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
2477 AvailabilityAttr const *PartialMatch = nullptr;
2478 // Check each AvailabilityAttr to find the one for this platform.
2479 // For multiple attributes with the same platform try to find one for this
2480 // environment.
2481 for (const auto *A : D->attrs()) {
2482 if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2483 StringRef AttrPlatform = Avail->getPlatform()->getName();
2484 StringRef TargetPlatform =
2486
2487 // Match the platform name.
2488 if (AttrPlatform == TargetPlatform) {
2489 // Find the best matching attribute for this environment
2490 if (HasMatchingEnvironmentOrNone(Avail))
2491 return Avail;
2492 PartialMatch = Avail;
2493 }
2494 }
2495 }
2496 return PartialMatch;
2497}
2498
2499// Check availability against target shader model version and current shader
2500// stage and emit diagnostic
2501void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
2502 const AvailabilityAttr *AA,
2503 SourceRange Range) {
2504
2505 IdentifierInfo *IIEnv = AA->getEnvironment();
2506
2507 if (!IIEnv) {
2508 // The availability attribute does not have environment -> it depends only
2509 // on shader model version and not on specific the shader stage.
2510
2511 // Skip emitting the diagnostics if the diagnostic mode is set to
2512 // strict (-fhlsl-strict-availability) because all relevant diagnostics
2513 // were already emitted in the DiagnoseUnguardedAvailability scan
2514 // (SemaAvailability.cpp).
2515 if (SemaRef.getLangOpts().HLSLStrictAvailability)
2516 return;
2517
2518 // Do not report shader-stage-independent issues if scanning a function
2519 // that was already scanned in a different shader stage context (they would
2520 // be duplicate)
2521 if (ReportOnlyShaderStageIssues)
2522 return;
2523
2524 } else {
2525 // The availability attribute has environment -> we need to know
2526 // the current stage context to property diagnose it.
2527 if (InUnknownShaderStageContext())
2528 return;
2529 }
2530
2531 // Check introduced version and if environment matches
2532 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2533 VersionTuple Introduced = AA->getIntroduced();
2534 VersionTuple TargetVersion =
2536
2537 if (TargetVersion >= Introduced && EnvironmentMatches)
2538 return;
2539
2540 // Emit diagnostic message
2541 const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
2542 llvm::StringRef PlatformName(
2543 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
2544
2545 llvm::StringRef CurrentEnvStr =
2546 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2547
2548 llvm::StringRef AttrEnvStr =
2549 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";
2550 bool UseEnvironment = !AttrEnvStr.empty();
2551
2552 if (EnvironmentMatches) {
2553 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)
2554 << Range << D << PlatformName << Introduced.getAsString()
2555 << UseEnvironment << CurrentEnvStr;
2556 } else {
2557 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2558 << Range << D;
2559 }
2560
2561 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
2562 << D << PlatformName << Introduced.getAsString()
2563 << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
2564 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2565}
2566
2567} // namespace
2568
2570 // process default CBuffer - create buffer layout struct and invoke codegenCGH
2571 if (!DefaultCBufferDecls.empty()) {
2573 SemaRef.getASTContext(), SemaRef.getCurLexicalContext(),
2574 DefaultCBufferDecls);
2575 addImplicitBindingAttrToDecl(SemaRef, DefaultCBuffer, RegisterType::CBuffer,
2576 getNextImplicitBindingOrderID());
2577 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2579
2580 // Set HasValidPackoffset if any of the decls has a register(c#) annotation;
2581 for (const Decl *VD : DefaultCBufferDecls) {
2582 const HLSLResourceBindingAttr *RBA =
2583 VD->getAttr<HLSLResourceBindingAttr>();
2584 if (RBA && RBA->hasRegisterSlot() &&
2585 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2586 DefaultCBuffer->setHasValidPackoffset(true);
2587 break;
2588 }
2589 }
2590
2591 DeclGroupRef DG(DefaultCBuffer);
2592 SemaRef.Consumer.HandleTopLevelDecl(DG);
2593 }
2594 diagnoseAvailabilityViolations(TU);
2595}
2596
2597void SemaHLSL::diagnoseAvailabilityViolations(TranslationUnitDecl *TU) {
2598 // Skip running the diagnostics scan if the diagnostic mode is
2599 // strict (-fhlsl-strict-availability) and the target shader stage is known
2600 // because all relevant diagnostics were already emitted in the
2601 // DiagnoseUnguardedAvailability scan (SemaAvailability.cpp).
2603 if (SemaRef.getLangOpts().HLSLStrictAvailability &&
2604 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2605 return;
2606
2607 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
2608}
2609
2610static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {
2611 assert(TheCall->getNumArgs() > 1);
2612 QualType ArgTy0 = TheCall->getArg(0)->getType();
2613
2614 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {
2616 ArgTy0, TheCall->getArg(I)->getType())) {
2617 S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2618 << TheCall->getDirectCallee() << /*useAllTerminology*/ true
2619 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
2620 TheCall->getArg(N - 1)->getEndLoc());
2621 return true;
2622 }
2623 }
2624 return false;
2625}
2626
2628 QualType ArgType = Arg->getType();
2630 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
2631 << ArgType << ExpectedType << 1 << 0 << 0;
2632 return true;
2633 }
2634 return false;
2635}
2636
2638 Sema *S, CallExpr *TheCall,
2639 llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,
2640 clang::QualType PassedType)>
2641 Check) {
2642 for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {
2643 Expr *Arg = TheCall->getArg(I);
2644 if (Check(S, Arg->getBeginLoc(), I + 1, Arg->getType()))
2645 return true;
2646 }
2647 return false;
2648}
2649
2651 int ArgOrdinal,
2652 clang::QualType PassedType) {
2653 clang::QualType BaseType =
2654 PassedType->isVectorType()
2655 ? PassedType->castAs<clang::VectorType>()->getElementType()
2656 : PassedType;
2657 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2658 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2659 << ArgOrdinal << /* scalar or vector of */ 5 << /* no int */ 0
2660 << /* half or float */ 2 << PassedType;
2661 return false;
2662}
2663
2664static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall,
2665 unsigned ArgIndex) {
2666 auto *Arg = TheCall->getArg(ArgIndex);
2667 SourceLocation OrigLoc = Arg->getExprLoc();
2668 if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==
2670 return false;
2671 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2672 return true;
2673}
2674
2675static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal,
2676 clang::QualType PassedType) {
2677 const auto *VecTy = PassedType->getAs<VectorType>();
2678 if (!VecTy)
2679 return false;
2680
2681 if (VecTy->getElementType()->isDoubleType())
2682 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2683 << ArgOrdinal << /* scalar */ 1 << /* no int */ 0 << /* fp */ 1
2684 << PassedType;
2685 return false;
2686}
2687
2689 int ArgOrdinal,
2690 clang::QualType PassedType) {
2691 if (!PassedType->hasIntegerRepresentation() &&
2692 !PassedType->hasFloatingRepresentation())
2693 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2694 << ArgOrdinal << /* scalar or vector of */ 5 << /* integer */ 1
2695 << /* fp */ 1 << PassedType;
2696 return false;
2697}
2698
2700 int ArgOrdinal,
2701 clang::QualType PassedType) {
2702 if (auto *VecTy = PassedType->getAs<VectorType>())
2703 if (VecTy->getElementType()->isUnsignedIntegerType())
2704 return false;
2705
2706 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2707 << ArgOrdinal << /* vector of */ 4 << /* uint */ 3 << /* no fp */ 0
2708 << PassedType;
2709}
2710
2711// checks for unsigned ints of all sizes
2713 int ArgOrdinal,
2714 clang::QualType PassedType) {
2715 if (!PassedType->hasUnsignedIntegerRepresentation())
2716 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2717 << ArgOrdinal << /* scalar or vector of */ 5 << /* unsigned int */ 3
2718 << /* no fp */ 0 << PassedType;
2719 return false;
2720}
2721
2723 QualType ReturnType) {
2724 auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
2725 if (VecTyA)
2726 ReturnType =
2727 S->Context.getExtVectorType(ReturnType, VecTyA->getNumElements());
2728
2729 TheCall->setType(ReturnType);
2730}
2731
2732static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar,
2733 unsigned ArgIndex) {
2734 assert(TheCall->getNumArgs() >= ArgIndex);
2735 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2736 auto *VTy = ArgType->getAs<VectorType>();
2737 // not the scalar or vector<scalar>
2738 if (!(S->Context.hasSameUnqualifiedType(ArgType, Scalar) ||
2739 (VTy &&
2740 S->Context.hasSameUnqualifiedType(VTy->getElementType(), Scalar)))) {
2741 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2742 diag::err_typecheck_expect_scalar_or_vector)
2743 << ArgType << Scalar;
2744 return true;
2745 }
2746 return false;
2747}
2748
2749static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall,
2750 unsigned ArgIndex) {
2751 assert(TheCall->getNumArgs() >= ArgIndex);
2752 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2753 auto *VTy = ArgType->getAs<VectorType>();
2754 // not the scalar or vector<scalar>
2755 if (!(ArgType->isScalarType() ||
2756 (VTy && VTy->getElementType()->isScalarType()))) {
2757 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2758 diag::err_typecheck_expect_any_scalar_or_vector)
2759 << ArgType << 1;
2760 return true;
2761 }
2762 return false;
2763}
2764
2765static bool CheckWaveActive(Sema *S, CallExpr *TheCall) {
2766 QualType BoolType = S->getASTContext().BoolTy;
2767 assert(TheCall->getNumArgs() >= 1);
2768 QualType ArgType = TheCall->getArg(0)->getType();
2769 auto *VTy = ArgType->getAs<VectorType>();
2770 // is the bool or vector<bool>
2771 if (S->Context.hasSameUnqualifiedType(ArgType, BoolType) ||
2772 (VTy &&
2773 S->Context.hasSameUnqualifiedType(VTy->getElementType(), BoolType))) {
2774 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2775 diag::err_typecheck_expect_any_scalar_or_vector)
2776 << ArgType << 0;
2777 return true;
2778 }
2779 return false;
2780}
2781
2782static bool CheckBoolSelect(Sema *S, CallExpr *TheCall) {
2783 assert(TheCall->getNumArgs() == 3);
2784 Expr *Arg1 = TheCall->getArg(1);
2785 Expr *Arg2 = TheCall->getArg(2);
2786 if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), Arg2->getType())) {
2787 S->Diag(TheCall->getBeginLoc(),
2788 diag::err_typecheck_call_different_arg_types)
2789 << Arg1->getType() << Arg2->getType() << Arg1->getSourceRange()
2790 << Arg2->getSourceRange();
2791 return true;
2792 }
2793
2794 TheCall->setType(Arg1->getType());
2795 return false;
2796}
2797
2798static bool CheckVectorSelect(Sema *S, CallExpr *TheCall) {
2799 assert(TheCall->getNumArgs() == 3);
2800 Expr *Arg1 = TheCall->getArg(1);
2801 QualType Arg1Ty = Arg1->getType();
2802 Expr *Arg2 = TheCall->getArg(2);
2803 QualType Arg2Ty = Arg2->getType();
2804
2805 QualType Arg1ScalarTy = Arg1Ty;
2806 if (auto VTy = Arg1ScalarTy->getAs<VectorType>())
2807 Arg1ScalarTy = VTy->getElementType();
2808
2809 QualType Arg2ScalarTy = Arg2Ty;
2810 if (auto VTy = Arg2ScalarTy->getAs<VectorType>())
2811 Arg2ScalarTy = VTy->getElementType();
2812
2813 if (!S->Context.hasSameUnqualifiedType(Arg1ScalarTy, Arg2ScalarTy))
2814 S->Diag(Arg1->getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2815 << /* second and third */ 1 << TheCall->getCallee() << Arg1Ty << Arg2Ty;
2816
2817 QualType Arg0Ty = TheCall->getArg(0)->getType();
2818 unsigned Arg0Length = Arg0Ty->getAs<VectorType>()->getNumElements();
2819 unsigned Arg1Length = Arg1Ty->isVectorType()
2820 ? Arg1Ty->getAs<VectorType>()->getNumElements()
2821 : 0;
2822 unsigned Arg2Length = Arg2Ty->isVectorType()
2823 ? Arg2Ty->getAs<VectorType>()->getNumElements()
2824 : 0;
2825 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2826 S->Diag(TheCall->getBeginLoc(),
2827 diag::err_typecheck_vector_lengths_not_equal)
2828 << Arg0Ty << Arg1Ty << TheCall->getArg(0)->getSourceRange()
2829 << Arg1->getSourceRange();
2830 return true;
2831 }
2832
2833 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2834 S->Diag(TheCall->getBeginLoc(),
2835 diag::err_typecheck_vector_lengths_not_equal)
2836 << Arg0Ty << Arg2Ty << TheCall->getArg(0)->getSourceRange()
2837 << Arg2->getSourceRange();
2838 return true;
2839 }
2840
2841 TheCall->setType(
2842 S->getASTContext().getExtVectorType(Arg1ScalarTy, Arg0Length));
2843 return false;
2844}
2845
2847 Sema *S, CallExpr *TheCall, unsigned ArgIndex,
2848 llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =
2849 nullptr) {
2850 assert(TheCall->getNumArgs() >= ArgIndex);
2851 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2852 const HLSLAttributedResourceType *ResTy =
2853 ArgType.getTypePtr()->getAs<HLSLAttributedResourceType>();
2854 if (!ResTy) {
2855 S->Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),
2856 diag::err_typecheck_expect_hlsl_resource)
2857 << ArgType;
2858 return true;
2859 }
2860 if (Check && Check(ResTy)) {
2861 S->Diag(TheCall->getArg(ArgIndex)->getExprLoc(),
2862 diag::err_invalid_hlsl_resource_type)
2863 << ArgType;
2864 return true;
2865 }
2866 return false;
2867}
2868
2869// Note: returning true in this case results in CheckBuiltinFunctionCall
2870// returning an ExprError
2871bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
2872 switch (BuiltinID) {
2873 case Builtin::BI__builtin_hlsl_adduint64: {
2874 if (SemaRef.checkArgCount(TheCall, 2))
2875 return true;
2876
2877 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
2879 return true;
2880
2881 auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
2882 // ensure arg integers are 32-bits
2883 uint64_t ElementBitCount = getASTContext()
2884 .getTypeSizeInChars(VTy->getElementType())
2885 .getQuantity() *
2886 8;
2887 if (ElementBitCount != 32) {
2888 SemaRef.Diag(TheCall->getBeginLoc(),
2889 diag::err_integer_incorrect_bit_count)
2890 << 32 << ElementBitCount;
2891 return true;
2892 }
2893
2894 // ensure both args are vectors of total bit size of a multiple of 64
2895 int NumElementsArg = VTy->getNumElements();
2896 if (NumElementsArg != 2 && NumElementsArg != 4) {
2897 SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count)
2898 << 1 /*a multiple of*/ << 64 << NumElementsArg * ElementBitCount;
2899 return true;
2900 }
2901
2902 // ensure first arg and second arg have the same type
2903 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2904 return true;
2905
2906 ExprResult A = TheCall->getArg(0);
2907 QualType ArgTyA = A.get()->getType();
2908 // return type is the same as the input type
2909 TheCall->setType(ArgTyA);
2910 break;
2911 }
2912 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2913 if (SemaRef.checkArgCount(TheCall, 2) ||
2914 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2915 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
2916 SemaRef.getASTContext().UnsignedIntTy))
2917 return true;
2918
2919 auto *ResourceTy =
2920 TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
2921 QualType ContainedTy = ResourceTy->getContainedType();
2922 auto ReturnType =
2923 SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
2924 ReturnType = SemaRef.Context.getPointerType(ReturnType);
2925 TheCall->setType(ReturnType);
2926 TheCall->setValueKind(VK_LValue);
2927
2928 break;
2929 }
2930 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2931 if (SemaRef.checkArgCount(TheCall, 1) ||
2932 CheckResourceHandle(&SemaRef, TheCall, 0))
2933 return true;
2934 // use the type of the handle (arg0) as a return type
2935 QualType ResourceTy = TheCall->getArg(0)->getType();
2936 TheCall->setType(ResourceTy);
2937 break;
2938 }
2939 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2940 ASTContext &AST = SemaRef.getASTContext();
2941 if (SemaRef.checkArgCount(TheCall, 6) ||
2942 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2943 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
2944 CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
2945 CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
2946 CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
2947 CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
2948 AST.getPointerType(AST.CharTy.withConst())))
2949 return true;
2950 // use the type of the handle (arg0) as a return type
2951 QualType ResourceTy = TheCall->getArg(0)->getType();
2952 TheCall->setType(ResourceTy);
2953 break;
2954 }
2955 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2956 ASTContext &AST = SemaRef.getASTContext();
2957 if (SemaRef.checkArgCount(TheCall, 6) ||
2958 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2959 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
2960 CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
2961 CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
2962 CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
2963 CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
2964 AST.getPointerType(AST.CharTy.withConst())))
2965 return true;
2966 // use the type of the handle (arg0) as a return type
2967 QualType ResourceTy = TheCall->getArg(0)->getType();
2968 TheCall->setType(ResourceTy);
2969 break;
2970 }
2971 case Builtin::BI__builtin_hlsl_and:
2972 case Builtin::BI__builtin_hlsl_or: {
2973 if (SemaRef.checkArgCount(TheCall, 2))
2974 return true;
2975 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
2976 return true;
2977 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2978 return true;
2979
2980 ExprResult A = TheCall->getArg(0);
2981 QualType ArgTyA = A.get()->getType();
2982 // return type is the same as the input type
2983 TheCall->setType(ArgTyA);
2984 break;
2985 }
2986 case Builtin::BI__builtin_hlsl_all:
2987 case Builtin::BI__builtin_hlsl_any: {
2988 if (SemaRef.checkArgCount(TheCall, 1))
2989 return true;
2990 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
2991 return true;
2992 break;
2993 }
2994 case Builtin::BI__builtin_hlsl_asdouble: {
2995 if (SemaRef.checkArgCount(TheCall, 2))
2996 return true;
2998 &SemaRef, TheCall,
2999 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
3000 /* arg index */ 0))
3001 return true;
3003 &SemaRef, TheCall,
3004 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
3005 /* arg index */ 1))
3006 return true;
3007 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3008 return true;
3009
3010 SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().DoubleTy);
3011 break;
3012 }
3013 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3014 if (SemaRef.BuiltinElementwiseTernaryMath(
3015 TheCall, /*ArgTyRestr=*/
3017 return true;
3018 break;
3019 }
3020 case Builtin::BI__builtin_hlsl_dot: {
3021 // arg count is checked by BuiltinVectorToScalarMath
3022 if (SemaRef.BuiltinVectorToScalarMath(TheCall))
3023 return true;
3025 return true;
3026 break;
3027 }
3028 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3029 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3030 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3031 return true;
3032
3033 const Expr *Arg = TheCall->getArg(0);
3034 QualType ArgTy = Arg->getType();
3035 QualType EltTy = ArgTy;
3036
3037 QualType ResTy = SemaRef.Context.UnsignedIntTy;
3038
3039 if (auto *VecTy = EltTy->getAs<VectorType>()) {
3040 EltTy = VecTy->getElementType();
3041 ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3042 }
3043
3044 if (!EltTy->isIntegerType()) {
3045 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
3046 << 1 << /* scalar or vector of */ 5 << /* integer ty */ 1
3047 << /* no fp */ 0 << ArgTy;
3048 return true;
3049 }
3050
3051 TheCall->setType(ResTy);
3052 break;
3053 }
3054 case Builtin::BI__builtin_hlsl_select: {
3055 if (SemaRef.checkArgCount(TheCall, 3))
3056 return true;
3057 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
3058 return true;
3059 QualType ArgTy = TheCall->getArg(0)->getType();
3060 if (ArgTy->isBooleanType() && CheckBoolSelect(&SemaRef, TheCall))
3061 return true;
3062 auto *VTy = ArgTy->getAs<VectorType>();
3063 if (VTy && VTy->getElementType()->isBooleanType() &&
3064 CheckVectorSelect(&SemaRef, TheCall))
3065 return true;
3066 break;
3067 }
3068 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3069 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3070 if (SemaRef.checkArgCount(TheCall, 1))
3071 return true;
3072 if (!TheCall->getArg(0)
3073 ->getType()
3074 ->hasFloatingRepresentation()) // half or float or double
3075 return SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
3076 diag::err_builtin_invalid_arg_type)
3077 << /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0
3078 << /* fp */ 1 << TheCall->getArg(0)->getType();
3079 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3080 return true;
3081 break;
3082 }
3083 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3084 case Builtin::BI__builtin_hlsl_elementwise_radians:
3085 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3086 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3087 if (SemaRef.checkArgCount(TheCall, 1))
3088 return true;
3089 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3091 return true;
3092 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3093 return true;
3094 break;
3095 }
3096 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
3097 if (SemaRef.checkArgCount(TheCall, 1))
3098 return true;
3099 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3101 return true;
3102 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3103 return true;
3105 break;
3106 }
3107 case Builtin::BI__builtin_hlsl_lerp: {
3108 if (SemaRef.checkArgCount(TheCall, 3))
3109 return true;
3110 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3112 return true;
3113 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3114 return true;
3115 if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3116 return true;
3117 break;
3118 }
3119 case Builtin::BI__builtin_hlsl_mad: {
3120 if (SemaRef.BuiltinElementwiseTernaryMath(
3121 TheCall, /*ArgTyRestr=*/
3123 return true;
3124 break;
3125 }
3126 case Builtin::BI__builtin_hlsl_normalize: {
3127 if (SemaRef.checkArgCount(TheCall, 1))
3128 return true;
3129 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3131 return true;
3132 ExprResult A = TheCall->getArg(0);
3133 QualType ArgTyA = A.get()->getType();
3134 // return type is the same as the input type
3135 TheCall->setType(ArgTyA);
3136 break;
3137 }
3138 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3139 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3140 return true;
3141 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3143 return true;
3145 break;
3146 }
3147 case Builtin::BI__builtin_hlsl_step: {
3148 if (SemaRef.checkArgCount(TheCall, 2))
3149 return true;
3150 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3152 return true;
3153
3154 ExprResult A = TheCall->getArg(0);
3155 QualType ArgTyA = A.get()->getType();
3156 // return type is the same as the input type
3157 TheCall->setType(ArgTyA);
3158 break;
3159 }
3160 case Builtin::BI__builtin_hlsl_wave_active_max:
3161 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3162 if (SemaRef.checkArgCount(TheCall, 1))
3163 return true;
3164
3165 // Ensure input expr type is a scalar/vector and the same as the return type
3166 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3167 return true;
3168 if (CheckWaveActive(&SemaRef, TheCall))
3169 return true;
3170 ExprResult Expr = TheCall->getArg(0);
3171 QualType ArgTyExpr = Expr.get()->getType();
3172 TheCall->setType(ArgTyExpr);
3173 break;
3174 }
3175 // Note these are llvm builtins that we want to catch invalid intrinsic
3176 // generation. Normal handling of these builitns will occur elsewhere.
3177 case Builtin::BI__builtin_elementwise_bitreverse: {
3178 // does not include a check for number of arguments
3179 // because that is done previously
3180 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3182 return true;
3183 break;
3184 }
3185 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3186 if (SemaRef.checkArgCount(TheCall, 2))
3187 return true;
3188
3189 // Ensure index parameter type can be interpreted as a uint
3190 ExprResult Index = TheCall->getArg(1);
3191 QualType ArgTyIndex = Index.get()->getType();
3192 if (!ArgTyIndex->isIntegerType()) {
3193 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3194 diag::err_typecheck_convert_incompatible)
3195 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3196 return true;
3197 }
3198
3199 // Ensure input expr type is a scalar/vector and the same as the return type
3200 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3201 return true;
3202
3203 ExprResult Expr = TheCall->getArg(0);
3204 QualType ArgTyExpr = Expr.get()->getType();
3205 TheCall->setType(ArgTyExpr);
3206 break;
3207 }
3208 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3209 if (SemaRef.checkArgCount(TheCall, 0))
3210 return true;
3211 break;
3212 }
3213 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3214 if (SemaRef.checkArgCount(TheCall, 3))
3215 return true;
3216
3217 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.DoubleTy, 0) ||
3218 CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,
3219 1) ||
3220 CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,
3221 2))
3222 return true;
3223
3224 if (CheckModifiableLValue(&SemaRef, TheCall, 1) ||
3225 CheckModifiableLValue(&SemaRef, TheCall, 2))
3226 return true;
3227 break;
3228 }
3229 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3230 if (SemaRef.checkArgCount(TheCall, 1))
3231 return true;
3232
3233 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0))
3234 return true;
3235 break;
3236 }
3237 case Builtin::BI__builtin_elementwise_acos:
3238 case Builtin::BI__builtin_elementwise_asin:
3239 case Builtin::BI__builtin_elementwise_atan:
3240 case Builtin::BI__builtin_elementwise_atan2:
3241 case Builtin::BI__builtin_elementwise_ceil:
3242 case Builtin::BI__builtin_elementwise_cos:
3243 case Builtin::BI__builtin_elementwise_cosh:
3244 case Builtin::BI__builtin_elementwise_exp:
3245 case Builtin::BI__builtin_elementwise_exp2:
3246 case Builtin::BI__builtin_elementwise_exp10:
3247 case Builtin::BI__builtin_elementwise_floor:
3248 case Builtin::BI__builtin_elementwise_fmod:
3249 case Builtin::BI__builtin_elementwise_log:
3250 case Builtin::BI__builtin_elementwise_log2:
3251 case Builtin::BI__builtin_elementwise_log10:
3252 case Builtin::BI__builtin_elementwise_pow:
3253 case Builtin::BI__builtin_elementwise_roundeven:
3254 case Builtin::BI__builtin_elementwise_sin:
3255 case Builtin::BI__builtin_elementwise_sinh:
3256 case Builtin::BI__builtin_elementwise_sqrt:
3257 case Builtin::BI__builtin_elementwise_tan:
3258 case Builtin::BI__builtin_elementwise_tanh:
3259 case Builtin::BI__builtin_elementwise_trunc: {
3260 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3262 return true;
3263 break;
3264 }
3265 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3266 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
3267 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3268 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3269 };
3270 if (SemaRef.checkArgCount(TheCall, 2) ||
3271 CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy) ||
3272 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
3273 SemaRef.getASTContext().IntTy))
3274 return true;
3275 Expr *OffsetExpr = TheCall->getArg(1);
3276 std::optional<llvm::APSInt> Offset =
3277 OffsetExpr->getIntegerConstantExpr(SemaRef.getASTContext());
3278 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
3279 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3280 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3281 << 1;
3282 return true;
3283 }
3284 break;
3285 }
3286 }
3287 return false;
3288}
3289
3293 WorkList.push_back(BaseTy);
3294 while (!WorkList.empty()) {
3295 QualType T = WorkList.pop_back_val();
3296 T = T.getCanonicalType().getUnqualifiedType();
3297 assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
3298 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3299 llvm::SmallVector<QualType, 16> ElementFields;
3300 // Generally I've avoided recursion in this algorithm, but arrays of
3301 // structs could be time-consuming to flatten and churn through on the
3302 // work list. Hopefully nesting arrays of structs containing arrays
3303 // of structs too many levels deep is unlikely.
3304 BuildFlattenedTypeList(AT->getElementType(), ElementFields);
3305 // Repeat the element's field list n times.
3306 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3307 llvm::append_range(List, ElementFields);
3308 continue;
3309 }
3310 // Vectors can only have element types that are builtin types, so this can
3311 // add directly to the list instead of to the WorkList.
3312 if (const auto *VT = dyn_cast<VectorType>(T)) {
3313 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3314 continue;
3315 }
3316 if (const auto *RD = T->getAsCXXRecordDecl()) {
3317 if (RD->isStandardLayout())
3318 RD = RD->getStandardLayoutBaseWithFields();
3319
3320 // For types that we shouldn't decompose (unions and non-aggregates), just
3321 // add the type itself to the list.
3322 if (RD->isUnion() || !RD->isAggregate()) {
3323 List.push_back(T);
3324 continue;
3325 }
3326
3328 for (const auto *FD : RD->fields())
3329 FieldTypes.push_back(FD->getType());
3330 // Reverse the newly added sub-range.
3331 std::reverse(FieldTypes.begin(), FieldTypes.end());
3332 llvm::append_range(WorkList, FieldTypes);
3333
3334 // If this wasn't a standard layout type we may also have some base
3335 // classes to deal with.
3336 if (!RD->isStandardLayout()) {
3337 FieldTypes.clear();
3338 for (const auto &Base : RD->bases())
3339 FieldTypes.push_back(Base.getType());
3340 std::reverse(FieldTypes.begin(), FieldTypes.end());
3341 llvm::append_range(WorkList, FieldTypes);
3342 }
3343 continue;
3344 }
3345 List.push_back(T);
3346 }
3347}
3348
3350 // null and array types are not allowed.
3351 if (QT.isNull() || QT->isArrayType())
3352 return false;
3353
3354 // UDT types are not allowed
3355 if (QT->isRecordType())
3356 return false;
3357
3358 if (QT->isBooleanType() || QT->isEnumeralType())
3359 return false;
3360
3361 // the only other valid builtin types are scalars or vectors
3362 if (QT->isArithmeticType()) {
3363 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3364 return false;
3365 return true;
3366 }
3367
3368 if (const VectorType *VT = QT->getAs<VectorType>()) {
3369 int ArraySize = VT->getNumElements();
3370
3371 if (ArraySize > 4)
3372 return false;
3373
3374 QualType ElTy = VT->getElementType();
3375 if (ElTy->isBooleanType())
3376 return false;
3377
3378 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3379 return false;
3380 return true;
3381 }
3382
3383 return false;
3384}
3385
3387 if (T1.isNull() || T2.isNull())
3388 return false;
3389
3392
3393 // If both types are the same canonical type, they're obviously compatible.
3394 if (SemaRef.getASTContext().hasSameType(T1, T2))
3395 return true;
3396
3398 BuildFlattenedTypeList(T1, T1Types);
3400 BuildFlattenedTypeList(T2, T2Types);
3401
3402 // Check the flattened type list
3403 return llvm::equal(T1Types, T2Types,
3404 [this](QualType LHS, QualType RHS) -> bool {
3405 return SemaRef.IsLayoutCompatible(LHS, RHS);
3406 });
3407}
3408
3410 FunctionDecl *Old) {
3411 if (New->getNumParams() != Old->getNumParams())
3412 return true;
3413
3414 bool HadError = false;
3415
3416 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
3417 ParmVarDecl *NewParam = New->getParamDecl(i);
3418 ParmVarDecl *OldParam = Old->getParamDecl(i);
3419
3420 // HLSL parameter declarations for inout and out must match between
3421 // declarations. In HLSL inout and out are ambiguous at the call site,
3422 // but have different calling behavior, so you cannot overload a
3423 // method based on a difference between inout and out annotations.
3424 const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>();
3425 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3426 const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>();
3427 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3428
3429 if (NSpellingIdx != OSpellingIdx) {
3430 SemaRef.Diag(NewParam->getLocation(),
3431 diag::err_hlsl_param_qualifier_mismatch)
3432 << NDAttr << NewParam;
3433 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
3434 << ODAttr;
3435 HadError = true;
3436 }
3437 }
3438 return HadError;
3439}
3440
3441// Generally follows PerformScalarCast, with cases reordered for
3442// clarity of what types are supported
3444
3445 if (!SrcTy->isScalarType() || !DestTy->isScalarType())
3446 return false;
3447
3448 if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3449 return true;
3450
3451 switch (SrcTy->getScalarTypeKind()) {
3452 case Type::STK_Bool: // casting from bool is like casting from an integer
3453 case Type::STK_Integral:
3454 switch (DestTy->getScalarTypeKind()) {
3455 case Type::STK_Bool:
3456 case Type::STK_Integral:
3457 case Type::STK_Floating:
3458 return true;
3459 case Type::STK_CPointer:
3463 llvm_unreachable("HLSL doesn't support pointers.");
3466 llvm_unreachable("HLSL doesn't support complex types.");
3468 llvm_unreachable("HLSL doesn't support fixed point types.");
3469 }
3470 llvm_unreachable("Should have returned before this");
3471
3472 case Type::STK_Floating:
3473 switch (DestTy->getScalarTypeKind()) {
3474 case Type::STK_Floating:
3475 case Type::STK_Bool:
3476 case Type::STK_Integral:
3477 return true;
3480 llvm_unreachable("HLSL doesn't support complex types.");
3482 llvm_unreachable("HLSL doesn't support fixed point types.");
3483 case Type::STK_CPointer:
3487 llvm_unreachable("HLSL doesn't support pointers.");
3488 }
3489 llvm_unreachable("Should have returned before this");
3490
3492 case Type::STK_CPointer:
3495 llvm_unreachable("HLSL doesn't support pointers.");
3496
3498 llvm_unreachable("HLSL doesn't support fixed point types.");
3499
3502 llvm_unreachable("HLSL doesn't support complex types.");
3503 }
3504
3505 llvm_unreachable("Unhandled scalar cast");
3506}
3507
3508// Detect if a type contains a bitfield. Will be removed when
3509// bitfield support is added to HLSLElementwiseCast and HLSLAggregateSplatCast
3512 WorkList.push_back(BaseTy);
3513 while (!WorkList.empty()) {
3514 QualType T = WorkList.pop_back_val();
3515 T = T.getCanonicalType().getUnqualifiedType();
3516 // only check aggregate types
3517 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3518 WorkList.push_back(AT->getElementType());
3519 continue;
3520 }
3521 if (const auto *RT = dyn_cast<RecordType>(T)) {
3522 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3523 if (RD->isUnion())
3524 continue;
3525
3526 const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(RD);
3527
3528 if (CXXD && CXXD->isStandardLayout())
3530
3531 for (const auto *FD : RD->fields()) {
3532 if (FD->isBitField())
3533 return true;
3534 WorkList.push_back(FD->getType());
3535 }
3536 continue;
3537 }
3538 }
3539 return false;
3540}
3541
3542// Can perform an HLSL Aggregate splat cast if the Dest is an aggregate and the
3543// Src is a scalar or a vector of length 1
3544// Or if Dest is a vector and Src is a vector of length 1
3546
3547 QualType SrcTy = Src->getType();
3548 // Not a valid HLSL Aggregate Splat cast if Dest is a scalar or if this is
3549 // going to be a vector splat from a scalar.
3550 if ((SrcTy->isScalarType() && DestTy->isVectorType()) ||
3551 DestTy->isScalarType())
3552 return false;
3553
3554 const VectorType *SrcVecTy = SrcTy->getAs<VectorType>();
3555
3556 // Src isn't a scalar or a vector of length 1
3557 if (!SrcTy->isScalarType() && !(SrcVecTy && SrcVecTy->getNumElements() == 1))
3558 return false;
3559
3560 if (SrcVecTy)
3561 SrcTy = SrcVecTy->getElementType();
3562
3563 if (ContainsBitField(DestTy))
3564 return false;
3565
3567 BuildFlattenedTypeList(DestTy, DestTypes);
3568
3569 for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3570 if (DestTypes[I]->isUnionType())
3571 return false;
3572 if (!CanPerformScalarCast(SrcTy, DestTypes[I]))
3573 return false;
3574 }
3575 return true;
3576}
3577
3578// Can we perform an HLSL Elementwise cast?
3579// TODO: update this code when matrices are added; see issue #88060
3581
3582 // Don't handle casts where LHS and RHS are any combination of scalar/vector
3583 // There must be an aggregate somewhere
3584 QualType SrcTy = Src->getType();
3585 if (SrcTy->isScalarType()) // always a splat and this cast doesn't handle that
3586 return false;
3587
3588 if (SrcTy->isVectorType() &&
3589 (DestTy->isScalarType() || DestTy->isVectorType()))
3590 return false;
3591
3592 if (ContainsBitField(DestTy) || ContainsBitField(SrcTy))
3593 return false;
3594
3596 BuildFlattenedTypeList(DestTy, DestTypes);
3598 BuildFlattenedTypeList(SrcTy, SrcTypes);
3599
3600 // Usually the size of SrcTypes must be greater than or equal to the size of
3601 // DestTypes.
3602 if (SrcTypes.size() < DestTypes.size())
3603 return false;
3604
3605 unsigned SrcSize = SrcTypes.size();
3606 unsigned DstSize = DestTypes.size();
3607 unsigned I;
3608 for (I = 0; I < DstSize && I < SrcSize; I++) {
3609 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3610 return false;
3611 if (!CanPerformScalarCast(SrcTypes[I], DestTypes[I])) {
3612 return false;
3613 }
3614 }
3615
3616 // check the rest of the source type for unions.
3617 for (; I < SrcSize; I++) {
3618 if (SrcTypes[I]->isUnionType())
3619 return false;
3620 }
3621 return true;
3622}
3623
3625 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3626 "We should not get here without a parameter modifier expression");
3627 const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();
3628 if (Attr->getABI() == ParameterABI::Ordinary)
3629 return ExprResult(Arg);
3630
3631 bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut;
3632 if (!Arg->isLValue()) {
3633 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue)
3634 << Arg << (IsInOut ? 1 : 0);
3635 return ExprError();
3636 }
3637
3638 ASTContext &Ctx = SemaRef.getASTContext();
3639
3640 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3641
3642 // HLSL allows implicit conversions from scalars to vectors, but not the
3643 // inverse, so we need to disallow `inout` with scalar->vector or
3644 // scalar->matrix conversions.
3645 if (Arg->getType()->isScalarType() != Ty->isScalarType()) {
3646 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)
3647 << Arg << (IsInOut ? 1 : 0);
3648 return ExprError();
3649 }
3650
3651 auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), Arg->getType(),
3652 VK_LValue, OK_Ordinary, Arg);
3653
3654 // Parameters are initialized via copy initialization. This allows for
3655 // overload resolution of argument constructors.
3656 InitializedEntity Entity =
3658 ExprResult Res =
3659 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3660 if (Res.isInvalid())
3661 return ExprError();
3662 Expr *Base = Res.get();
3663 // After the cast, drop the reference type when creating the exprs.
3664 Ty = Ty.getNonLValueExprType(Ctx);
3665 auto *OpV = new (Ctx)
3666 OpaqueValueExpr(Param->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);
3667
3668 // Writebacks are performed with `=` binary operator, which allows for
3669 // overload resolution on writeback result expressions.
3670 Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Param->getBeginLoc(),
3671 tok::equal, ArgOpV, OpV);
3672
3673 if (Res.isInvalid())
3674 return ExprError();
3675 Expr *Writeback = Res.get();
3676 auto *OutExpr =
3677 HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
3678
3679 return ExprResult(OutExpr);
3680}
3681
3683 // If HLSL gains support for references, all the cites that use this will need
3684 // to be updated with semantic checking to produce errors for
3685 // pointers/references.
3686 assert(!Ty->isReferenceType() &&
3687 "Pointer and reference types cannot be inout or out parameters");
3688 Ty = SemaRef.getASTContext().getLValueReferenceType(Ty);
3689 Ty.addRestrict();
3690 return Ty;
3691}
3692
3694 QualType QT = VD->getType();
3695 return VD->getDeclContext()->isTranslationUnit() &&
3697 VD->getStorageClass() != SC_Static &&
3698 !VD->hasAttr<HLSLVkConstantIdAttr>() &&
3700}
3701
3703 // The variable already has an address space (groupshared for ex).
3704 if (Decl->getType().hasAddressSpace())
3705 return;
3706
3707 if (Decl->getType()->isDependentType())
3708 return;
3709
3710 QualType Type = Decl->getType();
3711
3712 if (Decl->hasAttr<HLSLVkExtBuiltinInputAttr>()) {
3713 LangAS ImplAS = LangAS::hlsl_input;
3714 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3715 Decl->setType(Type);
3716 return;
3717 }
3718
3719 if (Type->isSamplerT() || Type->isVoidType())
3720 return;
3721
3722 // Resource handles.
3724 return;
3725
3726 // Only static globals belong to the Private address space.
3727 // Non-static globals belongs to the cbuffer.
3728 if (Decl->getStorageClass() != SC_Static && !Decl->isStaticDataMember())
3729 return;
3730
3732 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3733 Decl->setType(Type);
3734}
3735
3737 if (VD->hasGlobalStorage()) {
3738 // make sure the declaration has a complete type
3739 if (SemaRef.RequireCompleteType(
3740 VD->getLocation(),
3741 SemaRef.getASTContext().getBaseElementType(VD->getType()),
3742 diag::err_typecheck_decl_incomplete_type)) {
3743 VD->setInvalidDecl();
3745 return;
3746 }
3747
3748 // Global variables outside a cbuffer block that are not a resource, static,
3749 // groupshared, or an empty array or struct belong to the default constant
3750 // buffer $Globals (to be created at the end of the translation unit).
3752 // update address space to hlsl_constant
3755 VD->setType(NewTy);
3756 DefaultCBufferDecls.push_back(VD);
3757 }
3758
3759 // find all resources bindings on decl
3760 if (VD->getType()->isHLSLIntangibleType())
3761 collectResourceBindingsOnVarDecl(VD);
3762
3764 VD->hasAttr<HLSLVkConstantIdAttr>()) {
3765 // Make the variable for resources static. The global externally visible
3766 // storage is accessed through the handle, which is a member. The variable
3767 // itself is not externally visible.
3769 }
3770
3771 // process explicit bindings
3772 processExplicitBindingsOnDecl(VD);
3773
3774 if (VD->getType()->isHLSLResourceRecordArray()) {
3775 // If the resource array does not have an explicit binding attribute,
3776 // create an implicit one. It will be used to transfer implicit binding
3777 // order_ID to codegen.
3778 if (!VD->hasAttr<HLSLVkBindingAttr>()) {
3779 HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3780 if (!RBA || !RBA->hasRegisterSlot()) {
3781 uint32_t OrderID = getNextImplicitBindingOrderID();
3782 if (RBA)
3783 RBA->setImplicitBindingOrderID(OrderID);
3784 else
3787 OrderID);
3788 }
3789 }
3790 }
3791 }
3792
3794}
3795
3796bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
3797 assert(VD->getType()->isHLSLResourceRecord() &&
3798 "expected resource record type");
3799
3801 uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
3802 uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
3803
3804 // Gather resource binding information from attributes.
3805 HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3806 HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>();
3807 std::optional<uint32_t> RegisterSlot;
3808 uint32_t SpaceNo = 0;
3809 if (VkBinding) {
3810 RegisterSlot = VkBinding->getBinding();
3811 SpaceNo = VkBinding->getSet();
3812 } else if (RBA) {
3813 if (RBA->hasRegisterSlot())
3814 RegisterSlot = RBA->getSlotNumber();
3815 SpaceNo = RBA->getSpaceNumber();
3816 }
3817
3818 // Find correct initialization method and create its arguments.
3819 QualType ResourceTy = VD->getType();
3820 CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();
3821 CXXMethodDecl *CreateMethod = nullptr;
3822 llvm::SmallVector<Expr *> Args;
3823
3824 if (RegisterSlot.has_value()) {
3825 // The resource has explicit binding.
3826 CreateMethod = lookupMethod(SemaRef, ResourceDecl, "__createFromBinding",
3827 VD->getLocation());
3828 IntegerLiteral *RegSlot = IntegerLiteral::Create(
3829 AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy,
3830 SourceLocation());
3831 Args.push_back(RegSlot);
3832 } else {
3833 // The resource has implicit binding.
3834 CreateMethod =
3835 lookupMethod(SemaRef, ResourceDecl, "__createFromImplicitBinding",
3836 VD->getLocation());
3837 uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
3838 ? RBA->getImplicitBindingOrderID()
3839 : getNextImplicitBindingOrderID();
3840 IntegerLiteral *OrderId =
3841 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
3842 AST.UnsignedIntTy, SourceLocation());
3843 Args.push_back(OrderId);
3844 }
3845
3846 if (!CreateMethod)
3847 // This can happen if someone creates a struct that looks like an HLSL
3848 // resource record but does not have the required static create method.
3849 // No binding will be generated for it.
3850 return false;
3851
3852 IntegerLiteral *Space =
3853 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo),
3854 AST.UnsignedIntTy, SourceLocation());
3855 Args.push_back(Space);
3856
3857 IntegerLiteral *RangeSize = IntegerLiteral::Create(
3858 AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
3859 Args.push_back(RangeSize);
3860
3861 IntegerLiteral *Index = IntegerLiteral::Create(
3862 AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
3863 Args.push_back(Index);
3864
3865 StringRef VarName = VD->getName();
3866 StringLiteral *Name = StringLiteral::Create(
3867 AST, VarName, StringLiteralKind::Ordinary, false,
3868 AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
3869 SourceLocation());
3870 ImplicitCastExpr *NameCast = ImplicitCastExpr::Create(
3871 AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay,
3872 Name, nullptr, VK_PRValue, FPOptionsOverride());
3873 Args.push_back(NameCast);
3874
3875 // Make sure the create method template is instantiated and emitted.
3876 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3877 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3878 true);
3879
3880 // Create CallExpr with a call to the static method and set it as the decl
3881 // initialization.
3882 DeclRefExpr *DRE = DeclRefExpr::Create(
3883 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,
3884 CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue);
3885
3886 auto *ImpCast = ImplicitCastExpr::Create(
3887 AST, AST.getPointerType(CreateMethod->getType()),
3888 CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());
3889
3890 CallExpr *InitExpr =
3891 CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue,
3892 SourceLocation(), FPOptionsOverride());
3893 VD->setInit(InitExpr);
3895 SemaRef.CheckCompleteVariableDeclaration(VD);
3896 return true;
3897}
3898
3899bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
3900 assert(VD->getType()->isHLSLResourceRecordArray() &&
3901 "expected array of resource records");
3902
3903 // Individual resources in a resource array are not initialized here. They
3904 // are initialized later on during codegen when the individual resources are
3905 // accessed. Codegen will emit a call to the resource initialization method
3906 // with the specified array index. We need to make sure though that the method
3907 // for the specific resource type is instantiated, so codegen can emit a call
3908 // to it when the array element is accessed.
3909
3910 // Find correct initialization method based on the resource binding
3911 // information.
3912 ASTContext &AST = SemaRef.getASTContext();
3913 QualType ResElementTy = AST.getBaseElementType(VD->getType());
3914 CXXRecordDecl *ResourceDecl = ResElementTy->getAsCXXRecordDecl();
3915
3916 HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3917 HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>();
3918 CXXMethodDecl *CreateMethod = nullptr;
3919
3920 if (VkBinding || (RBA && RBA->hasRegisterSlot()))
3921 // Resource has explicit binding.
3922 CreateMethod = lookupMethod(SemaRef, ResourceDecl, "__createFromBinding",
3923 VD->getLocation());
3924 else
3925 // Resource has implicit binding.
3926 CreateMethod =
3927 lookupMethod(SemaRef, ResourceDecl, "__createFromImplicitBinding",
3928 VD->getLocation());
3929
3930 if (!CreateMethod)
3931 return false;
3932
3933 // Make sure the create method template is instantiated and emitted.
3934 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3935 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3936 true);
3937 return true;
3938}
3939
3940// Returns true if the initialization has been handled.
3941// Returns false to use default initialization.
3943 // Objects in the hlsl_constant address space are initialized
3944 // externally, so don't synthesize an implicit initializer.
3946 return true;
3947
3948 // Initialize resources at the global scope
3949 if (VD->hasGlobalStorage()) {
3950 const Type *Ty = VD->getType().getTypePtr();
3951 if (Ty->isHLSLResourceRecord())
3952 return initGlobalResourceDecl(VD);
3953 if (Ty->isHLSLResourceRecordArray())
3954 return initGlobalResourceArrayDecl(VD);
3955 }
3956 return false;
3957}
3958
3959// Return true if everything is ok; returns false if there was an error.
3961 Expr *RHSExpr, SourceLocation Loc) {
3962 assert((LHSExpr->getType()->isHLSLResourceRecord() ||
3963 LHSExpr->getType()->isHLSLResourceRecordArray()) &&
3964 "expected LHS to be a resource record or array of resource records");
3965 if (Opc != BO_Assign)
3966 return true;
3967
3968 // If LHS is an array subscript, get the underlying declaration.
3969 Expr *E = LHSExpr;
3970 while (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
3971 E = ASE->getBase()->IgnoreParenImpCasts();
3972
3973 // Report error if LHS is a resource declared at a global scope.
3974 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
3975 if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
3976 if (VD->hasGlobalStorage()) {
3977 // assignment to global resource is not allowed
3978 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
3979 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
3980 return false;
3981 }
3982 }
3983 }
3984 return true;
3985}
3986
3987// Walks though the global variable declaration, collects all resource binding
3988// requirements and adds them to Bindings
3989void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {
3990 assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() &&
3991 "expected global variable that contains HLSL resource");
3992
3993 // Cbuffers and Tbuffers are HLSLBufferDecl types
3994 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3995 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3996 ? ResourceClass::CBuffer
3997 : ResourceClass::SRV);
3998 return;
3999 }
4000
4001 // Unwrap arrays
4002 // FIXME: Calculate array size while unwrapping
4003 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
4004 while (Ty->isArrayType()) {
4005 const ArrayType *AT = cast<ArrayType>(Ty);
4007 }
4008
4009 // Resource (or array of resources)
4010 if (const HLSLAttributedResourceType *AttrResType =
4011 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4012 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4013 return;
4014 }
4015
4016 // User defined record type
4017 if (const RecordType *RT = dyn_cast<RecordType>(Ty))
4018 collectResourceBindingsOnUserRecordDecl(VD, RT);
4019}
4020
4021// Walks though the explicit resource binding attributes on the declaration,
4022// and makes sure there is a resource that matched the binding and updates
4023// DeclBindingInfoLists
4024void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
4025 assert(VD->hasGlobalStorage() && "expected global variable");
4026
4027 bool HasBinding = false;
4028 for (Attr *A : VD->attrs()) {
4030 HasBinding = true;
4031
4032 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4033 if (!RBA || !RBA->hasRegisterSlot())
4034 continue;
4035 HasBinding = true;
4036
4037 RegisterType RT = RBA->getRegisterType();
4038 assert(RT != RegisterType::I && "invalid or obsolete register type should "
4039 "never have an attribute created");
4040
4041 if (RT == RegisterType::C) {
4042 if (Bindings.hasBindingInfoForDecl(VD))
4043 SemaRef.Diag(VD->getLocation(),
4044 diag::warn_hlsl_user_defined_type_missing_member)
4045 << static_cast<int>(RT);
4046 continue;
4047 }
4048
4049 // Find DeclBindingInfo for this binding and update it, or report error
4050 // if it does not exist (user type does to contain resources with the
4051 // expected resource class).
4053 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4054 // update binding info
4055 BI->setBindingAttribute(RBA, BindingType::Explicit);
4056 } else {
4057 SemaRef.Diag(VD->getLocation(),
4058 diag::warn_hlsl_user_defined_type_missing_member)
4059 << static_cast<int>(RT);
4060 }
4061 }
4062
4063 if (!HasBinding && isResourceRecordTypeOrArrayOf(VD))
4064 SemaRef.Diag(VD->getLocation(), diag::warn_hlsl_implicit_binding);
4065}
4066namespace {
4067class InitListTransformer {
4068 Sema &S;
4069 ASTContext &Ctx;
4070 QualType InitTy;
4071 QualType *DstIt = nullptr;
4072 Expr **ArgIt = nullptr;
4073 // Is wrapping the destination type iterator required? This is only used for
4074 // incomplete array types where we loop over the destination type since we
4075 // don't know the full number of elements from the declaration.
4076 bool Wrap;
4077
4078 bool castInitializer(Expr *E) {
4079 assert(DstIt && "This should always be something!");
4080 if (DstIt == DestTypes.end()) {
4081 if (!Wrap) {
4082 ArgExprs.push_back(E);
4083 // This is odd, but it isn't technically a failure due to conversion, we
4084 // handle mismatched counts of arguments differently.
4085 return true;
4086 }
4087 DstIt = DestTypes.begin();
4088 }
4089 InitializedEntity Entity = InitializedEntity::InitializeParameter(
4090 Ctx, *DstIt, /* Consumed (ObjC) */ false);
4091 ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
4092 if (Res.isInvalid())
4093 return false;
4094 Expr *Init = Res.get();
4095 ArgExprs.push_back(Init);
4096 DstIt++;
4097 return true;
4098 }
4099
4100 bool buildInitializerListImpl(Expr *E) {
4101 // If this is an initialization list, traverse the sub initializers.
4102 if (auto *Init = dyn_cast<InitListExpr>(E)) {
4103 for (auto *SubInit : Init->inits())
4104 if (!buildInitializerListImpl(SubInit))
4105 return false;
4106 return true;
4107 }
4108
4109 // If this is a scalar type, just enqueue the expression.
4110 QualType Ty = E->getType();
4111
4112 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4113 return castInitializer(E);
4114
4115 if (auto *VecTy = Ty->getAs<VectorType>()) {
4116 uint64_t Size = VecTy->getNumElements();
4117
4118 QualType SizeTy = Ctx.getSizeType();
4119 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
4120 for (uint64_t I = 0; I < Size; ++I) {
4121 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
4122 SizeTy, SourceLocation());
4123
4125 E, E->getBeginLoc(), Idx, E->getEndLoc());
4126 if (ElExpr.isInvalid())
4127 return false;
4128 if (!castInitializer(ElExpr.get()))
4129 return false;
4130 }
4131 return true;
4132 }
4133
4134 if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {
4135 uint64_t Size = ArrTy->getZExtSize();
4136 QualType SizeTy = Ctx.getSizeType();
4137 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
4138 for (uint64_t I = 0; I < Size; ++I) {
4139 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
4140 SizeTy, SourceLocation());
4142 E, E->getBeginLoc(), Idx, E->getEndLoc());
4143 if (ElExpr.isInvalid())
4144 return false;
4145 if (!buildInitializerListImpl(ElExpr.get()))
4146 return false;
4147 }
4148 return true;
4149 }
4150
4151 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4152 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4153 RecordDecls.push_back(RD);
4154 while (RecordDecls.back()->getNumBases()) {
4155 CXXRecordDecl *D = RecordDecls.back();
4156 assert(D->getNumBases() == 1 &&
4157 "HLSL doesn't support multiple inheritance");
4158 RecordDecls.push_back(
4160 }
4161 while (!RecordDecls.empty()) {
4162 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4163 for (auto *FD : RD->fields()) {
4164 DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());
4165 DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
4167 E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
4168 if (Res.isInvalid())
4169 return false;
4170 if (!buildInitializerListImpl(Res.get()))
4171 return false;
4172 }
4173 }
4174 }
4175 return true;
4176 }
4177
4178 Expr *generateInitListsImpl(QualType Ty) {
4179 assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");
4180 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4181 return *(ArgIt++);
4182
4183 llvm::SmallVector<Expr *> Inits;
4184 assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL");
4185 Ty = Ty.getDesugaredType(Ctx);
4186 if (Ty->isVectorType() || Ty->isConstantArrayType()) {
4187 QualType ElTy;
4188 uint64_t Size = 0;
4189 if (auto *ATy = Ty->getAs<VectorType>()) {
4190 ElTy = ATy->getElementType();
4191 Size = ATy->getNumElements();
4192 } else {
4193 auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());
4194 ElTy = VTy->getElementType();
4195 Size = VTy->getZExtSize();
4196 }
4197 for (uint64_t I = 0; I < Size; ++I)
4198 Inits.push_back(generateInitListsImpl(ElTy));
4199 }
4200 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4201 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4202 RecordDecls.push_back(RD);
4203 while (RecordDecls.back()->getNumBases()) {
4204 CXXRecordDecl *D = RecordDecls.back();
4205 assert(D->getNumBases() == 1 &&
4206 "HLSL doesn't support multiple inheritance");
4207 RecordDecls.push_back(
4209 }
4210 while (!RecordDecls.empty()) {
4211 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4212 for (auto *FD : RD->fields())
4213 Inits.push_back(generateInitListsImpl(FD->getType()));
4214 }
4215 }
4216 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4217 Inits, Inits.back()->getEndLoc());
4218 NewInit->setType(Ty);
4219 return NewInit;
4220 }
4221
4222public:
4223 llvm::SmallVector<QualType, 16> DestTypes;
4224 llvm::SmallVector<Expr *, 16> ArgExprs;
4225 InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)
4226 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4227 Wrap(Entity.getType()->isIncompleteArrayType()) {
4228 InitTy = Entity.getType().getNonReferenceType();
4229 // When we're generating initializer lists for incomplete array types we
4230 // need to wrap around both when building the initializers and when
4231 // generating the final initializer lists.
4232 if (Wrap) {
4233 assert(InitTy->isIncompleteArrayType());
4234 const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType(InitTy);
4235 InitTy = IAT->getElementType();
4236 }
4237 BuildFlattenedTypeList(InitTy, DestTypes);
4238 DstIt = DestTypes.begin();
4239 }
4240
4241 bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }
4242
4243 Expr *generateInitLists() {
4244 assert(!ArgExprs.empty() &&
4245 "Call buildInitializerList to generate argument expressions.");
4246 ArgIt = ArgExprs.begin();
4247 if (!Wrap)
4248 return generateInitListsImpl(InitTy);
4249 llvm::SmallVector<Expr *> Inits;
4250 while (ArgIt != ArgExprs.end())
4251 Inits.push_back(generateInitListsImpl(InitTy));
4252
4253 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4254 Inits, Inits.back()->getEndLoc());
4255 llvm::APInt ArySize(64, Inits.size());
4256 NewInit->setType(Ctx.getConstantArrayType(InitTy, ArySize, nullptr,
4257 ArraySizeModifier::Normal, 0));
4258 return NewInit;
4259 }
4260};
4261} // namespace
4262
4264 InitListExpr *Init) {
4265 // If the initializer is a scalar, just return it.
4266 if (Init->getType()->isScalarType())
4267 return true;
4268 ASTContext &Ctx = SemaRef.getASTContext();
4269 InitListTransformer ILT(SemaRef, Entity);
4270
4271 for (unsigned I = 0; I < Init->getNumInits(); ++I) {
4272 Expr *E = Init->getInit(I);
4273 if (E->HasSideEffects(Ctx)) {
4274 QualType Ty = E->getType();
4275 if (Ty->isRecordType())
4276 E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());
4277 E = new (Ctx) OpaqueValueExpr(E->getBeginLoc(), Ty, E->getValueKind(),
4278 E->getObjectKind(), E);
4279 Init->setInit(I, E);
4280 }
4281 if (!ILT.buildInitializerList(E))
4282 return false;
4283 }
4284 size_t ExpectedSize = ILT.DestTypes.size();
4285 size_t ActualSize = ILT.ArgExprs.size();
4286 // For incomplete arrays it is completely arbitrary to choose whether we think
4287 // the user intended fewer or more elements. This implementation assumes that
4288 // the user intended more, and errors that there are too few initializers to
4289 // complete the final element.
4290 if (Entity.getType()->isIncompleteArrayType())
4291 ExpectedSize =
4292 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4293
4294 // An initializer list might be attempting to initialize a reference or
4295 // rvalue-reference. When checking the initializer we should look through
4296 // the reference.
4297 QualType InitTy = Entity.getType().getNonReferenceType();
4298 if (InitTy.hasAddressSpace())
4299 InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4300 if (ExpectedSize != ActualSize) {
4301 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4302 SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4303 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4304 return false;
4305 }
4306
4307 // generateInitListsImpl will always return an InitListExpr here, because the
4308 // scalar case is handled above.
4309 auto *NewInit = cast<InitListExpr>(ILT.generateInitLists());
4310 Init->resizeInits(Ctx, NewInit->getNumInits());
4311 for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
4312 Init->updateInit(Ctx, I, NewInit->getInit(I));
4313 return true;
4314}
4315
4317 const HLSLVkConstantIdAttr *ConstIdAttr =
4318 VDecl->getAttr<HLSLVkConstantIdAttr>();
4319 if (!ConstIdAttr)
4320 return true;
4321
4322 ASTContext &Context = SemaRef.getASTContext();
4323
4324 APValue InitValue;
4325 if (!Init->isCXX11ConstantExpr(Context, &InitValue)) {
4326 Diag(VDecl->getLocation(), diag::err_specialization_const);
4327 VDecl->setInvalidDecl();
4328 return false;
4329 }
4330
4331 Builtin::ID BID =
4333
4334 // Argument 1: The ID from the attribute
4335 int ConstantID = ConstIdAttr->getId();
4336 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4337 Expr *IdExpr = IntegerLiteral::Create(Context, IDVal, Context.IntTy,
4338 ConstIdAttr->getLocation());
4339
4340 SmallVector<Expr *, 2> Args = {IdExpr, Init};
4341 Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);
4342 if (C->getType()->getCanonicalTypeUnqualified() !=
4344 C = SemaRef
4345 .BuildCStyleCastExpr(SourceLocation(),
4346 Context.getTrivialTypeSourceInfo(
4347 Init->getType(), Init->getExprLoc()),
4348 SourceLocation(), C)
4349 .get();
4350 }
4351 Init = C;
4352 return true;
4353}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
TokenType getType() const
Returns the token's type, e.g.
FormatToken * Previous
The previous token in the unwrapped line.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
#define X(type, name)
Definition Value.h:97
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition SemaHLSL.cpp:944
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
Definition SemaHLSL.cpp:80
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
Definition SemaHLSL.cpp:907
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
Definition SemaHLSL.cpp:217
static bool isZeroSizedArray(const ConstantArrayType *CAT)
Definition SemaHLSL.cpp:336
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
Definition SemaHLSL.cpp:455
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
Definition SemaHLSL.cpp:362
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
Definition SemaHLSL.cpp:130
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
Definition SemaHLSL.cpp:418
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
Definition SemaHLSL.cpp:583
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)
Definition SemaHLSL.cpp:343
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
Definition SemaHLSL.cpp:236
static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)
Definition SemaHLSL.cpp:349
static RegisterType getRegisterType(ResourceClass RC)
Definition SemaHLSL.cpp:60
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
Definition SemaHLSL.cpp:915
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
Definition SemaHLSL.cpp:401
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition SemaHLSL.cpp:920
static ResourceClass getResourceClass(RegisterType RT)
Definition SemaHLSL.cpp:112
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
Definition SemaHLSL.cpp:487
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
Definition SemaHLSL.cpp:552
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
Definition SemaHLSL.cpp:381
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
Definition SemaHLSL.cpp:283
HLSLResourceBindingAttr::RegisterType RegisterType
Definition SemaHLSL.cpp:55
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
Definition SemaHLSL.cpp:997
static bool isValidWaveSizeValue(unsigned Value)
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
Definition Types.cpp:44
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:188
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
IdentifierTable & Idents
Definition ASTContext.h:737
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
CanQualType BoolTy
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
CanQualType CharTy
CanQualType IntTy
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:856
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3720
QualType getElementType() const
Definition TypeBase.h:3732
Attr - This represents one attribute.
Definition Attr.h:44
attr::Kind getKind() const
Definition Attr.h:90
SourceLocation getScopeLoc() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
Definition DeclCXX.h:146
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
Definition DeclCXX.h:1550
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
Definition DeclCXX.cpp:132
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
Definition DeclCXX.cpp:184
void completeDefinition() override
Indicates that the definition of this class is now complete.
Definition DeclCXX.cpp:2239
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
Definition DeclCXX.h:1225
base_class_range bases()
Definition DeclCXX.h:608
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition DeclCXX.h:602
base_class_iterator bases_begin()
Definition DeclCXX.h:615
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1186
const CXXRecordDecl * getStandardLayoutBaseWithFields() const
If this is a standard-layout class or union, any and all data members will be declared in the same ty...
Definition DeclCXX.cpp:559
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3081
SourceLocation getBeginLoc() const
Definition Expr.h:3211
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition Expr.cpp:1513
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
Expr * getCallee()
Definition Expr.h:3024
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3068
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3758
bool isZeroSize() const
Return true if the size is zero.
Definition TypeBase.h:3828
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
Definition DeclBase.h:2185
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:484
ValueDecl * getDecl()
Definition Expr.h:1338
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
void addAttr(Attr *A)
attr_iterator attr_end() const
Definition DeclBase.h:542
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:156
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
Definition DeclBase.h:539
SourceLocation getLocation() const
Definition DeclBase.h:439
void setImplicit(bool I=true)
Definition DeclBase.h:594
DeclContext * getDeclContext()
Definition DeclBase.h:448
attr_range attrs() const
Definition DeclBase.h:535
AccessSpecifier getAccess() const
Definition DeclBase.h:507
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:431
void dropAttr()
Definition DeclBase.h:556
bool hasAttr() const
Definition DeclBase.h:577
The name of a declaration.
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:779
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:830
This represents one expression.
Definition Expr.h:112
void setType(QualType t)
Definition Expr.h:145
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:444
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3085
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3081
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:451
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3665
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
Definition Expr.h:461
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
@ MLV_Valid
Definition Expr.h:305
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3157
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Definition Decl.cpp:4641
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition Diagnostic.h:139
Represents a function declaration or definition.
Definition Decl.h:1999
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2794
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3271
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition Decl.h:2313
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2771
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4198
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3767
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2210
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3191
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition Decl.cpp:3238
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5173
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
Definition Decl.cpp:5777
void addLayoutStruct(CXXRecordDecl *LS)
Definition Decl.cpp:5817
void setHasValidPackoffset(bool PO)
Definition Decl.h:5218
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
Definition Decl.cpp:5800
buffer_decl_range buffer_decls() const
Definition Decl.h:5248
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
Definition Expr.cpp:5499
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
Definition Decl.cpp:5863
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2068
Describes an C or C++ initializer list.
Definition Expr.h:5233
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:971
Represents the results of name lookup.
Definition Lookup.h:147
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition Lookup.h:569
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4914
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3381
This represents a decl that may have a name.
Definition Decl.h:273
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:294
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:300
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:339
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Represents a parameter to a function.
Definition Decl.h:1789
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition ParsedAttr.h:389
bool hasParsedType() const
Definition ParsedAttr.h:337
const ParsedType & getTypeArg() const
Definition ParsedAttr.h:459
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition ParsedAttr.h:371
bool isArgIdent(unsigned Arg) const
Definition ParsedAttr.h:385
Expr * getArgAsExpr(unsigned Arg) const
Definition ParsedAttr.h:383
AttributeCommonInfo::Kind getKind() const
Definition ParsedAttr.h:610
A (possibly-)qualified type.
Definition TypeBase.h:937
void addRestrict()
Add the restrict qualifier to this QualType.
Definition TypeBase.h:1172
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3556
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1296
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8285
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8411
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8470
QualType getCanonicalType() const
Definition TypeBase.h:8337
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8379
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition TypeBase.h:8406
Represents a struct/union/class.
Definition Decl.h:4309
field_range fields() const
Definition Decl.h:4512
bool field_empty() const
Definition Decl.h:4520
bool hasBindingInfoForDecl(const VarDecl *VD) const
Definition SemaHLSL.cpp:191
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Definition SemaHLSL.cpp:177
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Definition SemaHLSL.cpp:164
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition SemaBase.cpp:61
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
Definition SemaHLSL.cpp:892
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D)
Definition SemaHLSL.cpp:772
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
Definition SemaHLSL.cpp:792
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
Definition SemaHLSL.cpp:655
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
Definition SemaHLSL.cpp:621
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
Definition SemaHLSL.cpp:864
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
bool ContainsBitField(QualType BaseTy)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
T * createSemanticAttr(const ParsedAttr &AL, std::optional< unsigned > Location)
Definition SemaHLSL.h:182
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
void ActOnTopLevelFunction(FunctionDecl *FD)
Definition SemaHLSL.cpp:724
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
Definition SemaHLSL.cpp:691
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
Definition SemaHLSL.cpp:593
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
Definition SemaHLSL.cpp:704
QualType getInoutParameterType(QualType Ty)
SemaHLSL(Sema &S)
Definition SemaHLSL.cpp:195
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
Definition SemaHLSL.cpp:197
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
Definition SemaHLSL.cpp:635
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9291
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
Definition Sema.h:9299
ASTContext & Context
Definition Sema.h:1283
ASTContext & getASTContext() const
Definition Sema.h:925
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
Definition Sema.cpp:756
const LangOptions & getLangOpts() const
Definition Sema.h:918
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:358
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
Definition Expr.cpp:1184
void startDefinition()
Starts the definition of this tag declaration.
Definition Decl.cpp:4847
bool isUnion() const
Definition Decl.h:3919
bool isClass() const
Definition Decl.h:3918
Exposes information about the current target.
Definition TargetInfo.h:226
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:323
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
The top declaration context.
Definition Decl.h:104
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8256
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:272
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isVoidType() const
Definition TypeBase.h:8878
bool isBooleanType() const
Definition TypeBase.h:9008
bool isIncompleteArrayType() const
Definition TypeBase.h:8629
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantArrayType() const
Definition TypeBase.h:8625
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition Type.cpp:2066
bool isArrayType() const
Definition TypeBase.h:8621
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
bool isArithmeticType() const
Definition Type.cpp:2337
bool isHLSLBuiltinIntangibleType() const
Definition TypeBase.h:8823
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8922
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9165
bool isReferenceType() const
Definition TypeBase.h:8546
bool isHLSLIntangibleType() const
Definition Type.cpp:5383
bool isEnumeralType() const
Definition TypeBase.h:8653
bool isScalarType() const
Definition TypeBase.h:8980
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2103
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
Definition Type.cpp:471
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2291
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2411
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
Definition Type.cpp:2364
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2243
bool isHLSLResourceRecord() const
Definition Type.cpp:5370
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition Type.cpp:2312
bool isVectorType() const
Definition TypeBase.h:8661
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2320
bool isHLSLAttributedResourceType() const
Definition TypeBase.h:8835
@ STK_FloatingComplex
Definition TypeBase.h:2764
@ STK_ObjCObjectPointer
Definition TypeBase.h:2758
@ STK_IntegralComplex
Definition TypeBase.h:2763
@ STK_MemberPointer
Definition TypeBase.h:2759
bool isFloatingType() const
Definition Type.cpp:2304
bool isSamplerT() const
Definition TypeBase.h:8756
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9098
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:653
bool isRecordType() const
Definition TypeBase.h:8649
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5374
void setType(QualType newType)
Definition Decl.h:723
QualType getType() const
Definition Decl.h:722
Represents a variable declaration or definition.
Definition Decl.h:925
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1451
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:933
void setStorageClass(StorageClass SC)
Definition Decl.cpp:2163
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1225
void setInit(Expr *I)
Definition Decl.cpp:2477
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1167
Represents a GCC generic vector type.
Definition TypeBase.h:4173
unsigned getNumElements() const
Definition TypeBase.h:4188
QualType getElementType() const
Definition TypeBase.h:4187
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition SemaSPIRV.cpp:66
@ ICIS_NoInit
No in-class initializer.
Definition Specifiers.h:272
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
Definition SemaSPIRV.cpp:49
@ AS_public
Definition Specifiers.h:124
@ AS_none
Definition Specifiers.h:127
@ SC_Static
Definition Specifiers.h:252
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
Definition TypeBase.h:905
@ Ordinary
This parameter uses ordinary ABI rules for its type.
Definition Specifiers.h:380
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
Definition SemaSPIRV.cpp:32
ExprResult ExprError()
Definition Ownership.h:265
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
Visibility
Describes the different kinds of visibility that a declaration may have.
Definition Visibility.h:34
unsigned long uint64_t
unsigned int uint32_t
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
#define false
Definition stdbool.h:26
Describes how types, statements, expressions, and declarations should be printed.
const SourceLocation & getLocation() const
Definition SemaHLSL.h:46
const llvm::hlsl::rootsig::RootElement & getElement() const
Definition SemaHLSL.h:45