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
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 ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(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() &&
369 isZeroSizedArray(cast<ConstantArrayType>(Ty)))
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
619}
620
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 if (RootSigOverrideIdent) {
733 LookupResult R(SemaRef, RootSigOverrideIdent, SourceLocation(),
736 if (auto *SignatureDecl =
737 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
738 FD->dropAttr<RootSignatureAttr>();
739 // We could look up the SourceRange of the macro here as well
740 AttributeCommonInfo AL(RootSigOverrideIdent, AttributeScopeInfo(),
741 SourceRange(), ParsedAttr::Form::Microsoft());
742 FD->addAttr(::new (getASTContext()) RootSignatureAttr(
743 getASTContext(), AL, RootSigOverrideIdent, SignatureDecl));
744 }
745 }
746
747 llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment();
748 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
749 if (const auto *Shader = FD->getAttr<HLSLShaderAttr>()) {
750 // The entry point is already annotated - check that it matches the
751 // triple.
752 if (Shader->getType() != Env) {
753 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
754 << Shader;
755 FD->setInvalidDecl();
756 }
757 } else {
758 // Implicitly add the shader attribute if the entry function isn't
759 // explicitly annotated.
760 FD->addAttr(HLSLShaderAttr::CreateImplicit(getASTContext(), Env,
761 FD->getBeginLoc()));
762 }
763 } else {
764 switch (Env) {
765 case llvm::Triple::UnknownEnvironment:
766 case llvm::Triple::Library:
767 break;
768 default:
769 llvm_unreachable("Unhandled environment in triple");
770 }
771 }
772}
773
775 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
776 assert(ShaderAttr && "Entry point has no shader attribute");
777 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
779 VersionTuple Ver = TargetInfo.getTriple().getOSVersion();
780 switch (ST) {
781 case llvm::Triple::Pixel:
782 case llvm::Triple::Vertex:
783 case llvm::Triple::Geometry:
784 case llvm::Triple::Hull:
785 case llvm::Triple::Domain:
786 case llvm::Triple::RayGeneration:
787 case llvm::Triple::Intersection:
788 case llvm::Triple::AnyHit:
789 case llvm::Triple::ClosestHit:
790 case llvm::Triple::Miss:
791 case llvm::Triple::Callable:
792 if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {
794 {llvm::Triple::Compute,
795 llvm::Triple::Amplification,
796 llvm::Triple::Mesh});
797 FD->setInvalidDecl();
798 }
799 if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
801 {llvm::Triple::Compute,
802 llvm::Triple::Amplification,
803 llvm::Triple::Mesh});
804 FD->setInvalidDecl();
805 }
806 break;
807
808 case llvm::Triple::Compute:
809 case llvm::Triple::Amplification:
810 case llvm::Triple::Mesh:
811 if (!FD->hasAttr<HLSLNumThreadsAttr>()) {
812 Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)
813 << llvm::Triple::getEnvironmentTypeName(ST);
814 FD->setInvalidDecl();
815 }
816 if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
817 if (Ver < VersionTuple(6, 6)) {
818 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
819 << WS << "6.6";
820 FD->setInvalidDecl();
821 } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
822 Diag(
823 WS->getLocation(),
824 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
825 << WS << WS->getSpelledArgsCount() << "6.8";
826 FD->setInvalidDecl();
827 }
828 }
829 break;
830 default:
831 llvm_unreachable("Unhandled environment in triple");
832 }
833
834 for (ParmVarDecl *Param : FD->parameters()) {
835 if (const auto *AnnotationAttr = Param->getAttr<HLSLAnnotationAttr>()) {
836 CheckSemanticAnnotation(FD, Param, AnnotationAttr);
837 } else {
838 // FIXME: Handle struct parameters where annotations are on struct fields.
839 // See: https://github.com/llvm/llvm-project/issues/57875
840 Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation);
841 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
842 FD->setInvalidDecl();
843 }
844 }
845 // FIXME: Verify return type semantic annotation.
846}
847
849 FunctionDecl *EntryPoint, const Decl *Param,
850 const HLSLAnnotationAttr *AnnotationAttr) {
851 auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>();
852 assert(ShaderAttr && "Entry point has no shader attribute");
853 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
854
855 switch (AnnotationAttr->getKind()) {
856 case attr::HLSLSV_DispatchThreadID:
857 case attr::HLSLSV_GroupIndex:
858 case attr::HLSLSV_GroupThreadID:
859 case attr::HLSLSV_GroupID:
860 if (ST == llvm::Triple::Compute)
861 return;
862 DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
863 break;
864 case attr::HLSLSV_Position:
865 // TODO(#143523): allow use on other shader types & output once the overall
866 // semantic logic is implemented.
867 if (ST == llvm::Triple::Pixel)
868 return;
869 DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Pixel});
870 break;
871 default:
872 llvm_unreachable("Unknown HLSLAnnotationAttr");
873 }
874}
875
877 const Attr *A, llvm::Triple::EnvironmentType Stage,
878 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
879 SmallVector<StringRef, 8> StageStrings;
880 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
881 [](llvm::Triple::EnvironmentType ST) {
882 return StringRef(
883 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
884 });
885 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
886 << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
887 << (AllowedStages.size() != 1) << join(StageStrings, ", ");
888}
889
890template <CastKind Kind>
891static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
892 if (const auto *VTy = Ty->getAs<VectorType>())
893 Ty = VTy->getElementType();
894 Ty = S.getASTContext().getExtVectorType(Ty, Sz);
895 E = S.ImpCastExprToType(E.get(), Ty, Kind);
896}
897
898template <CastKind Kind>
900 E = S.ImpCastExprToType(E.get(), Ty, Kind);
901 return Ty;
902}
903
905 Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
906 QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
907 bool LHSFloat = LElTy->isRealFloatingType();
908 bool RHSFloat = RElTy->isRealFloatingType();
909
910 if (LHSFloat && RHSFloat) {
911 if (IsCompAssign ||
912 SemaRef.getASTContext().getFloatingTypeOrder(LElTy, RElTy) > 0)
913 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
914
915 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
916 }
917
918 if (LHSFloat)
919 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
920
921 assert(RHSFloat);
922 if (IsCompAssign)
923 return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
924
925 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
926}
927
929 Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
930 QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
931
932 int IntOrder = SemaRef.Context.getIntegerTypeOrder(LElTy, RElTy);
933 bool LHSSigned = LElTy->hasSignedIntegerRepresentation();
934 bool RHSSigned = RElTy->hasSignedIntegerRepresentation();
935 auto &Ctx = SemaRef.getASTContext();
936
937 // If both types have the same signedness, use the higher ranked type.
938 if (LHSSigned == RHSSigned) {
939 if (IsCompAssign || IntOrder >= 0)
940 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
941
942 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
943 }
944
945 // If the unsigned type has greater than or equal rank of the signed type, use
946 // the unsigned type.
947 if (IntOrder != (LHSSigned ? 1 : -1)) {
948 if (IsCompAssign || RHSSigned)
949 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
950 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
951 }
952
953 // At this point the signed type has higher rank than the unsigned type, which
954 // means it will be the same size or bigger. If the signed type is bigger, it
955 // can represent all the values of the unsigned type, so select it.
956 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
957 if (IsCompAssign || LHSSigned)
958 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
959 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
960 }
961
962 // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due
963 // to C/C++ leaking through. The place this happens today is long vs long
964 // long. When arguments are vector<unsigned long, N> and vector<long long, N>,
965 // the long long has higher rank than long even though they are the same size.
966
967 // If this is a compound assignment cast the right hand side to the left hand
968 // side's type.
969 if (IsCompAssign)
970 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
971
972 // If this isn't a compound assignment we convert to unsigned long long.
973 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
974 QualType NewTy = Ctx.getExtVectorType(
975 ElTy, RHSType->castAs<VectorType>()->getNumElements());
976 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
977
978 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
979}
980
982 QualType SrcTy) {
983 if (DestTy->isRealFloatingType() && SrcTy->isRealFloatingType())
984 return CK_FloatingCast;
985 if (DestTy->isIntegralType(Ctx) && SrcTy->isIntegralType(Ctx))
986 return CK_IntegralCast;
987 if (DestTy->isRealFloatingType())
988 return CK_IntegralToFloating;
989 assert(SrcTy->isRealFloatingType() && DestTy->isIntegralType(Ctx));
990 return CK_FloatingToIntegral;
991}
992
994 QualType LHSType,
995 QualType RHSType,
996 bool IsCompAssign) {
997 const auto *LVecTy = LHSType->getAs<VectorType>();
998 const auto *RVecTy = RHSType->getAs<VectorType>();
999 auto &Ctx = getASTContext();
1000
1001 // If the LHS is not a vector and this is a compound assignment, we truncate
1002 // the argument to a scalar then convert it to the LHS's type.
1003 if (!LVecTy && IsCompAssign) {
1004 QualType RElTy = RHSType->castAs<VectorType>()->getElementType();
1005 RHS = SemaRef.ImpCastExprToType(RHS.get(), RElTy, CK_HLSLVectorTruncation);
1006 RHSType = RHS.get()->getType();
1007 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1008 return LHSType;
1009 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSType,
1010 getScalarCastKind(Ctx, LHSType, RHSType));
1011 return LHSType;
1012 }
1013
1014 unsigned EndSz = std::numeric_limits<unsigned>::max();
1015 unsigned LSz = 0;
1016 if (LVecTy)
1017 LSz = EndSz = LVecTy->getNumElements();
1018 if (RVecTy)
1019 EndSz = std::min(RVecTy->getNumElements(), EndSz);
1020 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1021 "one of the above should have had a value");
1022
1023 // In a compound assignment, the left operand does not change type, the right
1024 // operand is converted to the type of the left operand.
1025 if (IsCompAssign && LSz != EndSz) {
1026 Diag(LHS.get()->getBeginLoc(),
1027 diag::err_hlsl_vector_compound_assignment_truncation)
1028 << LHSType << RHSType;
1029 return QualType();
1030 }
1031
1032 if (RVecTy && RVecTy->getNumElements() > EndSz)
1033 castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);
1034 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1035 castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);
1036
1037 if (!RVecTy)
1038 castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);
1039 if (!IsCompAssign && !LVecTy)
1040 castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);
1041
1042 // If we're at the same type after resizing we can stop here.
1043 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1044 return Ctx.getCommonSugaredType(LHSType, RHSType);
1045
1046 QualType LElTy = LHSType->castAs<VectorType>()->getElementType();
1047 QualType RElTy = RHSType->castAs<VectorType>()->getElementType();
1048
1049 // Handle conversion for floating point vectors.
1050 if (LElTy->isRealFloatingType() || RElTy->isRealFloatingType())
1051 return handleFloatVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,
1052 LElTy, RElTy, IsCompAssign);
1053
1054 assert(LElTy->isIntegralType(Ctx) && RElTy->isIntegralType(Ctx) &&
1055 "HLSL Vectors can only contain integer or floating point types");
1056 return handleIntegerVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,
1057 LElTy, RElTy, IsCompAssign);
1058}
1059
1061 BinaryOperatorKind Opc) {
1062 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1063 "Called with non-logical operator");
1065 llvm::raw_svector_ostream OS(Buff);
1067 StringRef NewFnName = Opc == BO_LOr ? "or" : "and";
1068 OS << NewFnName << "(";
1069 LHS->printPretty(OS, nullptr, PP);
1070 OS << ", ";
1071 RHS->printPretty(OS, nullptr, PP);
1072 OS << ")";
1073 SourceRange FullRange = SourceRange(LHS->getBeginLoc(), RHS->getEndLoc());
1074 SemaRef.Diag(LHS->getBeginLoc(), diag::note_function_suggestion)
1075 << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
1076}
1077
1078std::pair<IdentifierInfo *, bool>
1080 llvm::hash_code Hash = llvm::hash_value(Signature);
1081 std::string IdStr = "__hlsl_rootsig_decl_" + std::to_string(Hash);
1082 IdentifierInfo *DeclIdent = &(getASTContext().Idents.get(IdStr));
1083
1084 // Check if we have already found a decl of the same name.
1085 LookupResult R(SemaRef, DeclIdent, SourceLocation(),
1088 return {DeclIdent, Found};
1089}
1090
1092 SourceLocation Loc, IdentifierInfo *DeclIdent,
1094
1095 if (handleRootSignatureElements(RootElements))
1096 return;
1097
1099 for (auto &RootSigElement : RootElements)
1100 Elements.push_back(RootSigElement.getElement());
1101
1102 auto *SignatureDecl = HLSLRootSignatureDecl::Create(
1103 SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc,
1104 DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1105
1106 SignatureDecl->setImplicit();
1107 SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());
1108}
1109
1110namespace {
1111
1112struct PerVisibilityBindingChecker {
1113 SemaHLSL *S;
1114 // We need one builder per `llvm::dxbc::ShaderVisibility` value.
1115 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1116
1117 struct ElemInfo {
1118 const hlsl::RootSignatureElement *Elem;
1119 llvm::dxbc::ShaderVisibility Vis;
1120 bool Diagnosed;
1121 };
1122 llvm::SmallVector<ElemInfo> ElemInfoMap;
1123
1124 PerVisibilityBindingChecker(SemaHLSL *S) : S(S) {}
1125
1126 void trackBinding(llvm::dxbc::ShaderVisibility Visibility,
1127 llvm::dxil::ResourceClass RC, uint32_t Space,
1128 uint32_t LowerBound, uint32_t UpperBound,
1129 const hlsl::RootSignatureElement *Elem) {
1130 uint32_t BuilderIndex = llvm::to_underlying(Visibility);
1131 assert(BuilderIndex < Builders.size() &&
1132 "Not enough builders for visibility type");
1133 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1134 static_cast<const void *>(Elem));
1135
1136 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1137 "'All' visibility must come first");
1138 if (Visibility == llvm::dxbc::ShaderVisibility::All)
1139 for (size_t I = 1, E = Builders.size(); I < E; ++I)
1140 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1141 static_cast<const void *>(Elem));
1142
1143 ElemInfoMap.push_back({Elem, Visibility, false});
1144 }
1145
1146 ElemInfo &getInfo(const hlsl::RootSignatureElement *Elem) {
1147 auto It = llvm::lower_bound(
1148 ElemInfoMap, Elem,
1149 [](const auto &LHS, const auto &RHS) { return LHS.Elem < RHS; });
1150 assert(It->Elem == Elem && "Element not in map");
1151 return *It;
1152 }
1153
1154 bool checkOverlap() {
1155 llvm::sort(ElemInfoMap, [](const auto &LHS, const auto &RHS) {
1156 return LHS.Elem < RHS.Elem;
1157 });
1158
1159 bool HadOverlap = false;
1160
1161 using llvm::hlsl::BindingInfoBuilder;
1162 auto ReportOverlap = [this,
1163 &HadOverlap](const BindingInfoBuilder &Builder,
1164 const llvm::hlsl::Binding &Reported) {
1165 HadOverlap = true;
1166
1167 const auto *Elem =
1168 static_cast<const hlsl::RootSignatureElement *>(Reported.Cookie);
1169 const llvm::hlsl::Binding &Previous = Builder.findOverlapping(Reported);
1170 const auto *PrevElem =
1171 static_cast<const hlsl::RootSignatureElement *>(Previous.Cookie);
1172
1173 ElemInfo &Info = getInfo(Elem);
1174 // We will have already diagnosed this binding if there's overlap in the
1175 // "All" visibility as well as any particular visibility.
1176 if (Info.Diagnosed)
1177 return;
1178 Info.Diagnosed = true;
1179
1180 ElemInfo &PrevInfo = getInfo(PrevElem);
1181 llvm::dxbc::ShaderVisibility CommonVis =
1182 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1183 : Info.Vis;
1184
1185 this->S->Diag(Elem->getLocation(), diag::err_hlsl_resource_range_overlap)
1186 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1187 << Reported.isUnbounded() << Reported.UpperBound
1188 << llvm::to_underlying(Previous.RC) << Previous.LowerBound
1189 << Previous.isUnbounded() << Previous.UpperBound << Reported.Space
1190 << CommonVis;
1191
1192 this->S->Diag(PrevElem->getLocation(),
1193 diag::note_hlsl_resource_range_here);
1194 };
1195
1196 for (BindingInfoBuilder &Builder : Builders)
1197 Builder.calculateBindingInfo(ReportOverlap);
1198
1199 return HadOverlap;
1200 }
1201};
1202
1203} // end anonymous namespace
1204
1207 // Define some common error handling functions
1208 bool HadError = false;
1209 auto ReportError = [this, &HadError](SourceLocation Loc, uint32_t LowerBound,
1210 uint32_t UpperBound) {
1211 HadError = true;
1212 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1213 << LowerBound << UpperBound;
1214 };
1215
1216 auto ReportFloatError = [this, &HadError](SourceLocation Loc,
1217 float LowerBound,
1218 float UpperBound) {
1219 HadError = true;
1220 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1221 << llvm::formatv("{0:f}", LowerBound).sstr<6>()
1222 << llvm::formatv("{0:f}", UpperBound).sstr<6>();
1223 };
1224
1225 auto VerifyRegister = [ReportError](SourceLocation Loc, uint32_t Register) {
1226 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1227 ReportError(Loc, 0, 0xfffffffe);
1228 };
1229
1230 auto VerifySpace = [ReportError](SourceLocation Loc, uint32_t Space) {
1231 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1232 ReportError(Loc, 0, 0xffffffef);
1233 };
1234
1235 const uint32_t Version =
1236 llvm::to_underlying(SemaRef.getLangOpts().HLSLRootSigVer);
1237 const uint32_t VersionEnum = Version - 1;
1238 auto ReportFlagError = [this, &HadError, VersionEnum](SourceLocation Loc) {
1239 HadError = true;
1240 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1241 << /*version minor*/ VersionEnum;
1242 };
1243
1244 // Iterate through the elements and do basic validations
1245 for (const hlsl::RootSignatureElement &RootSigElem : Elements) {
1246 SourceLocation Loc = RootSigElem.getLocation();
1247 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();
1248 if (const auto *Descriptor =
1249 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1250 VerifyRegister(Loc, Descriptor->Reg.Number);
1251 VerifySpace(Loc, Descriptor->Space);
1252
1253 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(
1254 Version, llvm::to_underlying(Descriptor->Flags)))
1255 ReportFlagError(Loc);
1256 } else if (const auto *Constants =
1257 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1258 VerifyRegister(Loc, Constants->Reg.Number);
1259 VerifySpace(Loc, Constants->Space);
1260 } else if (const auto *Sampler =
1261 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1262 VerifyRegister(Loc, Sampler->Reg.Number);
1263 VerifySpace(Loc, Sampler->Space);
1264
1265 assert(!std::isnan(Sampler->MaxLOD) && !std::isnan(Sampler->MinLOD) &&
1266 "By construction, parseFloatParam can't produce a NaN from a "
1267 "float_literal token");
1268
1269 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1270 ReportError(Loc, 0, 16);
1271 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1272 ReportFloatError(Loc, -16.f, 15.99f);
1273 } else if (const auto *Clause =
1274 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1275 &Elem)) {
1276 VerifyRegister(Loc, Clause->Reg.Number);
1277 VerifySpace(Loc, Clause->Space);
1278
1279 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1280 // NumDescriptor could techincally be ~0u but that is reserved for
1281 // unbounded, so the diagnostic will not report that as a valid int
1282 // value
1283 ReportError(Loc, 1, 0xfffffffe);
1284 }
1285
1286 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(
1287 Version, llvm::to_underlying(Clause->Type),
1288 llvm::to_underlying(Clause->Flags)))
1289 ReportFlagError(Loc);
1290 }
1291 }
1292
1293 PerVisibilityBindingChecker BindingChecker(this);
1294 SmallVector<std::pair<const llvm::hlsl::rootsig::DescriptorTableClause *,
1296 UnboundClauses;
1297
1298 for (const hlsl::RootSignatureElement &RootSigElem : Elements) {
1299 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();
1300 if (const auto *Descriptor =
1301 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1302 uint32_t LowerBound(Descriptor->Reg.Number);
1303 uint32_t UpperBound(LowerBound); // inclusive range
1304
1305 BindingChecker.trackBinding(
1306 Descriptor->Visibility,
1307 static_cast<llvm::dxil::ResourceClass>(Descriptor->Type),
1308 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1309 } else if (const auto *Constants =
1310 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1311 uint32_t LowerBound(Constants->Reg.Number);
1312 uint32_t UpperBound(LowerBound); // inclusive range
1313
1314 BindingChecker.trackBinding(
1315 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1316 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1317 } else if (const auto *Sampler =
1318 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1319 uint32_t LowerBound(Sampler->Reg.Number);
1320 uint32_t UpperBound(LowerBound); // inclusive range
1321
1322 BindingChecker.trackBinding(
1323 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1324 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1325 } else if (const auto *Clause =
1326 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1327 &Elem)) {
1328 // We'll process these once we see the table element.
1329 UnboundClauses.emplace_back(Clause, &RootSigElem);
1330 } else if (const auto *Table =
1331 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1332 assert(UnboundClauses.size() == Table->NumClauses &&
1333 "Number of unbound elements must match the number of clauses");
1334 for (const auto &[Clause, ClauseElem] : UnboundClauses) {
1335 uint32_t LowerBound(Clause->Reg.Number);
1336 // Relevant error will have already been reported above and needs to be
1337 // fixed before we can conduct range analysis, so shortcut error return
1338 if (Clause->NumDescriptors == 0)
1339 return true;
1340 uint32_t UpperBound = Clause->NumDescriptors == ~0u
1341 ? ~0u
1342 : LowerBound + Clause->NumDescriptors - 1;
1343
1344 BindingChecker.trackBinding(
1345 Table->Visibility,
1346 static_cast<llvm::dxil::ResourceClass>(Clause->Type), Clause->Space,
1347 LowerBound, UpperBound, ClauseElem);
1348 }
1349 UnboundClauses.clear();
1350 }
1351 }
1352
1353 return BindingChecker.checkOverlap();
1354}
1355
1357 if (AL.getNumArgs() != 1) {
1358 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1359 return;
1360 }
1361
1363 if (auto *RS = D->getAttr<RootSignatureAttr>()) {
1364 if (RS->getSignatureIdent() != Ident) {
1365 Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1366 return;
1367 }
1368
1369 Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1370 return;
1371 }
1372
1375 if (auto *SignatureDecl =
1376 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1377 D->addAttr(::new (getASTContext()) RootSignatureAttr(
1378 getASTContext(), AL, Ident, SignatureDecl));
1379 }
1380}
1381
1383 llvm::VersionTuple SMVersion =
1384 getASTContext().getTargetInfo().getTriple().getOSVersion();
1385 bool IsDXIL = getASTContext().getTargetInfo().getTriple().getArch() ==
1386 llvm::Triple::dxil;
1387
1388 uint32_t ZMax = 1024;
1389 uint32_t ThreadMax = 1024;
1390 if (IsDXIL && SMVersion.getMajor() <= 4) {
1391 ZMax = 1;
1392 ThreadMax = 768;
1393 } else if (IsDXIL && SMVersion.getMajor() == 5) {
1394 ZMax = 64;
1395 ThreadMax = 1024;
1396 }
1397
1398 uint32_t X;
1399 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), X))
1400 return;
1401 if (X > 1024) {
1402 Diag(AL.getArgAsExpr(0)->getExprLoc(),
1403 diag::err_hlsl_numthreads_argument_oor)
1404 << 0 << 1024;
1405 return;
1406 }
1407 uint32_t Y;
1408 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Y))
1409 return;
1410 if (Y > 1024) {
1411 Diag(AL.getArgAsExpr(1)->getExprLoc(),
1412 diag::err_hlsl_numthreads_argument_oor)
1413 << 1 << 1024;
1414 return;
1415 }
1416 uint32_t Z;
1417 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Z))
1418 return;
1419 if (Z > ZMax) {
1421 diag::err_hlsl_numthreads_argument_oor)
1422 << 2 << ZMax;
1423 return;
1424 }
1425
1426 if (X * Y * Z > ThreadMax) {
1427 Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1428 return;
1429 }
1430
1431 HLSLNumThreadsAttr *NewAttr = mergeNumThreadsAttr(D, AL, X, Y, Z);
1432 if (NewAttr)
1433 D->addAttr(NewAttr);
1434}
1435
1436static bool isValidWaveSizeValue(unsigned Value) {
1437 return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;
1438}
1439
1441 // validate that the wavesize argument is a power of 2 between 4 and 128
1442 // inclusive
1443 unsigned SpelledArgsCount = AL.getNumArgs();
1444 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1445 return;
1446
1447 uint32_t Min;
1449 return;
1450
1451 uint32_t Max = 0;
1452 if (SpelledArgsCount > 1 &&
1454 return;
1455
1456 uint32_t Preferred = 0;
1457 if (SpelledArgsCount > 2 &&
1458 !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Preferred))
1459 return;
1460
1461 if (SpelledArgsCount > 2) {
1462 if (!isValidWaveSizeValue(Preferred)) {
1463 Diag(AL.getArgAsExpr(2)->getExprLoc(),
1464 diag::err_attribute_power_of_two_in_range)
1465 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1466 << Preferred;
1467 return;
1468 }
1469 // Preferred not in range.
1470 if (Preferred < Min || Preferred > Max) {
1471 Diag(AL.getArgAsExpr(2)->getExprLoc(),
1472 diag::err_attribute_power_of_two_in_range)
1473 << AL << Min << Max << Preferred;
1474 return;
1475 }
1476 } else if (SpelledArgsCount > 1) {
1477 if (!isValidWaveSizeValue(Max)) {
1478 Diag(AL.getArgAsExpr(1)->getExprLoc(),
1479 diag::err_attribute_power_of_two_in_range)
1480 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;
1481 return;
1482 }
1483 if (Max < Min) {
1484 Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1485 return;
1486 } else if (Max == Min) {
1487 Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;
1488 }
1489 } else {
1490 if (!isValidWaveSizeValue(Min)) {
1491 Diag(AL.getArgAsExpr(0)->getExprLoc(),
1492 diag::err_attribute_power_of_two_in_range)
1493 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;
1494 return;
1495 }
1496 }
1497
1498 HLSLWaveSizeAttr *NewAttr =
1499 mergeWaveSizeAttr(D, AL, Min, Max, Preferred, SpelledArgsCount);
1500 if (NewAttr)
1501 D->addAttr(NewAttr);
1502}
1503
1505 uint32_t ID;
1506 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), ID))
1507 return;
1508 D->addAttr(::new (getASTContext())
1509 HLSLVkExtBuiltinInputAttr(getASTContext(), AL, ID));
1510}
1511
1513 uint32_t Id;
1514 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Id))
1515 return;
1516 HLSLVkConstantIdAttr *NewAttr = mergeVkConstantIdAttr(D, AL, Id);
1517 if (NewAttr)
1518 D->addAttr(NewAttr);
1519}
1520
1522 // The vk::binding attribute only applies to SPIR-V.
1523 if (!getASTContext().getTargetInfo().getTriple().isSPIRV())
1524 return;
1525
1526 uint32_t Binding = 0;
1527 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Binding))
1528 return;
1529 uint32_t Set = 0;
1530 if (AL.getNumArgs() > 1 &&
1532 return;
1533
1534 D->addAttr(::new (getASTContext())
1535 HLSLVkBindingAttr(getASTContext(), AL, Binding, Set));
1536}
1537
1539 const auto *VT = T->getAs<VectorType>();
1540
1542 (VT && VT->getNumElements() > 3)) {
1543 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1544 << AL << "uint/uint2/uint3";
1545 return false;
1546 }
1547
1548 return true;
1549}
1550
1552 auto *VD = cast<ValueDecl>(D);
1553 if (!diagnoseInputIDType(VD->getType(), AL))
1554 return;
1555
1556 D->addAttr(::new (getASTContext())
1557 HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
1558}
1559
1561 const auto *VT = T->getAs<VectorType>();
1562
1563 if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1564 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1565 << AL << "float/float1/float2/float3/float4";
1566 return false;
1567 }
1568
1569 return true;
1570}
1571
1573 auto *VD = cast<ValueDecl>(D);
1574 if (!diagnosePositionType(VD->getType(), AL))
1575 return;
1576
1577 D->addAttr(::new (getASTContext()) HLSLSV_PositionAttr(getASTContext(), AL));
1578}
1579
1581 auto *VD = cast<ValueDecl>(D);
1582 if (!diagnoseInputIDType(VD->getType(), AL))
1583 return;
1584
1585 D->addAttr(::new (getASTContext())
1586 HLSLSV_GroupThreadIDAttr(getASTContext(), AL));
1587}
1588
1590 auto *VD = cast<ValueDecl>(D);
1591 if (!diagnoseInputIDType(VD->getType(), AL))
1592 return;
1593
1594 D->addAttr(::new (getASTContext()) HLSLSV_GroupIDAttr(getASTContext(), AL));
1595}
1596
1598 if (!isa<VarDecl>(D) || !isa<HLSLBufferDecl>(D->getDeclContext())) {
1599 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1600 << AL << "shader constant in a constant buffer";
1601 return;
1602 }
1603
1604 uint32_t SubComponent;
1605 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), SubComponent))
1606 return;
1607 uint32_t Component;
1608 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Component))
1609 return;
1610
1611 QualType T = cast<VarDecl>(D)->getType().getCanonicalType();
1612 // Check if T is an array or struct type.
1613 // TODO: mark matrix type as aggregate type.
1614 bool IsAggregateTy = (T->isArrayType() || T->isStructureType());
1615
1616 // Check Component is valid for T.
1617 if (Component) {
1618 unsigned Size = getASTContext().getTypeSize(T);
1619 if (IsAggregateTy || Size > 128) {
1620 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1621 return;
1622 } else {
1623 // Make sure Component + sizeof(T) <= 4.
1624 if ((Component * 32 + Size) > 128) {
1625 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1626 return;
1627 }
1628 QualType EltTy = T;
1629 if (const auto *VT = T->getAs<VectorType>())
1630 EltTy = VT->getElementType();
1631 unsigned Align = getASTContext().getTypeAlign(EltTy);
1632 if (Align > 32 && Component == 1) {
1633 // NOTE: Component 3 will hit err_hlsl_packoffset_cross_reg_boundary.
1634 // So we only need to check Component 1 here.
1635 Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1636 << Align << EltTy;
1637 return;
1638 }
1639 }
1640 }
1641
1642 D->addAttr(::new (getASTContext()) HLSLPackOffsetAttr(
1643 getASTContext(), AL, SubComponent, Component));
1644}
1645
1647 StringRef Str;
1648 SourceLocation ArgLoc;
1649 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1650 return;
1651
1652 llvm::Triple::EnvironmentType ShaderType;
1653 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1654 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1655 << AL << Str << ArgLoc;
1656 return;
1657 }
1658
1659 // FIXME: check function match the shader stage.
1660
1661 HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);
1662 if (NewAttr)
1663 D->addAttr(NewAttr);
1664}
1665
1667 Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,
1668 QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo) {
1669 assert(AttrList.size() && "expected list of resource attributes");
1670
1671 QualType ContainedTy = QualType();
1672 TypeSourceInfo *ContainedTyInfo = nullptr;
1673 SourceLocation LocBegin = AttrList[0]->getRange().getBegin();
1674 SourceLocation LocEnd = AttrList[0]->getRange().getEnd();
1675
1677
1678 bool HasResourceClass = false;
1679 for (const Attr *A : AttrList) {
1680 if (!A)
1681 continue;
1682 LocEnd = A->getRange().getEnd();
1683 switch (A->getKind()) {
1684 case attr::HLSLResourceClass: {
1685 ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
1686 if (HasResourceClass) {
1687 S.Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1688 ? diag::warn_duplicate_attribute_exact
1689 : diag::warn_duplicate_attribute)
1690 << A;
1691 return false;
1692 }
1693 ResAttrs.ResourceClass = RC;
1694 HasResourceClass = true;
1695 break;
1696 }
1697 case attr::HLSLROV:
1698 if (ResAttrs.IsROV) {
1699 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1700 return false;
1701 }
1702 ResAttrs.IsROV = true;
1703 break;
1704 case attr::HLSLRawBuffer:
1705 if (ResAttrs.RawBuffer) {
1706 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1707 return false;
1708 }
1709 ResAttrs.RawBuffer = true;
1710 break;
1711 case attr::HLSLContainedType: {
1712 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
1713 QualType Ty = CTAttr->getType();
1714 if (!ContainedTy.isNull()) {
1715 S.Diag(A->getLocation(), ContainedTy == Ty
1716 ? diag::warn_duplicate_attribute_exact
1717 : diag::warn_duplicate_attribute)
1718 << A;
1719 return false;
1720 }
1721 ContainedTy = Ty;
1722 ContainedTyInfo = CTAttr->getTypeLoc();
1723 break;
1724 }
1725 default:
1726 llvm_unreachable("unhandled resource attribute type");
1727 }
1728 }
1729
1730 if (!HasResourceClass) {
1731 S.Diag(AttrList.back()->getRange().getEnd(),
1732 diag::err_hlsl_missing_resource_class);
1733 return false;
1734 }
1735
1737 Wrapped, ContainedTy, ResAttrs);
1738
1739 if (LocInfo && ContainedTyInfo) {
1740 LocInfo->Range = SourceRange(LocBegin, LocEnd);
1741 LocInfo->ContainedTyInfo = ContainedTyInfo;
1742 }
1743 return true;
1744}
1745
1746// Validates and creates an HLSL attribute that is applied as type attribute on
1747// HLSL resource. The attributes are collected in HLSLResourcesTypeAttrs and at
1748// the end of the declaration they are applied to the declaration type by
1749// wrapping it in HLSLAttributedResourceType.
1751 // only allow resource type attributes on intangible types
1752 if (!T->isHLSLResourceType()) {
1753 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1754 << AL << getASTContext().HLSLResourceTy;
1755 return false;
1756 }
1757
1758 // validate number of arguments
1759 if (!AL.checkExactlyNumArgs(SemaRef, AL.getMinArgs()))
1760 return false;
1761
1762 Attr *A = nullptr;
1763
1767 {
1768 AttributeCommonInfo::AS_CXX11, 0, false /*IsAlignas*/,
1769 false /*IsRegularKeywordAttribute*/
1770 });
1771
1772 switch (AL.getKind()) {
1773 case ParsedAttr::AT_HLSLResourceClass: {
1774 if (!AL.isArgIdent(0)) {
1775 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1776 << AL << AANT_ArgumentIdentifier;
1777 return false;
1778 }
1779
1781 StringRef Identifier = Loc->getIdentifierInfo()->getName();
1782 SourceLocation ArgLoc = Loc->getLoc();
1783
1784 // Validate resource class value
1785 ResourceClass RC;
1786 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1787 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1788 << "ResourceClass" << Identifier;
1789 return false;
1790 }
1791 A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);
1792 break;
1793 }
1794
1795 case ParsedAttr::AT_HLSLROV:
1796 A = HLSLROVAttr::Create(getASTContext(), ACI);
1797 break;
1798
1799 case ParsedAttr::AT_HLSLRawBuffer:
1800 A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
1801 break;
1802
1803 case ParsedAttr::AT_HLSLContainedType: {
1804 if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {
1805 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1806 return false;
1807 }
1808
1809 TypeSourceInfo *TSI = nullptr;
1811 assert(TSI && "no type source info for attribute argument");
1813 diag::err_incomplete_type))
1814 return false;
1815 A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);
1816 break;
1817 }
1818
1819 default:
1820 llvm_unreachable("unhandled HLSL attribute");
1821 }
1822
1823 HLSLResourcesTypeAttrs.emplace_back(A);
1824 return true;
1825}
1826
1827// Combines all resource type attributes and creates HLSLAttributedResourceType.
1829 if (!HLSLResourcesTypeAttrs.size())
1830 return CurrentType;
1831
1832 QualType QT = CurrentType;
1835 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1836 const HLSLAttributedResourceType *RT =
1837 cast<HLSLAttributedResourceType>(QT.getTypePtr());
1838
1839 // Temporarily store TypeLoc information for the new type.
1840 // It will be transferred to HLSLAttributesResourceTypeLoc
1841 // shortly after the type is created by TypeSpecLocFiller which
1842 // will call the TakeLocForHLSLAttribute method below.
1843 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1844 }
1845 HLSLResourcesTypeAttrs.clear();
1846 return QT;
1847}
1848
1849// Returns source location for the HLSLAttributedResourceType
1852 HLSLAttributedResourceLocInfo LocInfo = {};
1853 auto I = LocsForHLSLAttributedResources.find(RT);
1854 if (I != LocsForHLSLAttributedResources.end()) {
1855 LocInfo = I->second;
1856 LocsForHLSLAttributedResources.erase(I);
1857 return LocInfo;
1858 }
1859 LocInfo.Range = SourceRange();
1860 return LocInfo;
1861}
1862
1863// Walks though the global variable declaration, collects all resource binding
1864// requirements and adds them to Bindings
1865void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
1866 const RecordType *RT) {
1867 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1868 for (FieldDecl *FD : RD->fields()) {
1869 const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();
1870
1871 // Unwrap arrays
1872 // FIXME: Calculate array size while unwrapping
1873 assert(!Ty->isIncompleteArrayType() &&
1874 "incomplete arrays inside user defined types are not supported");
1875 while (Ty->isConstantArrayType()) {
1876 const ConstantArrayType *CAT = cast<ConstantArrayType>(Ty);
1878 }
1879
1880 if (!Ty->isRecordType())
1881 continue;
1882
1883 if (const HLSLAttributedResourceType *AttrResType =
1885 // Add a new DeclBindingInfo to Bindings if it does not already exist
1886 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1887 DeclBindingInfo *DBI = Bindings.getDeclBindingInfo(VD, RC);
1888 if (!DBI)
1889 Bindings.addDeclBindingInfo(VD, RC);
1890 } else if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1891 // Recursively scan embedded struct or class; it would be nice to do this
1892 // without recursion, but tricky to correctly calculate the size of the
1893 // binding, which is something we are probably going to need to do later
1894 // on. Hopefully nesting of structs in structs too many levels is
1895 // unlikely.
1896 collectResourceBindingsOnUserRecordDecl(VD, RT);
1897 }
1898 }
1899}
1900
1901// Diagnose localized register binding errors for a single binding; does not
1902// diagnose resource binding on user record types, that will be done later
1903// in processResourceBindingOnDecl based on the information collected in
1904// collectResourceBindingsOnVarDecl.
1905// Returns false if the register binding is not valid.
1907 Decl *D, RegisterType RegType,
1908 bool SpecifiedSpace) {
1909 int RegTypeNum = static_cast<int>(RegType);
1910
1911 // check if the decl type is groupshared
1912 if (D->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
1913 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1914 return false;
1915 }
1916
1917 // Cbuffers and Tbuffers are HLSLBufferDecl types
1918 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
1919 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1920 : ResourceClass::SRV;
1921 if (RegType == getRegisterType(RC))
1922 return true;
1923
1924 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
1925 << RegTypeNum;
1926 return false;
1927 }
1928
1929 // Samplers, UAVs, and SRVs are VarDecl types
1930 assert(isa<VarDecl>(D) && "D is expected to be VarDecl or HLSLBufferDecl");
1931 VarDecl *VD = cast<VarDecl>(D);
1932
1933 // Resource
1934 if (const HLSLAttributedResourceType *AttrResType =
1936 VD->getType().getTypePtr())) {
1937 if (RegType == getRegisterType(AttrResType))
1938 return true;
1939
1940 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
1941 << RegTypeNum;
1942 return false;
1943 }
1944
1945 const clang::Type *Ty = VD->getType().getTypePtr();
1946 while (Ty->isArrayType())
1948
1949 // Basic types
1950 if (Ty->isArithmeticType() || Ty->isVectorType()) {
1951 bool DeclaredInCOrTBuffer = isa<HLSLBufferDecl>(D->getDeclContext());
1952 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
1953 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1954
1955 if (!DeclaredInCOrTBuffer && (Ty->isIntegralType(S.getASTContext()) ||
1956 Ty->isFloatingType() || Ty->isVectorType())) {
1957 // Register annotation on default constant buffer declaration ($Globals)
1958 if (RegType == RegisterType::CBuffer)
1959 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1960 else if (RegType != RegisterType::C)
1961 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1962 else
1963 return true;
1964 } else {
1965 if (RegType == RegisterType::C)
1966 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1967 else
1968 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1969 }
1970 return false;
1971 }
1972 if (Ty->isRecordType())
1973 // RecordTypes will be diagnosed in processResourceBindingOnDecl
1974 // that is called from ActOnVariableDeclarator
1975 return true;
1976
1977 // Anything else is an error
1978 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1979 return false;
1980}
1981
1983 RegisterType regType) {
1984 // make sure that there are no two register annotations
1985 // applied to the decl with the same register type
1986 bool RegisterTypesDetected[5] = {false};
1987 RegisterTypesDetected[static_cast<int>(regType)] = true;
1988
1989 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {
1990 if (HLSLResourceBindingAttr *attr =
1991 dyn_cast<HLSLResourceBindingAttr>(*it)) {
1992
1993 RegisterType otherRegType = attr->getRegisterType();
1994 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {
1995 int otherRegTypeNum = static_cast<int>(otherRegType);
1996 S.Diag(TheDecl->getLocation(),
1997 diag::err_hlsl_duplicate_register_annotation)
1998 << otherRegTypeNum;
1999 return false;
2000 }
2001 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;
2002 }
2003 }
2004 return true;
2005}
2006
2008 Decl *D, RegisterType RegType,
2009 bool SpecifiedSpace) {
2010
2011 // exactly one of these two types should be set
2012 assert(((isa<VarDecl>(D) && !isa<HLSLBufferDecl>(D)) ||
2013 (!isa<VarDecl>(D) && isa<HLSLBufferDecl>(D))) &&
2014 "expecting VarDecl or HLSLBufferDecl");
2015
2016 // check if the declaration contains resource matching the register type
2017 if (!DiagnoseLocalRegisterBinding(S, ArgLoc, D, RegType, SpecifiedSpace))
2018 return false;
2019
2020 // next, if multiple register annotations exist, check that none conflict.
2021 return ValidateMultipleRegisterAnnotations(S, D, RegType);
2022}
2023
2025 if (isa<VarDecl>(TheDecl)) {
2027 cast<ValueDecl>(TheDecl)->getType(),
2028 diag::err_incomplete_type))
2029 return;
2030 }
2031
2032 StringRef Slot = "";
2033 StringRef Space = "";
2034 SourceLocation SlotLoc, SpaceLoc;
2035
2036 if (!AL.isArgIdent(0)) {
2037 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2038 << AL << AANT_ArgumentIdentifier;
2039 return;
2040 }
2042
2043 if (AL.getNumArgs() == 2) {
2044 Slot = Loc->getIdentifierInfo()->getName();
2045 SlotLoc = Loc->getLoc();
2046 if (!AL.isArgIdent(1)) {
2047 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2048 << AL << AANT_ArgumentIdentifier;
2049 return;
2050 }
2051 Loc = AL.getArgAsIdent(1);
2052 Space = Loc->getIdentifierInfo()->getName();
2053 SpaceLoc = Loc->getLoc();
2054 } else {
2055 StringRef Str = Loc->getIdentifierInfo()->getName();
2056 if (Str.starts_with("space")) {
2057 Space = Str;
2058 SpaceLoc = Loc->getLoc();
2059 } else {
2060 Slot = Str;
2061 SlotLoc = Loc->getLoc();
2062 Space = "space0";
2063 }
2064 }
2065
2066 RegisterType RegType = RegisterType::SRV;
2067 std::optional<unsigned> SlotNum;
2068 unsigned SpaceNum = 0;
2069
2070 // Validate slot
2071 if (!Slot.empty()) {
2072 if (!convertToRegisterType(Slot, &RegType)) {
2073 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2074 return;
2075 }
2076 if (RegType == RegisterType::I) {
2077 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2078 return;
2079 }
2080 StringRef SlotNumStr = Slot.substr(1);
2081 unsigned N;
2082 if (SlotNumStr.getAsInteger(10, N)) {
2083 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2084 return;
2085 }
2086 SlotNum = N;
2087 }
2088
2089 // Validate space
2090 if (!Space.starts_with("space")) {
2091 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2092 return;
2093 }
2094 StringRef SpaceNumStr = Space.substr(5);
2095 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2096 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2097 return;
2098 }
2099
2100 // If we have slot, diagnose it is the right register type for the decl
2101 if (SlotNum.has_value())
2102 if (!DiagnoseHLSLRegisterAttribute(SemaRef, SlotLoc, TheDecl, RegType,
2103 !SpaceLoc.isInvalid()))
2104 return;
2105
2106 HLSLResourceBindingAttr *NewAttr =
2107 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
2108 if (NewAttr) {
2109 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2110 TheDecl->addAttr(NewAttr);
2111 }
2112}
2113
2115 HLSLParamModifierAttr *NewAttr = mergeParamModifierAttr(
2116 D, AL,
2117 static_cast<HLSLParamModifierAttr::Spelling>(AL.getSemanticSpelling()));
2118 if (NewAttr)
2119 D->addAttr(NewAttr);
2120}
2121
2122namespace {
2123
2124/// This class implements HLSL availability diagnostics for default
2125/// and relaxed mode
2126///
2127/// The goal of this diagnostic is to emit an error or warning when an
2128/// unavailable API is found in code that is reachable from the shader
2129/// entry function or from an exported function (when compiling a shader
2130/// library).
2131///
2132/// This is done by traversing the AST of all shader entry point functions
2133/// and of all exported functions, and any functions that are referenced
2134/// from this AST. In other words, any functions that are reachable from
2135/// the entry points.
2136class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
2137 Sema &SemaRef;
2138
2139 // Stack of functions to be scaned
2141
2142 // Tracks which environments functions have been scanned in.
2143 //
2144 // Maps FunctionDecl to an unsigned number that represents the set of shader
2145 // environments the function has been scanned for.
2146 // The llvm::Triple::EnvironmentType enum values for shader stages guaranteed
2147 // to be numbered from llvm::Triple::Pixel to llvm::Triple::Amplification
2148 // (verified by static_asserts in Triple.cpp), we can use it to index
2149 // individual bits in the set, as long as we shift the values to start with 0
2150 // by subtracting the value of llvm::Triple::Pixel first.
2151 //
2152 // The N'th bit in the set will be set if the function has been scanned
2153 // in shader environment whose llvm::Triple::EnvironmentType integer value
2154 // equals (llvm::Triple::Pixel + N).
2155 //
2156 // For example, if a function has been scanned in compute and pixel stage
2157 // environment, the value will be 0x21 (100001 binary) because:
2158 //
2159 // (int)(llvm::Triple::Pixel - llvm::Triple::Pixel) == 0
2160 // (int)(llvm::Triple::Compute - llvm::Triple::Pixel) == 5
2161 //
2162 // A FunctionDecl is mapped to 0 (or not included in the map) if it has not
2163 // been scanned in any environment.
2164 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2165
2166 // Do not access these directly, use the get/set methods below to make
2167 // sure the values are in sync
2168 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2169 unsigned CurrentShaderStageBit;
2170
2171 // True if scanning a function that was already scanned in a different
2172 // shader stage context, and therefore we should not report issues that
2173 // depend only on shader model version because they would be duplicate.
2174 bool ReportOnlyShaderStageIssues;
2175
2176 // Helper methods for dealing with current stage context / environment
2177 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2178 static_assert(sizeof(unsigned) >= 4);
2179 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2180 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2181 "ShaderType is too big for this bitmap"); // 31 is reserved for
2182 // "unknown"
2183
2184 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2185 CurrentShaderEnvironment = ShaderType;
2186 CurrentShaderStageBit = (1 << bitmapIndex);
2187 }
2188
2189 void SetUnknownShaderStageContext() {
2190 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2191 CurrentShaderStageBit = (1 << 31);
2192 }
2193
2194 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
2195 return CurrentShaderEnvironment;
2196 }
2197
2198 bool InUnknownShaderStageContext() const {
2199 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2200 }
2201
2202 // Helper methods for dealing with shader stage bitmap
2203 void AddToScannedFunctions(const FunctionDecl *FD) {
2204 unsigned &ScannedStages = ScannedDecls[FD];
2205 ScannedStages |= CurrentShaderStageBit;
2206 }
2207
2208 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }
2209
2210 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
2211 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2212 }
2213
2214 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
2215 return ScannerStages & CurrentShaderStageBit;
2216 }
2217
2218 static bool NeverBeenScanned(unsigned ScannedStages) {
2219 return ScannedStages == 0;
2220 }
2221
2222 // Scanning methods
2223 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2224 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
2226 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
2227 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
2228
2229public:
2230 DiagnoseHLSLAvailability(Sema &SemaRef)
2231 : SemaRef(SemaRef),
2232 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2233 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
2234
2235 // AST traversal methods
2236 void RunOnTranslationUnit(const TranslationUnitDecl *TU);
2237 void RunOnFunction(const FunctionDecl *FD);
2238
2239 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
2240 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());
2241 if (FD)
2242 HandleFunctionOrMethodRef(FD, DRE);
2243 return true;
2244 }
2245
2246 bool VisitMemberExpr(MemberExpr *ME) override {
2247 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());
2248 if (FD)
2249 HandleFunctionOrMethodRef(FD, ME);
2250 return true;
2251 }
2252};
2253
2254void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
2255 Expr *RefExpr) {
2256 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
2257 "expected DeclRefExpr or MemberExpr");
2258
2259 // has a definition -> add to stack to be scanned
2260 const FunctionDecl *FDWithBody = nullptr;
2261 if (FD->hasBody(FDWithBody)) {
2262 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2263 DeclsToScan.push_back(FDWithBody);
2264 return;
2265 }
2266
2267 // no body -> diagnose availability
2268 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2269 if (AA)
2270 CheckDeclAvailability(
2271 FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));
2272}
2273
2274void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2275 const TranslationUnitDecl *TU) {
2276
2277 // Iterate over all shader entry functions and library exports, and for those
2278 // that have a body (definiton), run diag scan on each, setting appropriate
2279 // shader environment context based on whether it is a shader entry function
2280 // or an exported function. Exported functions can be in namespaces and in
2281 // export declarations so we need to scan those declaration contexts as well.
2283 DeclContextsToScan.push_back(TU);
2284
2285 while (!DeclContextsToScan.empty()) {
2286 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2287 for (auto &D : DC->decls()) {
2288 // do not scan implicit declaration generated by the implementation
2289 if (D->isImplicit())
2290 continue;
2291
2292 // for namespace or export declaration add the context to the list to be
2293 // scanned later
2294 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2295 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2296 continue;
2297 }
2298
2299 // skip over other decls or function decls without body
2300 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2301 if (!FD || !FD->isThisDeclarationADefinition())
2302 continue;
2303
2304 // shader entry point
2305 if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) {
2306 SetShaderStageContext(ShaderAttr->getType());
2307 RunOnFunction(FD);
2308 continue;
2309 }
2310 // exported library function
2311 // FIXME: replace this loop with external linkage check once issue #92071
2312 // is resolved
2313 bool isExport = FD->isInExportDeclContext();
2314 if (!isExport) {
2315 for (const auto *Redecl : FD->redecls()) {
2316 if (Redecl->isInExportDeclContext()) {
2317 isExport = true;
2318 break;
2319 }
2320 }
2321 }
2322 if (isExport) {
2323 SetUnknownShaderStageContext();
2324 RunOnFunction(FD);
2325 continue;
2326 }
2327 }
2328 }
2329}
2330
2331void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
2332 assert(DeclsToScan.empty() && "DeclsToScan should be empty");
2333 DeclsToScan.push_back(FD);
2334
2335 while (!DeclsToScan.empty()) {
2336 // Take one decl from the stack and check it by traversing its AST.
2337 // For any CallExpr found during the traversal add it's callee to the top of
2338 // the stack to be processed next. Functions already processed are stored in
2339 // ScannedDecls.
2340 const FunctionDecl *FD = DeclsToScan.pop_back_val();
2341
2342 // Decl was already scanned
2343 const unsigned ScannedStages = GetScannedStages(FD);
2344 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2345 continue;
2346
2347 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2348
2349 AddToScannedFunctions(FD);
2350 TraverseStmt(FD->getBody());
2351 }
2352}
2353
2354bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2355 const AvailabilityAttr *AA) {
2356 IdentifierInfo *IIEnvironment = AA->getEnvironment();
2357 if (!IIEnvironment)
2358 return true;
2359
2360 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2361 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2362 return false;
2363
2364 llvm::Triple::EnvironmentType AttrEnv =
2365 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
2366
2367 return CurrentEnv == AttrEnv;
2368}
2369
2370const AvailabilityAttr *
2371DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
2372 AvailabilityAttr const *PartialMatch = nullptr;
2373 // Check each AvailabilityAttr to find the one for this platform.
2374 // For multiple attributes with the same platform try to find one for this
2375 // environment.
2376 for (const auto *A : D->attrs()) {
2377 if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2378 StringRef AttrPlatform = Avail->getPlatform()->getName();
2379 StringRef TargetPlatform =
2381
2382 // Match the platform name.
2383 if (AttrPlatform == TargetPlatform) {
2384 // Find the best matching attribute for this environment
2385 if (HasMatchingEnvironmentOrNone(Avail))
2386 return Avail;
2387 PartialMatch = Avail;
2388 }
2389 }
2390 }
2391 return PartialMatch;
2392}
2393
2394// Check availability against target shader model version and current shader
2395// stage and emit diagnostic
2396void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
2397 const AvailabilityAttr *AA,
2399
2400 IdentifierInfo *IIEnv = AA->getEnvironment();
2401
2402 if (!IIEnv) {
2403 // The availability attribute does not have environment -> it depends only
2404 // on shader model version and not on specific the shader stage.
2405
2406 // Skip emitting the diagnostics if the diagnostic mode is set to
2407 // strict (-fhlsl-strict-availability) because all relevant diagnostics
2408 // were already emitted in the DiagnoseUnguardedAvailability scan
2409 // (SemaAvailability.cpp).
2410 if (SemaRef.getLangOpts().HLSLStrictAvailability)
2411 return;
2412
2413 // Do not report shader-stage-independent issues if scanning a function
2414 // that was already scanned in a different shader stage context (they would
2415 // be duplicate)
2416 if (ReportOnlyShaderStageIssues)
2417 return;
2418
2419 } else {
2420 // The availability attribute has environment -> we need to know
2421 // the current stage context to property diagnose it.
2422 if (InUnknownShaderStageContext())
2423 return;
2424 }
2425
2426 // Check introduced version and if environment matches
2427 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2428 VersionTuple Introduced = AA->getIntroduced();
2429 VersionTuple TargetVersion =
2431
2432 if (TargetVersion >= Introduced && EnvironmentMatches)
2433 return;
2434
2435 // Emit diagnostic message
2436 const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
2437 llvm::StringRef PlatformName(
2438 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
2439
2440 llvm::StringRef CurrentEnvStr =
2441 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2442
2443 llvm::StringRef AttrEnvStr =
2444 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";
2445 bool UseEnvironment = !AttrEnvStr.empty();
2446
2447 if (EnvironmentMatches) {
2448 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)
2449 << Range << D << PlatformName << Introduced.getAsString()
2450 << UseEnvironment << CurrentEnvStr;
2451 } else {
2452 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2453 << Range << D;
2454 }
2455
2456 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
2457 << D << PlatformName << Introduced.getAsString()
2458 << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
2459 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2460}
2461
2462} // namespace
2463
2465 // process default CBuffer - create buffer layout struct and invoke codegenCGH
2466 if (!DefaultCBufferDecls.empty()) {
2469 DefaultCBufferDecls);
2470 addImplicitBindingAttrToDecl(SemaRef, DefaultCBuffer, RegisterType::CBuffer,
2471 getNextImplicitBindingOrderID());
2472 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2474
2475 // Set HasValidPackoffset if any of the decls has a register(c#) annotation;
2476 for (const Decl *VD : DefaultCBufferDecls) {
2477 const HLSLResourceBindingAttr *RBA =
2478 VD->getAttr<HLSLResourceBindingAttr>();
2479 if (RBA && RBA->hasRegisterSlot() &&
2480 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2481 DefaultCBuffer->setHasValidPackoffset(true);
2482 break;
2483 }
2484 }
2485
2486 DeclGroupRef DG(DefaultCBuffer);
2488 }
2489 diagnoseAvailabilityViolations(TU);
2490}
2491
2492void SemaHLSL::diagnoseAvailabilityViolations(TranslationUnitDecl *TU) {
2493 // Skip running the diagnostics scan if the diagnostic mode is
2494 // strict (-fhlsl-strict-availability) and the target shader stage is known
2495 // because all relevant diagnostics were already emitted in the
2496 // DiagnoseUnguardedAvailability scan (SemaAvailability.cpp).
2498 if (SemaRef.getLangOpts().HLSLStrictAvailability &&
2499 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2500 return;
2501
2502 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
2503}
2504
2505static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {
2506 assert(TheCall->getNumArgs() > 1);
2507 QualType ArgTy0 = TheCall->getArg(0)->getType();
2508
2509 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {
2511 ArgTy0, TheCall->getArg(I)->getType())) {
2512 S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2513 << TheCall->getDirectCallee() << /*useAllTerminology*/ true
2514 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
2515 TheCall->getArg(N - 1)->getEndLoc());
2516 return true;
2517 }
2518 }
2519 return false;
2520}
2521
2523 QualType ArgType = Arg->getType();
2525 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
2526 << ArgType << ExpectedType << 1 << 0 << 0;
2527 return true;
2528 }
2529 return false;
2530}
2531
2533 Sema *S, CallExpr *TheCall,
2534 llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,
2535 clang::QualType PassedType)>
2536 Check) {
2537 for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {
2538 Expr *Arg = TheCall->getArg(I);
2539 if (Check(S, Arg->getBeginLoc(), I + 1, Arg->getType()))
2540 return true;
2541 }
2542 return false;
2543}
2544
2546 int ArgOrdinal,
2547 clang::QualType PassedType) {
2548 clang::QualType BaseType =
2549 PassedType->isVectorType()
2550 ? PassedType->castAs<clang::VectorType>()->getElementType()
2551 : PassedType;
2552 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2553 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2554 << ArgOrdinal << /* scalar or vector of */ 5 << /* no int */ 0
2555 << /* half or float */ 2 << PassedType;
2556 return false;
2557}
2558
2559static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall,
2560 unsigned ArgIndex) {
2561 auto *Arg = TheCall->getArg(ArgIndex);
2562 SourceLocation OrigLoc = Arg->getExprLoc();
2563 if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==
2565 return false;
2566 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2567 return true;
2568}
2569
2570static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal,
2571 clang::QualType PassedType) {
2572 const auto *VecTy = PassedType->getAs<VectorType>();
2573 if (!VecTy)
2574 return false;
2575
2576 if (VecTy->getElementType()->isDoubleType())
2577 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2578 << ArgOrdinal << /* scalar */ 1 << /* no int */ 0 << /* fp */ 1
2579 << PassedType;
2580 return false;
2581}
2582
2584 int ArgOrdinal,
2585 clang::QualType PassedType) {
2586 if (!PassedType->hasIntegerRepresentation() &&
2587 !PassedType->hasFloatingRepresentation())
2588 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2589 << ArgOrdinal << /* scalar or vector of */ 5 << /* integer */ 1
2590 << /* fp */ 1 << PassedType;
2591 return false;
2592}
2593
2595 int ArgOrdinal,
2596 clang::QualType PassedType) {
2597 if (auto *VecTy = PassedType->getAs<VectorType>())
2598 if (VecTy->getElementType()->isUnsignedIntegerType())
2599 return false;
2600
2601 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2602 << ArgOrdinal << /* vector of */ 4 << /* uint */ 3 << /* no fp */ 0
2603 << PassedType;
2604}
2605
2606// checks for unsigned ints of all sizes
2608 int ArgOrdinal,
2609 clang::QualType PassedType) {
2610 if (!PassedType->hasUnsignedIntegerRepresentation())
2611 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2612 << ArgOrdinal << /* scalar or vector of */ 5 << /* unsigned int */ 3
2613 << /* no fp */ 0 << PassedType;
2614 return false;
2615}
2616
2618 QualType ReturnType) {
2619 auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
2620 if (VecTyA)
2621 ReturnType =
2622 S->Context.getExtVectorType(ReturnType, VecTyA->getNumElements());
2623
2624 TheCall->setType(ReturnType);
2625}
2626
2627static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar,
2628 unsigned ArgIndex) {
2629 assert(TheCall->getNumArgs() >= ArgIndex);
2630 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2631 auto *VTy = ArgType->getAs<VectorType>();
2632 // not the scalar or vector<scalar>
2633 if (!(S->Context.hasSameUnqualifiedType(ArgType, Scalar) ||
2634 (VTy &&
2635 S->Context.hasSameUnqualifiedType(VTy->getElementType(), Scalar)))) {
2636 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2637 diag::err_typecheck_expect_scalar_or_vector)
2638 << ArgType << Scalar;
2639 return true;
2640 }
2641 return false;
2642}
2643
2644static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall,
2645 unsigned ArgIndex) {
2646 assert(TheCall->getNumArgs() >= ArgIndex);
2647 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2648 auto *VTy = ArgType->getAs<VectorType>();
2649 // not the scalar or vector<scalar>
2650 if (!(ArgType->isScalarType() ||
2651 (VTy && VTy->getElementType()->isScalarType()))) {
2652 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2653 diag::err_typecheck_expect_any_scalar_or_vector)
2654 << ArgType << 1;
2655 return true;
2656 }
2657 return false;
2658}
2659
2660static bool CheckWaveActive(Sema *S, CallExpr *TheCall) {
2661 QualType BoolType = S->getASTContext().BoolTy;
2662 assert(TheCall->getNumArgs() >= 1);
2663 QualType ArgType = TheCall->getArg(0)->getType();
2664 auto *VTy = ArgType->getAs<VectorType>();
2665 // is the bool or vector<bool>
2666 if (S->Context.hasSameUnqualifiedType(ArgType, BoolType) ||
2667 (VTy &&
2668 S->Context.hasSameUnqualifiedType(VTy->getElementType(), BoolType))) {
2669 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2670 diag::err_typecheck_expect_any_scalar_or_vector)
2671 << ArgType << 0;
2672 return true;
2673 }
2674 return false;
2675}
2676
2677static bool CheckBoolSelect(Sema *S, CallExpr *TheCall) {
2678 assert(TheCall->getNumArgs() == 3);
2679 Expr *Arg1 = TheCall->getArg(1);
2680 Expr *Arg2 = TheCall->getArg(2);
2681 if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), Arg2->getType())) {
2682 S->Diag(TheCall->getBeginLoc(),
2683 diag::err_typecheck_call_different_arg_types)
2684 << Arg1->getType() << Arg2->getType() << Arg1->getSourceRange()
2685 << Arg2->getSourceRange();
2686 return true;
2687 }
2688
2689 TheCall->setType(Arg1->getType());
2690 return false;
2691}
2692
2693static bool CheckVectorSelect(Sema *S, CallExpr *TheCall) {
2694 assert(TheCall->getNumArgs() == 3);
2695 Expr *Arg1 = TheCall->getArg(1);
2696 QualType Arg1Ty = Arg1->getType();
2697 Expr *Arg2 = TheCall->getArg(2);
2698 QualType Arg2Ty = Arg2->getType();
2699
2700 QualType Arg1ScalarTy = Arg1Ty;
2701 if (auto VTy = Arg1ScalarTy->getAs<VectorType>())
2702 Arg1ScalarTy = VTy->getElementType();
2703
2704 QualType Arg2ScalarTy = Arg2Ty;
2705 if (auto VTy = Arg2ScalarTy->getAs<VectorType>())
2706 Arg2ScalarTy = VTy->getElementType();
2707
2708 if (!S->Context.hasSameUnqualifiedType(Arg1ScalarTy, Arg2ScalarTy))
2709 S->Diag(Arg1->getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2710 << /* second and third */ 1 << TheCall->getCallee() << Arg1Ty << Arg2Ty;
2711
2712 QualType Arg0Ty = TheCall->getArg(0)->getType();
2713 unsigned Arg0Length = Arg0Ty->getAs<VectorType>()->getNumElements();
2714 unsigned Arg1Length = Arg1Ty->isVectorType()
2715 ? Arg1Ty->getAs<VectorType>()->getNumElements()
2716 : 0;
2717 unsigned Arg2Length = Arg2Ty->isVectorType()
2718 ? Arg2Ty->getAs<VectorType>()->getNumElements()
2719 : 0;
2720 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2721 S->Diag(TheCall->getBeginLoc(),
2722 diag::err_typecheck_vector_lengths_not_equal)
2723 << Arg0Ty << Arg1Ty << TheCall->getArg(0)->getSourceRange()
2724 << Arg1->getSourceRange();
2725 return true;
2726 }
2727
2728 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2729 S->Diag(TheCall->getBeginLoc(),
2730 diag::err_typecheck_vector_lengths_not_equal)
2731 << Arg0Ty << Arg2Ty << TheCall->getArg(0)->getSourceRange()
2732 << Arg2->getSourceRange();
2733 return true;
2734 }
2735
2736 TheCall->setType(
2737 S->getASTContext().getExtVectorType(Arg1ScalarTy, Arg0Length));
2738 return false;
2739}
2740
2742 Sema *S, CallExpr *TheCall, unsigned ArgIndex,
2743 llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =
2744 nullptr) {
2745 assert(TheCall->getNumArgs() >= ArgIndex);
2746 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2747 const HLSLAttributedResourceType *ResTy =
2749 if (!ResTy) {
2750 S->Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),
2751 diag::err_typecheck_expect_hlsl_resource)
2752 << ArgType;
2753 return true;
2754 }
2755 if (Check && Check(ResTy)) {
2756 S->Diag(TheCall->getArg(ArgIndex)->getExprLoc(),
2757 diag::err_invalid_hlsl_resource_type)
2758 << ArgType;
2759 return true;
2760 }
2761 return false;
2762}
2763
2764// Note: returning true in this case results in CheckBuiltinFunctionCall
2765// returning an ExprError
2766bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
2767 switch (BuiltinID) {
2768 case Builtin::BI__builtin_hlsl_adduint64: {
2769 if (SemaRef.checkArgCount(TheCall, 2))
2770 return true;
2771
2772 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
2774 return true;
2775
2776 auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
2777 // ensure arg integers are 32-bits
2778 uint64_t ElementBitCount = getASTContext()
2779 .getTypeSizeInChars(VTy->getElementType())
2780 .getQuantity() *
2781 8;
2782 if (ElementBitCount != 32) {
2783 SemaRef.Diag(TheCall->getBeginLoc(),
2784 diag::err_integer_incorrect_bit_count)
2785 << 32 << ElementBitCount;
2786 return true;
2787 }
2788
2789 // ensure both args are vectors of total bit size of a multiple of 64
2790 int NumElementsArg = VTy->getNumElements();
2791 if (NumElementsArg != 2 && NumElementsArg != 4) {
2792 SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count)
2793 << 1 /*a multiple of*/ << 64 << NumElementsArg * ElementBitCount;
2794 return true;
2795 }
2796
2797 // ensure first arg and second arg have the same type
2798 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2799 return true;
2800
2801 ExprResult A = TheCall->getArg(0);
2802 QualType ArgTyA = A.get()->getType();
2803 // return type is the same as the input type
2804 TheCall->setType(ArgTyA);
2805 break;
2806 }
2807 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2808 if (SemaRef.checkArgCount(TheCall, 2) ||
2809 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2810 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
2812 return true;
2813
2814 auto *ResourceTy =
2816 QualType ContainedTy = ResourceTy->getContainedType();
2817 auto ReturnType =
2819 ReturnType = SemaRef.Context.getPointerType(ReturnType);
2820 TheCall->setType(ReturnType);
2821 TheCall->setValueKind(VK_LValue);
2822
2823 break;
2824 }
2825 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2826 if (SemaRef.checkArgCount(TheCall, 1) ||
2827 CheckResourceHandle(&SemaRef, TheCall, 0))
2828 return true;
2829 // use the type of the handle (arg0) as a return type
2830 QualType ResourceTy = TheCall->getArg(0)->getType();
2831 TheCall->setType(ResourceTy);
2832 break;
2833 }
2834 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2836 if (SemaRef.checkArgCount(TheCall, 6) ||
2837 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2838 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
2839 CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
2840 CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
2841 CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
2842 CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
2843 AST.getPointerType(AST.CharTy.withConst())))
2844 return true;
2845 // use the type of the handle (arg0) as a return type
2846 QualType ResourceTy = TheCall->getArg(0)->getType();
2847 TheCall->setType(ResourceTy);
2848 break;
2849 }
2850 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2852 if (SemaRef.checkArgCount(TheCall, 6) ||
2853 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2854 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
2855 CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.IntTy) ||
2856 CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.UnsignedIntTy) ||
2857 CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
2858 CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
2859 AST.getPointerType(AST.CharTy.withConst())))
2860 return true;
2861 // use the type of the handle (arg0) as a return type
2862 QualType ResourceTy = TheCall->getArg(0)->getType();
2863 TheCall->setType(ResourceTy);
2864 break;
2865 }
2866 case Builtin::BI__builtin_hlsl_and:
2867 case Builtin::BI__builtin_hlsl_or: {
2868 if (SemaRef.checkArgCount(TheCall, 2))
2869 return true;
2870 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
2871 return true;
2872 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2873 return true;
2874
2875 ExprResult A = TheCall->getArg(0);
2876 QualType ArgTyA = A.get()->getType();
2877 // return type is the same as the input type
2878 TheCall->setType(ArgTyA);
2879 break;
2880 }
2881 case Builtin::BI__builtin_hlsl_all:
2882 case Builtin::BI__builtin_hlsl_any: {
2883 if (SemaRef.checkArgCount(TheCall, 1))
2884 return true;
2885 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
2886 return true;
2887 break;
2888 }
2889 case Builtin::BI__builtin_hlsl_asdouble: {
2890 if (SemaRef.checkArgCount(TheCall, 2))
2891 return true;
2893 &SemaRef, TheCall,
2894 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
2895 /* arg index */ 0))
2896 return true;
2898 &SemaRef, TheCall,
2899 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
2900 /* arg index */ 1))
2901 return true;
2902 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2903 return true;
2904
2905 SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().DoubleTy);
2906 break;
2907 }
2908 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
2910 TheCall, /*ArgTyRestr=*/
2912 return true;
2913 break;
2914 }
2915 case Builtin::BI__builtin_hlsl_dot: {
2916 // arg count is checked by BuiltinVectorToScalarMath
2918 return true;
2920 return true;
2921 break;
2922 }
2923 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
2924 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
2926 return true;
2927
2928 const Expr *Arg = TheCall->getArg(0);
2929 QualType ArgTy = Arg->getType();
2930 QualType EltTy = ArgTy;
2931
2933
2934 if (auto *VecTy = EltTy->getAs<VectorType>()) {
2935 EltTy = VecTy->getElementType();
2936 ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
2937 }
2938
2939 if (!EltTy->isIntegerType()) {
2940 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2941 << 1 << /* scalar or vector of */ 5 << /* integer ty */ 1
2942 << /* no fp */ 0 << ArgTy;
2943 return true;
2944 }
2945
2946 TheCall->setType(ResTy);
2947 break;
2948 }
2949 case Builtin::BI__builtin_hlsl_select: {
2950 if (SemaRef.checkArgCount(TheCall, 3))
2951 return true;
2952 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
2953 return true;
2954 QualType ArgTy = TheCall->getArg(0)->getType();
2955 if (ArgTy->isBooleanType() && CheckBoolSelect(&SemaRef, TheCall))
2956 return true;
2957 auto *VTy = ArgTy->getAs<VectorType>();
2958 if (VTy && VTy->getElementType()->isBooleanType() &&
2959 CheckVectorSelect(&SemaRef, TheCall))
2960 return true;
2961 break;
2962 }
2963 case Builtin::BI__builtin_hlsl_elementwise_saturate:
2964 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
2965 if (SemaRef.checkArgCount(TheCall, 1))
2966 return true;
2967 if (!TheCall->getArg(0)
2968 ->getType()
2969 ->hasFloatingRepresentation()) // half or float or double
2970 return SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
2971 diag::err_builtin_invalid_arg_type)
2972 << /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0
2973 << /* fp */ 1 << TheCall->getArg(0)->getType();
2975 return true;
2976 break;
2977 }
2978 case Builtin::BI__builtin_hlsl_elementwise_degrees:
2979 case Builtin::BI__builtin_hlsl_elementwise_radians:
2980 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
2981 case Builtin::BI__builtin_hlsl_elementwise_frac: {
2982 if (SemaRef.checkArgCount(TheCall, 1))
2983 return true;
2984 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
2986 return true;
2988 return true;
2989 break;
2990 }
2991 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
2992 if (SemaRef.checkArgCount(TheCall, 1))
2993 return true;
2994 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
2996 return true;
2998 return true;
3000 break;
3001 }
3002 case Builtin::BI__builtin_hlsl_lerp: {
3003 if (SemaRef.checkArgCount(TheCall, 3))
3004 return true;
3005 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3007 return true;
3008 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3009 return true;
3011 return true;
3012 break;
3013 }
3014 case Builtin::BI__builtin_hlsl_mad: {
3016 TheCall, /*ArgTyRestr=*/
3018 return true;
3019 break;
3020 }
3021 case Builtin::BI__builtin_hlsl_normalize: {
3022 if (SemaRef.checkArgCount(TheCall, 1))
3023 return true;
3024 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3026 return true;
3027 ExprResult A = TheCall->getArg(0);
3028 QualType ArgTyA = A.get()->getType();
3029 // return type is the same as the input type
3030 TheCall->setType(ArgTyA);
3031 break;
3032 }
3033 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3035 return true;
3036 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3038 return true;
3040 break;
3041 }
3042 case Builtin::BI__builtin_hlsl_step: {
3043 if (SemaRef.checkArgCount(TheCall, 2))
3044 return true;
3045 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3047 return true;
3048
3049 ExprResult A = TheCall->getArg(0);
3050 QualType ArgTyA = A.get()->getType();
3051 // return type is the same as the input type
3052 TheCall->setType(ArgTyA);
3053 break;
3054 }
3055 case Builtin::BI__builtin_hlsl_wave_active_max:
3056 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3057 if (SemaRef.checkArgCount(TheCall, 1))
3058 return true;
3059
3060 // Ensure input expr type is a scalar/vector and the same as the return type
3061 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3062 return true;
3063 if (CheckWaveActive(&SemaRef, TheCall))
3064 return true;
3065 ExprResult Expr = TheCall->getArg(0);
3066 QualType ArgTyExpr = Expr.get()->getType();
3067 TheCall->setType(ArgTyExpr);
3068 break;
3069 }
3070 // Note these are llvm builtins that we want to catch invalid intrinsic
3071 // generation. Normal handling of these builitns will occur elsewhere.
3072 case Builtin::BI__builtin_elementwise_bitreverse: {
3073 // does not include a check for number of arguments
3074 // because that is done previously
3075 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3077 return true;
3078 break;
3079 }
3080 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3081 if (SemaRef.checkArgCount(TheCall, 2))
3082 return true;
3083
3084 // Ensure index parameter type can be interpreted as a uint
3085 ExprResult Index = TheCall->getArg(1);
3086 QualType ArgTyIndex = Index.get()->getType();
3087 if (!ArgTyIndex->isIntegerType()) {
3088 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3089 diag::err_typecheck_convert_incompatible)
3090 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3091 return true;
3092 }
3093
3094 // Ensure input expr type is a scalar/vector and the same as the return type
3095 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3096 return true;
3097
3098 ExprResult Expr = TheCall->getArg(0);
3099 QualType ArgTyExpr = Expr.get()->getType();
3100 TheCall->setType(ArgTyExpr);
3101 break;
3102 }
3103 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3104 if (SemaRef.checkArgCount(TheCall, 0))
3105 return true;
3106 break;
3107 }
3108 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3109 if (SemaRef.checkArgCount(TheCall, 3))
3110 return true;
3111
3112 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.DoubleTy, 0) ||
3114 1) ||
3116 2))
3117 return true;
3118
3119 if (CheckModifiableLValue(&SemaRef, TheCall, 1) ||
3120 CheckModifiableLValue(&SemaRef, TheCall, 2))
3121 return true;
3122 break;
3123 }
3124 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3125 if (SemaRef.checkArgCount(TheCall, 1))
3126 return true;
3127
3129 return true;
3130 break;
3131 }
3132 case Builtin::BI__builtin_elementwise_acos:
3133 case Builtin::BI__builtin_elementwise_asin:
3134 case Builtin::BI__builtin_elementwise_atan:
3135 case Builtin::BI__builtin_elementwise_atan2:
3136 case Builtin::BI__builtin_elementwise_ceil:
3137 case Builtin::BI__builtin_elementwise_cos:
3138 case Builtin::BI__builtin_elementwise_cosh:
3139 case Builtin::BI__builtin_elementwise_exp:
3140 case Builtin::BI__builtin_elementwise_exp2:
3141 case Builtin::BI__builtin_elementwise_exp10:
3142 case Builtin::BI__builtin_elementwise_floor:
3143 case Builtin::BI__builtin_elementwise_fmod:
3144 case Builtin::BI__builtin_elementwise_log:
3145 case Builtin::BI__builtin_elementwise_log2:
3146 case Builtin::BI__builtin_elementwise_log10:
3147 case Builtin::BI__builtin_elementwise_pow:
3148 case Builtin::BI__builtin_elementwise_roundeven:
3149 case Builtin::BI__builtin_elementwise_sin:
3150 case Builtin::BI__builtin_elementwise_sinh:
3151 case Builtin::BI__builtin_elementwise_sqrt:
3152 case Builtin::BI__builtin_elementwise_tan:
3153 case Builtin::BI__builtin_elementwise_tanh:
3154 case Builtin::BI__builtin_elementwise_trunc: {
3155 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3157 return true;
3158 break;
3159 }
3160 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3161 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
3162 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3163 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3164 };
3165 if (SemaRef.checkArgCount(TheCall, 2) ||
3166 CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy) ||
3167 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
3169 return true;
3170 Expr *OffsetExpr = TheCall->getArg(1);
3171 std::optional<llvm::APSInt> Offset =
3173 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
3174 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3175 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3176 << 1;
3177 return true;
3178 }
3179 break;
3180 }
3181 }
3182 return false;
3183}
3184
3188 WorkList.push_back(BaseTy);
3189 while (!WorkList.empty()) {
3190 QualType T = WorkList.pop_back_val();
3191 T = T.getCanonicalType().getUnqualifiedType();
3192 assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
3193 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3194 llvm::SmallVector<QualType, 16> ElementFields;
3195 // Generally I've avoided recursion in this algorithm, but arrays of
3196 // structs could be time-consuming to flatten and churn through on the
3197 // work list. Hopefully nesting arrays of structs containing arrays
3198 // of structs too many levels deep is unlikely.
3199 BuildFlattenedTypeList(AT->getElementType(), ElementFields);
3200 // Repeat the element's field list n times.
3201 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3202 llvm::append_range(List, ElementFields);
3203 continue;
3204 }
3205 // Vectors can only have element types that are builtin types, so this can
3206 // add directly to the list instead of to the WorkList.
3207 if (const auto *VT = dyn_cast<VectorType>(T)) {
3208 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3209 continue;
3210 }
3211 if (const auto *RD = T->getAsCXXRecordDecl()) {
3212 if (RD->isStandardLayout())
3213 RD = RD->getStandardLayoutBaseWithFields();
3214
3215 // For types that we shouldn't decompose (unions and non-aggregates), just
3216 // add the type itself to the list.
3217 if (RD->isUnion() || !RD->isAggregate()) {
3218 List.push_back(T);
3219 continue;
3220 }
3221
3223 for (const auto *FD : RD->fields())
3224 FieldTypes.push_back(FD->getType());
3225 // Reverse the newly added sub-range.
3226 std::reverse(FieldTypes.begin(), FieldTypes.end());
3227 llvm::append_range(WorkList, FieldTypes);
3228
3229 // If this wasn't a standard layout type we may also have some base
3230 // classes to deal with.
3231 if (!RD->isStandardLayout()) {
3232 FieldTypes.clear();
3233 for (const auto &Base : RD->bases())
3234 FieldTypes.push_back(Base.getType());
3235 std::reverse(FieldTypes.begin(), FieldTypes.end());
3236 llvm::append_range(WorkList, FieldTypes);
3237 }
3238 continue;
3239 }
3240 List.push_back(T);
3241 }
3242}
3243
3245 // null and array types are not allowed.
3246 if (QT.isNull() || QT->isArrayType())
3247 return false;
3248
3249 // UDT types are not allowed
3250 if (QT->isRecordType())
3251 return false;
3252
3253 if (QT->isBooleanType() || QT->isEnumeralType())
3254 return false;
3255
3256 // the only other valid builtin types are scalars or vectors
3257 if (QT->isArithmeticType()) {
3258 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3259 return false;
3260 return true;
3261 }
3262
3263 if (const VectorType *VT = QT->getAs<VectorType>()) {
3264 int ArraySize = VT->getNumElements();
3265
3266 if (ArraySize > 4)
3267 return false;
3268
3269 QualType ElTy = VT->getElementType();
3270 if (ElTy->isBooleanType())
3271 return false;
3272
3273 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3274 return false;
3275 return true;
3276 }
3277
3278 return false;
3279}
3280
3282 if (T1.isNull() || T2.isNull())
3283 return false;
3284
3287
3288 // If both types are the same canonical type, they're obviously compatible.
3289 if (SemaRef.getASTContext().hasSameType(T1, T2))
3290 return true;
3291
3293 BuildFlattenedTypeList(T1, T1Types);
3295 BuildFlattenedTypeList(T2, T2Types);
3296
3297 // Check the flattened type list
3298 return llvm::equal(T1Types, T2Types,
3299 [this](QualType LHS, QualType RHS) -> bool {
3300 return SemaRef.IsLayoutCompatible(LHS, RHS);
3301 });
3302}
3303
3305 FunctionDecl *Old) {
3306 if (New->getNumParams() != Old->getNumParams())
3307 return true;
3308
3309 bool HadError = false;
3310
3311 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
3312 ParmVarDecl *NewParam = New->getParamDecl(i);
3313 ParmVarDecl *OldParam = Old->getParamDecl(i);
3314
3315 // HLSL parameter declarations for inout and out must match between
3316 // declarations. In HLSL inout and out are ambiguous at the call site,
3317 // but have different calling behavior, so you cannot overload a
3318 // method based on a difference between inout and out annotations.
3319 const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>();
3320 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3321 const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>();
3322 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3323
3324 if (NSpellingIdx != OSpellingIdx) {
3325 SemaRef.Diag(NewParam->getLocation(),
3326 diag::err_hlsl_param_qualifier_mismatch)
3327 << NDAttr << NewParam;
3328 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
3329 << ODAttr;
3330 HadError = true;
3331 }
3332 }
3333 return HadError;
3334}
3335
3336// Generally follows PerformScalarCast, with cases reordered for
3337// clarity of what types are supported
3339
3340 if (!SrcTy->isScalarType() || !DestTy->isScalarType())
3341 return false;
3342
3343 if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3344 return true;
3345
3346 switch (SrcTy->getScalarTypeKind()) {
3347 case Type::STK_Bool: // casting from bool is like casting from an integer
3348 case Type::STK_Integral:
3349 switch (DestTy->getScalarTypeKind()) {
3350 case Type::STK_Bool:
3351 case Type::STK_Integral:
3352 case Type::STK_Floating:
3353 return true;
3354 case Type::STK_CPointer:
3358 llvm_unreachable("HLSL doesn't support pointers.");
3361 llvm_unreachable("HLSL doesn't support complex types.");
3363 llvm_unreachable("HLSL doesn't support fixed point types.");
3364 }
3365 llvm_unreachable("Should have returned before this");
3366
3367 case Type::STK_Floating:
3368 switch (DestTy->getScalarTypeKind()) {
3369 case Type::STK_Floating:
3370 case Type::STK_Bool:
3371 case Type::STK_Integral:
3372 return true;
3375 llvm_unreachable("HLSL doesn't support complex types.");
3377 llvm_unreachable("HLSL doesn't support fixed point types.");
3378 case Type::STK_CPointer:
3382 llvm_unreachable("HLSL doesn't support pointers.");
3383 }
3384 llvm_unreachable("Should have returned before this");
3385
3387 case Type::STK_CPointer:
3390 llvm_unreachable("HLSL doesn't support pointers.");
3391
3393 llvm_unreachable("HLSL doesn't support fixed point types.");
3394
3397 llvm_unreachable("HLSL doesn't support complex types.");
3398 }
3399
3400 llvm_unreachable("Unhandled scalar cast");
3401}
3402
3403// Detect if a type contains a bitfield. Will be removed when
3404// bitfield support is added to HLSLElementwiseCast and HLSLAggregateSplatCast
3407 WorkList.push_back(BaseTy);
3408 while (!WorkList.empty()) {
3409 QualType T = WorkList.pop_back_val();
3410 T = T.getCanonicalType().getUnqualifiedType();
3411 // only check aggregate types
3412 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3413 WorkList.push_back(AT->getElementType());
3414 continue;
3415 }
3416 if (const auto *RT = dyn_cast<RecordType>(T)) {
3417 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3418 if (RD->isUnion())
3419 continue;
3420
3421 const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(RD);
3422
3423 if (CXXD && CXXD->isStandardLayout())
3425
3426 for (const auto *FD : RD->fields()) {
3427 if (FD->isBitField())
3428 return true;
3429 WorkList.push_back(FD->getType());
3430 }
3431 continue;
3432 }
3433 }
3434 return false;
3435}
3436
3437// Can perform an HLSL Aggregate splat cast if the Dest is an aggregate and the
3438// Src is a scalar or a vector of length 1
3439// Or if Dest is a vector and Src is a vector of length 1
3441
3442 QualType SrcTy = Src->getType();
3443 // Not a valid HLSL Aggregate Splat cast if Dest is a scalar or if this is
3444 // going to be a vector splat from a scalar.
3445 if ((SrcTy->isScalarType() && DestTy->isVectorType()) ||
3446 DestTy->isScalarType())
3447 return false;
3448
3449 const VectorType *SrcVecTy = SrcTy->getAs<VectorType>();
3450
3451 // Src isn't a scalar or a vector of length 1
3452 if (!SrcTy->isScalarType() && !(SrcVecTy && SrcVecTy->getNumElements() == 1))
3453 return false;
3454
3455 if (SrcVecTy)
3456 SrcTy = SrcVecTy->getElementType();
3457
3458 if (ContainsBitField(DestTy))
3459 return false;
3460
3462 BuildFlattenedTypeList(DestTy, DestTypes);
3463
3464 for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3465 if (DestTypes[I]->isUnionType())
3466 return false;
3467 if (!CanPerformScalarCast(SrcTy, DestTypes[I]))
3468 return false;
3469 }
3470 return true;
3471}
3472
3473// Can we perform an HLSL Elementwise cast?
3474// TODO: update this code when matrices are added; see issue #88060
3476
3477 // Don't handle casts where LHS and RHS are any combination of scalar/vector
3478 // There must be an aggregate somewhere
3479 QualType SrcTy = Src->getType();
3480 if (SrcTy->isScalarType()) // always a splat and this cast doesn't handle that
3481 return false;
3482
3483 if (SrcTy->isVectorType() &&
3484 (DestTy->isScalarType() || DestTy->isVectorType()))
3485 return false;
3486
3487 if (ContainsBitField(DestTy) || ContainsBitField(SrcTy))
3488 return false;
3489
3491 BuildFlattenedTypeList(DestTy, DestTypes);
3493 BuildFlattenedTypeList(SrcTy, SrcTypes);
3494
3495 // Usually the size of SrcTypes must be greater than or equal to the size of
3496 // DestTypes.
3497 if (SrcTypes.size() < DestTypes.size())
3498 return false;
3499
3500 unsigned SrcSize = SrcTypes.size();
3501 unsigned DstSize = DestTypes.size();
3502 unsigned I;
3503 for (I = 0; I < DstSize && I < SrcSize; I++) {
3504 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3505 return false;
3506 if (!CanPerformScalarCast(SrcTypes[I], DestTypes[I])) {
3507 return false;
3508 }
3509 }
3510
3511 // check the rest of the source type for unions.
3512 for (; I < SrcSize; I++) {
3513 if (SrcTypes[I]->isUnionType())
3514 return false;
3515 }
3516 return true;
3517}
3518
3520 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3521 "We should not get here without a parameter modifier expression");
3522 const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();
3523 if (Attr->getABI() == ParameterABI::Ordinary)
3524 return ExprResult(Arg);
3525
3526 bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut;
3527 if (!Arg->isLValue()) {
3528 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue)
3529 << Arg << (IsInOut ? 1 : 0);
3530 return ExprError();
3531 }
3532
3534
3535 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3536
3537 // HLSL allows implicit conversions from scalars to vectors, but not the
3538 // inverse, so we need to disallow `inout` with scalar->vector or
3539 // scalar->matrix conversions.
3540 if (Arg->getType()->isScalarType() != Ty->isScalarType()) {
3541 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)
3542 << Arg << (IsInOut ? 1 : 0);
3543 return ExprError();
3544 }
3545
3546 auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), Arg->getType(),
3547 VK_LValue, OK_Ordinary, Arg);
3548
3549 // Parameters are initialized via copy initialization. This allows for
3550 // overload resolution of argument constructors.
3551 InitializedEntity Entity =
3553 ExprResult Res =
3554 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3555 if (Res.isInvalid())
3556 return ExprError();
3557 Expr *Base = Res.get();
3558 // After the cast, drop the reference type when creating the exprs.
3559 Ty = Ty.getNonLValueExprType(Ctx);
3560 auto *OpV = new (Ctx)
3562
3563 // Writebacks are performed with `=` binary operator, which allows for
3564 // overload resolution on writeback result expressions.
3566 tok::equal, ArgOpV, OpV);
3567
3568 if (Res.isInvalid())
3569 return ExprError();
3570 Expr *Writeback = Res.get();
3571 auto *OutExpr =
3572 HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
3573
3574 return ExprResult(OutExpr);
3575}
3576
3578 // If HLSL gains support for references, all the cites that use this will need
3579 // to be updated with semantic checking to produce errors for
3580 // pointers/references.
3581 assert(!Ty->isReferenceType() &&
3582 "Pointer and reference types cannot be inout or out parameters");
3584 Ty.addRestrict();
3585 return Ty;
3586}
3587
3589 QualType QT = VD->getType();
3590 return VD->getDeclContext()->isTranslationUnit() &&
3592 VD->getStorageClass() != SC_Static &&
3593 !VD->hasAttr<HLSLVkConstantIdAttr>() &&
3595}
3596
3598 // The variable already has an address space (groupshared for ex).
3599 if (Decl->getType().hasAddressSpace())
3600 return;
3601
3602 if (Decl->getType()->isDependentType())
3603 return;
3604
3605 QualType Type = Decl->getType();
3606
3607 if (Decl->hasAttr<HLSLVkExtBuiltinInputAttr>()) {
3608 LangAS ImplAS = LangAS::hlsl_input;
3610 Decl->setType(Type);
3611 return;
3612 }
3613
3614 if (Type->isSamplerT() || Type->isVoidType())
3615 return;
3616
3617 // Resource handles.
3619 return;
3620
3621 // Only static globals belong to the Private address space.
3622 // Non-static globals belongs to the cbuffer.
3623 if (Decl->getStorageClass() != SC_Static && !Decl->isStaticDataMember())
3624 return;
3625
3628 Decl->setType(Type);
3629}
3630
3632 if (VD->hasGlobalStorage()) {
3633 // make sure the declaration has a complete type
3635 VD->getLocation(),
3637 diag::err_typecheck_decl_incomplete_type)) {
3638 VD->setInvalidDecl();
3640 return;
3641 }
3642
3643 // Global variables outside a cbuffer block that are not a resource, static,
3644 // groupshared, or an empty array or struct belong to the default constant
3645 // buffer $Globals (to be created at the end of the translation unit).
3647 // update address space to hlsl_constant
3650 VD->setType(NewTy);
3651 DefaultCBufferDecls.push_back(VD);
3652 }
3653
3654 // find all resources bindings on decl
3655 if (VD->getType()->isHLSLIntangibleType())
3656 collectResourceBindingsOnVarDecl(VD);
3657
3659 VD->hasAttr<HLSLVkConstantIdAttr>()) {
3660 // Make the variable for resources static. The global externally visible
3661 // storage is accessed through the handle, which is a member. The variable
3662 // itself is not externally visible.
3664 }
3665
3666 // process explicit bindings
3667 processExplicitBindingsOnDecl(VD);
3668
3669 if (VD->getType()->isHLSLResourceRecordArray()) {
3670 // If the resource array does not have an explicit binding attribute,
3671 // create an implicit one. It will be used to transfer implicit binding
3672 // order_ID to codegen.
3673 if (!VD->hasAttr<HLSLVkBindingAttr>()) {
3674 HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3675 if (!RBA || !RBA->hasRegisterSlot()) {
3676 uint32_t OrderID = getNextImplicitBindingOrderID();
3677 if (RBA)
3678 RBA->setImplicitBindingOrderID(OrderID);
3679 else
3682 OrderID);
3683 }
3684 }
3685 }
3686 }
3687
3689}
3690
3696
3697 InitializationSequence InitSeq(S, Entity, Kind, Args);
3698 if (InitSeq.Failed())
3699 return false;
3700
3701 ExprResult Init = InitSeq.Perform(S, Entity, Kind, Args);
3702 if (!Init.get())
3703 return false;
3704
3708 return true;
3709}
3710
3711void SemaHLSL::createResourceRecordCtorArgs(
3712 const Type *ResourceTy, StringRef VarName, HLSLResourceBindingAttr *RBA,
3713 HLSLVkBindingAttr *VkBinding, uint32_t ArrayIndex,
3715 std::optional<uint32_t> RegisterSlot;
3716 uint32_t SpaceNo = 0;
3717 if (VkBinding) {
3718 RegisterSlot = VkBinding->getBinding();
3719 SpaceNo = VkBinding->getSet();
3720 } else if (RBA) {
3721 if (RBA->hasRegisterSlot())
3722 RegisterSlot = RBA->getSlotNumber();
3723 SpaceNo = RBA->getSpaceNumber();
3724 }
3725
3727 uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
3728 uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
3730 AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
3731 IntegerLiteral *Index =
3732 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, ArrayIndex),
3734 IntegerLiteral *Space =
3735 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo),
3738 AST, VarName, StringLiteralKind::Ordinary, false,
3739 AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
3740 SourceLocation());
3741
3742 // resource with explicit binding
3743 if (RegisterSlot.has_value()) {
3745 AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy,
3746 SourceLocation());
3747 Args.append({RegSlot, Space, RangeSize, Index, Name});
3748 } else {
3749 // resource with implicit binding
3750 uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
3751 ? RBA->getImplicitBindingOrderID()
3752 : getNextImplicitBindingOrderID();
3753 IntegerLiteral *OrderId =
3754 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
3756 Args.append({Space, RangeSize, Index, OrderId, Name});
3757 }
3758}
3759
3760bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
3762 createResourceRecordCtorArgs(VD->getType().getTypePtr(), VD->getName(),
3763 VD->getAttr<HLSLResourceBindingAttr>(),
3764 VD->getAttr<HLSLVkBindingAttr>(), 0, Args);
3765 return initVarDeclWithCtor(SemaRef, VD, Args);
3766}
3767
3768bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
3769 assert(VD->getType()->isHLSLResourceRecordArray() &&
3770 "expected array of resource records");
3771
3772 // Individual resources in a resource array are not initialized here. They
3773 // are initialized later on during codegen when the individual resources are
3774 // accessed. Codegen will emit a call to the resource constructor with the
3775 // specified array index. We need to make sure though that the constructor
3776 // for the specific resource type is instantiated, so codegen can emit a call
3777 // to it when the array element is accessed.
3779 QualType ResElementTy = VD->getASTContext().getBaseElementType(VD->getType());
3780 createResourceRecordCtorArgs(ResElementTy.getTypePtr(), VD->getName(),
3781 VD->getAttr<HLSLResourceBindingAttr>(),
3782 VD->getAttr<HLSLVkBindingAttr>(), 0, Args);
3783
3785 InitializedEntity Entity =
3788 InitializationSequence InitSeq(SemaRef, Entity, Kind, Args);
3789 if (InitSeq.Failed())
3790 return false;
3791
3792 // This takes care of instantiating and emitting of the constructor that will
3793 // be called from codegen when the array is accessed.
3794 ExprResult OneResInit = InitSeq.Perform(SemaRef, Entity, Kind, Args);
3795 return !OneResInit.isInvalid();
3796}
3797
3798// Returns true if the initialization has been handled.
3799// Returns false to use default initialization.
3801 // Objects in the hlsl_constant address space are initialized
3802 // externally, so don't synthesize an implicit initializer.
3804 return true;
3805
3806 // Initialize resources at the global scope
3807 if (VD->hasGlobalStorage()) {
3808 const Type *Ty = VD->getType().getTypePtr();
3809 if (Ty->isHLSLResourceRecord())
3810 return initGlobalResourceDecl(VD);
3811 if (Ty->isHLSLResourceRecordArray())
3812 return initGlobalResourceArrayDecl(VD);
3813 }
3814 return false;
3815}
3816
3817// Walks though the global variable declaration, collects all resource binding
3818// requirements and adds them to Bindings
3819void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {
3820 assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() &&
3821 "expected global variable that contains HLSL resource");
3822
3823 // Cbuffers and Tbuffers are HLSLBufferDecl types
3824 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3825 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3826 ? ResourceClass::CBuffer
3827 : ResourceClass::SRV);
3828 return;
3829 }
3830
3831 // Unwrap arrays
3832 // FIXME: Calculate array size while unwrapping
3833 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
3834 while (Ty->isConstantArrayType()) {
3835 const ConstantArrayType *CAT = cast<ConstantArrayType>(Ty);
3837 }
3838
3839 // Resource (or array of resources)
3840 if (const HLSLAttributedResourceType *AttrResType =
3842 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
3843 return;
3844 }
3845
3846 // User defined record type
3847 if (const RecordType *RT = dyn_cast<RecordType>(Ty))
3848 collectResourceBindingsOnUserRecordDecl(VD, RT);
3849}
3850
3851// Walks though the explicit resource binding attributes on the declaration,
3852// and makes sure there is a resource that matched the binding and updates
3853// DeclBindingInfoLists
3854void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
3855 assert(VD->hasGlobalStorage() && "expected global variable");
3856
3857 bool HasBinding = false;
3858 for (Attr *A : VD->attrs()) {
3859 if (isa<HLSLVkBindingAttr>(A))
3860 HasBinding = true;
3861
3862 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
3863 if (!RBA || !RBA->hasRegisterSlot())
3864 continue;
3865 HasBinding = true;
3866
3867 RegisterType RT = RBA->getRegisterType();
3868 assert(RT != RegisterType::I && "invalid or obsolete register type should "
3869 "never have an attribute created");
3870
3871 if (RT == RegisterType::C) {
3872 if (Bindings.hasBindingInfoForDecl(VD))
3873 SemaRef.Diag(VD->getLocation(),
3874 diag::warn_hlsl_user_defined_type_missing_member)
3875 << static_cast<int>(RT);
3876 continue;
3877 }
3878
3879 // Find DeclBindingInfo for this binding and update it, or report error
3880 // if it does not exist (user type does to contain resources with the
3881 // expected resource class).
3883 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
3884 // update binding info
3885 BI->setBindingAttribute(RBA, BindingType::Explicit);
3886 } else {
3887 SemaRef.Diag(VD->getLocation(),
3888 diag::warn_hlsl_user_defined_type_missing_member)
3889 << static_cast<int>(RT);
3890 }
3891 }
3892
3893 if (!HasBinding && isResourceRecordTypeOrArrayOf(VD))
3894 SemaRef.Diag(VD->getLocation(), diag::warn_hlsl_implicit_binding);
3895}
3896namespace {
3897class InitListTransformer {
3898 Sema &S;
3899 ASTContext &Ctx;
3900 QualType InitTy;
3901 QualType *DstIt = nullptr;
3902 Expr **ArgIt = nullptr;
3903 // Is wrapping the destination type iterator required? This is only used for
3904 // incomplete array types where we loop over the destination type since we
3905 // don't know the full number of elements from the declaration.
3906 bool Wrap;
3907
3908 bool castInitializer(Expr *E) {
3909 assert(DstIt && "This should always be something!");
3910 if (DstIt == DestTypes.end()) {
3911 if (!Wrap) {
3912 ArgExprs.push_back(E);
3913 // This is odd, but it isn't technically a failure due to conversion, we
3914 // handle mismatched counts of arguments differently.
3915 return true;
3916 }
3917 DstIt = DestTypes.begin();
3918 }
3920 Ctx, *DstIt, /* Consumed (ObjC) */ false);
3921 ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
3922 if (Res.isInvalid())
3923 return false;
3924 Expr *Init = Res.get();
3925 ArgExprs.push_back(Init);
3926 DstIt++;
3927 return true;
3928 }
3929
3930 bool buildInitializerListImpl(Expr *E) {
3931 // If this is an initialization list, traverse the sub initializers.
3932 if (auto *Init = dyn_cast<InitListExpr>(E)) {
3933 for (auto *SubInit : Init->inits())
3934 if (!buildInitializerListImpl(SubInit))
3935 return false;
3936 return true;
3937 }
3938
3939 // If this is a scalar type, just enqueue the expression.
3940 QualType Ty = E->getType();
3941
3942 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
3943 return castInitializer(E);
3944
3945 if (auto *VecTy = Ty->getAs<VectorType>()) {
3946 uint64_t Size = VecTy->getNumElements();
3947
3948 QualType SizeTy = Ctx.getSizeType();
3949 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
3950 for (uint64_t I = 0; I < Size; ++I) {
3951 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
3952 SizeTy, SourceLocation());
3953
3955 E, E->getBeginLoc(), Idx, E->getEndLoc());
3956 if (ElExpr.isInvalid())
3957 return false;
3958 if (!castInitializer(ElExpr.get()))
3959 return false;
3960 }
3961 return true;
3962 }
3963
3964 if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {
3965 uint64_t Size = ArrTy->getZExtSize();
3966 QualType SizeTy = Ctx.getSizeType();
3967 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
3968 for (uint64_t I = 0; I < Size; ++I) {
3969 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
3970 SizeTy, SourceLocation());
3972 E, E->getBeginLoc(), Idx, E->getEndLoc());
3973 if (ElExpr.isInvalid())
3974 return false;
3975 if (!buildInitializerListImpl(ElExpr.get()))
3976 return false;
3977 }
3978 return true;
3979 }
3980
3981 if (auto *RD = Ty->getAsCXXRecordDecl()) {
3983 RecordDecls.push_back(RD);
3984 while (RecordDecls.back()->getNumBases()) {
3985 CXXRecordDecl *D = RecordDecls.back();
3986 assert(D->getNumBases() == 1 &&
3987 "HLSL doesn't support multiple inheritance");
3988 RecordDecls.push_back(
3989 D->bases_begin()->getType()->castAsCXXRecordDecl());
3990 }
3991 while (!RecordDecls.empty()) {
3992 CXXRecordDecl *RD = RecordDecls.pop_back_val();
3993 for (auto *FD : RD->fields()) {
3995 DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
3997 E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
3998 if (Res.isInvalid())
3999 return false;
4000 if (!buildInitializerListImpl(Res.get()))
4001 return false;
4002 }
4003 }
4004 }
4005 return true;
4006 }
4007
4008 Expr *generateInitListsImpl(QualType Ty) {
4009 assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");
4010 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4011 return *(ArgIt++);
4012
4014 assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL");
4015 Ty = Ty.getDesugaredType(Ctx);
4016 if (Ty->isVectorType() || Ty->isConstantArrayType()) {
4017 QualType ElTy;
4018 uint64_t Size = 0;
4019 if (auto *ATy = Ty->getAs<VectorType>()) {
4020 ElTy = ATy->getElementType();
4021 Size = ATy->getNumElements();
4022 } else {
4023 auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());
4024 ElTy = VTy->getElementType();
4025 Size = VTy->getZExtSize();
4026 }
4027 for (uint64_t I = 0; I < Size; ++I)
4028 Inits.push_back(generateInitListsImpl(ElTy));
4029 }
4030 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4032 RecordDecls.push_back(RD);
4033 while (RecordDecls.back()->getNumBases()) {
4034 CXXRecordDecl *D = RecordDecls.back();
4035 assert(D->getNumBases() == 1 &&
4036 "HLSL doesn't support multiple inheritance");
4037 RecordDecls.push_back(
4038 D->bases_begin()->getType()->castAsCXXRecordDecl());
4039 }
4040 while (!RecordDecls.empty()) {
4041 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4042 for (auto *FD : RD->fields())
4043 Inits.push_back(generateInitListsImpl(FD->getType()));
4044 }
4045 }
4046 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4047 Inits, Inits.back()->getEndLoc());
4048 NewInit->setType(Ty);
4049 return NewInit;
4050 }
4051
4052public:
4055 InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)
4056 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4057 Wrap(Entity.getType()->isIncompleteArrayType()) {
4058 InitTy = Entity.getType().getNonReferenceType();
4059 // When we're generating initializer lists for incomplete array types we
4060 // need to wrap around both when building the initializers and when
4061 // generating the final initializer lists.
4062 if (Wrap) {
4063 assert(InitTy->isIncompleteArrayType());
4064 const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType(InitTy);
4065 InitTy = IAT->getElementType();
4066 }
4067 BuildFlattenedTypeList(InitTy, DestTypes);
4068 DstIt = DestTypes.begin();
4069 }
4070
4071 bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }
4072
4073 Expr *generateInitLists() {
4074 assert(!ArgExprs.empty() &&
4075 "Call buildInitializerList to generate argument expressions.");
4076 ArgIt = ArgExprs.begin();
4077 if (!Wrap)
4078 return generateInitListsImpl(InitTy);
4080 while (ArgIt != ArgExprs.end())
4081 Inits.push_back(generateInitListsImpl(InitTy));
4082
4083 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4084 Inits, Inits.back()->getEndLoc());
4085 llvm::APInt ArySize(64, Inits.size());
4086 NewInit->setType(Ctx.getConstantArrayType(InitTy, ArySize, nullptr,
4087 ArraySizeModifier::Normal, 0));
4088 return NewInit;
4089 }
4090};
4091} // namespace
4092
4094 InitListExpr *Init) {
4095 // If the initializer is a scalar, just return it.
4096 if (Init->getType()->isScalarType())
4097 return true;
4099 InitListTransformer ILT(SemaRef, Entity);
4100
4101 for (unsigned I = 0; I < Init->getNumInits(); ++I) {
4102 Expr *E = Init->getInit(I);
4103 if (E->HasSideEffects(Ctx)) {
4104 QualType Ty = E->getType();
4105 if (Ty->isRecordType())
4106 E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());
4107 E = new (Ctx) OpaqueValueExpr(E->getBeginLoc(), Ty, E->getValueKind(),
4108 E->getObjectKind(), E);
4109 Init->setInit(I, E);
4110 }
4111 if (!ILT.buildInitializerList(E))
4112 return false;
4113 }
4114 size_t ExpectedSize = ILT.DestTypes.size();
4115 size_t ActualSize = ILT.ArgExprs.size();
4116 // For incomplete arrays it is completely arbitrary to choose whether we think
4117 // the user intended fewer or more elements. This implementation assumes that
4118 // the user intended more, and errors that there are too few initializers to
4119 // complete the final element.
4120 if (Entity.getType()->isIncompleteArrayType())
4121 ExpectedSize =
4122 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4123
4124 // An initializer list might be attempting to initialize a reference or
4125 // rvalue-reference. When checking the initializer we should look through
4126 // the reference.
4127 QualType InitTy = Entity.getType().getNonReferenceType();
4128 if (InitTy.hasAddressSpace())
4130 if (ExpectedSize != ActualSize) {
4131 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4132 SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4133 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4134 return false;
4135 }
4136
4137 // generateInitListsImpl will always return an InitListExpr here, because the
4138 // scalar case is handled above.
4139 auto *NewInit = cast<InitListExpr>(ILT.generateInitLists());
4140 Init->resizeInits(Ctx, NewInit->getNumInits());
4141 for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
4142 Init->updateInit(Ctx, I, NewInit->getInit(I));
4143 return true;
4144}
4145
4147 const HLSLVkConstantIdAttr *ConstIdAttr =
4148 VDecl->getAttr<HLSLVkConstantIdAttr>();
4149 if (!ConstIdAttr)
4150 return true;
4151
4152 ASTContext &Context = SemaRef.getASTContext();
4153
4154 APValue InitValue;
4155 if (!Init->isCXX11ConstantExpr(Context, &InitValue)) {
4156 Diag(VDecl->getLocation(), diag::err_specialization_const);
4157 VDecl->setInvalidDecl();
4158 return false;
4159 }
4160
4161 Builtin::ID BID =
4163
4164 // Argument 1: The ID from the attribute
4165 int ConstantID = ConstIdAttr->getId();
4166 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4167 Expr *IdExpr = IntegerLiteral::Create(Context, IDVal, Context.IntTy,
4168 ConstIdAttr->getLocation());
4169
4170 SmallVector<Expr *, 2> Args = {IdExpr, Init};
4171 Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);
4172 if (C->getType()->getCanonicalTypeUnqualified() !=
4174 C = SemaRef
4177 Init->getType(), Init->getExprLoc()),
4178 SourceLocation(), C)
4179 .get();
4180 }
4181 Init = C;
4182 return true;
4183}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Definition: CGHLSLRuntime.h:50
const Decl * D
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
StringRef Identifier
Definition: Format.cpp:3185
const Environment & Env
Definition: HTMLLogger.cpp:147
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
#define X(type, name)
Definition: Value.h:145
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
uint32_t Id
Definition: SemaARM.cpp:1179
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
Definition: SemaHLSL.cpp:2522
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
Definition: SemaHLSL.cpp:3185
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition: SemaHLSL.cpp:2607
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition: SemaHLSL.cpp:928
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
Definition: SemaHLSL.cpp:80
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:2660
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
Definition: SemaHLSL.cpp:891
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:2677
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)
Definition: SemaHLSL.cpp:2007
static bool initVarDeclWithCtor(Sema &S, VarDecl *VD, MutableArrayRef< Expr * > Args)
Definition: SemaHLSL.cpp:3691
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)
Definition: SemaHLSL.cpp:2594
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)
Definition: SemaHLSL.cpp:2583
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
Definition: SemaHLSL.cpp:2644
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)
Definition: SemaHLSL.cpp:2617
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)
Definition: SemaHLSL.cpp:2559
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
Definition: SemaHLSL.cpp:899
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
Definition: SemaHLSL.cpp:401
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:2693
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition: SemaHLSL.cpp:904
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)
Definition: SemaHLSL.cpp:2627
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)
Definition: SemaHLSL.cpp:2741
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:981
static bool isValidWaveSizeValue(unsigned Value)
Definition: SemaHLSL.cpp:1436
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
Definition: SemaHLSL.cpp:3588
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition: SemaHLSL.cpp:2570
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
Definition: SemaHLSL.cpp:1982
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
Definition: SemaHLSL.cpp:1906
This file declares semantic analysis for HLSL constructs.
SourceRange Range
Definition: SemaObjC.cpp:753
SourceLocation Loc
Definition: SemaObjC.cpp:754
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
SourceLocation Begin
StateNode * Previous
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Definition: ASTConsumer.cpp:18
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:3056
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
CanQualType FloatTy
Definition: ASTContext.h:1234
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2867
CanQualType DoubleTy
Definition: ASTContext.h:1234
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
Definition: ASTContext.h:3062
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition: ASTContext.h:740
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
Definition: ASTContext.h:1223
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
Definition: ASTContext.h:1224
QualType removeAddrSpaceQualType(QualType T) const
Remove any existing address space on the type and returns the type with qualifiers intact (or that's ...
CanQualType IntTy
Definition: ASTContext.h:1231
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2898
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
Definition: ASTContext.h:1232
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:859
QualType getCorrespondingUnsignedType(QualType T) const
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
QualType getCommonSugaredType(QualType X, QualType Y, bool Unqualified=false) const
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Definition: ASTContext.h:2656
PtrTy get() const
Definition: Ownership.h:171
bool isInvalid() const
Definition: Ownership.h:167
QualType getElementType() const
Definition: TypeBase.h:3750
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
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
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:73
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3083
SourceLocation getBeginLoc() const
Definition: Expr.h:3213
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3062
Expr * getCallee()
Definition: Expr.h:3026
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3070
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.
Definition: CanonicalType.h:84
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:3776
bool isZeroSize() const
Return true if the size is zero.
Definition: TypeBase.h:3846
A POD class for pairing a NamedDecl* with an access specifier.
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.
Definition: DeclBase.cpp:1879
bool isTranslationUnit() const
Definition: DeclBase.h:2185
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1793
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2373
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1450
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
ValueDecl * getDecl()
Definition: Expr.h:1340
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:573
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:524
void addAttr(Attr *A)
Definition: DeclBase.cpp:1022
attr_iterator attr_end() const
Definition: DeclBase.h:542
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:593
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.
Definition: DeclBase.cpp:1121
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.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:830
Recursive AST visitor that supports extension via dynamic dispatch.
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
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:3624
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
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3767
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3191
const Attributes & getAttrs() const
Definition: TypeBase.h:6754
static const HLSLAttributedResourceType * findHandleTypeOnResource(const Type *RT)
Definition: Type.cpp:5784
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition: Decl.h:5156
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
Definition: Decl.cpp:5773
void addLayoutStruct(CXXRecordDecl *LS)
Definition: Decl.cpp:5813
void setHasValidPackoffset(bool PO)
Definition: Decl.h:5201
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
Definition: Decl.cpp:5796
buffer_decl_range buffer_decls() const
Definition: Decl.h:5231
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
Definition: Expr.cpp:5458
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
Definition: Decl.cpp:5859
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.
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Represents a C array with an unspecified size.
Definition: TypeBase.h:3925
Describes an C or C++ initializer list.
Definition: Expr.h:5235
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc)
Create a direct initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Definition: SemaInit.cpp:7739
bool Failed() const
Determine whether the initialization sequence is invalid.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
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
llvm::dxbc::RootSignatureVersion HLSLRootSigVer
The HLSL root signature version for dxil.
Definition: LangOptions.h:552
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
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3300
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3383
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:1180
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 ...
Definition: ParsedAttr.cpp:252
unsigned getMinArgs() const
Definition: ParsedAttr.cpp:138
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:288
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:3591
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:8343
LangAS getAddressSpace() const
Return the address space of this type.
Definition: TypeBase.h:8469
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:8528
QualType getCanonicalType() const
Definition: TypeBase.h:8395
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: TypeBase.h:8437
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition: TypeBase.h:8464
Represents a struct/union/class.
Definition: Decl.h:4309
field_range fields() const
Definition: Decl.h:4512
RecordDecl * getDefinitionOrSelf() const
Definition: Decl.h:4497
bool field_empty() const
Definition: Decl.h:4520
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: TypeBase.h:6502
RecordDecl * getOriginalDecl() const
Definition: TypeBase.h:6509
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: Redeclarable.h:293
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
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
Definition: SemaHLSL.cpp:3519
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
Definition: SemaHLSL.cpp:3475
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
Definition: SemaHLSL.cpp:876
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1440
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
Definition: SemaHLSL.cpp:1851
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
Definition: SemaHLSL.cpp:3338
QualType ProcessResourceTypeAttributes(QualType Wrapped)
Definition: SemaHLSL.cpp:1828
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1580
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1646
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1551
void CheckEntryPoint(FunctionDecl *FD)
Definition: SemaHLSL.cpp:774
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
Definition: SemaHLSL.cpp:1060
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
Definition: SemaHLSL.cpp:2464
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)
Definition: SemaHLSL.cpp:3597
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
Definition: SemaHLSL.cpp:1079
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1597
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
Definition: SemaHLSL.cpp:848
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1560
bool ContainsBitField(QualType BaseTy)
Definition: SemaHLSL.cpp:3405
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
Definition: SemaHLSL.cpp:4146
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1538
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:2114
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
Definition: SemaHLSL.cpp:3440
void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1572
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
Definition: SemaHLSL.cpp:3281
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1356
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
Definition: SemaHLSL.cpp:3304
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
Definition: SemaHLSL.cpp:993
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:2024
bool IsTypedResourceElementCompatible(QualType T1)
Definition: SemaHLSL.cpp:3244
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
Definition: SemaHLSL.cpp:4093
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1382
bool ActOnUninitializedVarDecl(VarDecl *D)
Definition: SemaHLSL.cpp:3800
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1504
void ActOnTopLevelFunction(FunctionDecl *FD)
Definition: SemaHLSL.cpp:724
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1750
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)
Definition: SemaHLSL.cpp:1521
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
Definition: SemaHLSL.cpp:704
QualType getInoutParameterType(QualType Ty)
Definition: SemaHLSL.cpp:3577
SemaHLSL(Sema &S)
Definition: SemaHLSL.cpp:195
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1512
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)
Definition: SemaHLSL.cpp:1205
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1589
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...
Definition: SemaHLSL.cpp:1091
void ActOnVariableDeclarator(VarDecl *VD)
Definition: SemaHLSL.cpp:3631
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaHLSL.cpp:2766
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:1113
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:9281
Expr * BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs)
BuildBuiltinCallExpr - Create a call to a builtin function specified by Id.
Definition: SemaExpr.cpp:6788
ASTContext & Context
Definition: Sema.h:1276
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1555
ASTContext & getASTContext() const
Definition: Sema.h:918
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
bool BuiltinVectorToScalarMath(CallExpr *TheCall)
bool IsLayoutCompatible(QualType T1, QualType T2) const
const LangOptions & getLangOpts() const
Definition: Sema.h:911
DeclContext * getCurLexicalContext() const
Definition: Sema.h:1117
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3441
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
Definition: Sema.h:4819
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1411
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr=EltwiseBuiltinArgTyRestriction::None)
ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)
Binary Operators. 'Tok' is the token for the operator.
Definition: SemaExpr.cpp:15539
void CheckCompleteVariableDeclaration(VarDecl *VD)
Definition: SemaDecl.cpp:14616
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr=EltwiseBuiltinArgTyRestriction::FloatTy)
ASTConsumer & Consumer
Definition: Sema.h:1277
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5197
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9241
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1366
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Definition: SemaInit.cpp:9874
void PopDeclContext()
Definition: SemaDecl.cpp:1373
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:2773
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() 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
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1801
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.
Definition: TargetInfo.h:1288
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
Definition: TargetInfo.h:1699
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
Definition: TargetInfo.h:1703
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:8314
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 isStructureType() const
Definition: Type.cpp:678
bool isVoidType() const
Definition: TypeBase.h:8936
bool isBooleanType() const
Definition: TypeBase.h:9066
bool isIncompleteArrayType() const
Definition: TypeBase.h:8687
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:8683
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.h:41
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:2070
bool isArrayType() const
Definition: TypeBase.h:8679
bool isArithmeticType() const
Definition: Type.cpp:2341
bool isHLSLBuiltinIntangibleType() const
Definition: TypeBase.h:8881
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: TypeBase.h:8980
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isHLSLIntangibleType() const
Definition: Type.cpp:5428
bool isEnumeralType() const
Definition: TypeBase.h:8711
bool isScalarType() const
Definition: TypeBase.h:9038
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2107
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:2295
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition: Type.cpp:2415
bool isFloat32Type() const
Definition: TypeBase.h:8949
bool isHalfType() const
Definition: TypeBase.h:8940
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
Definition: Type.cpp:2368
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2247
bool isHLSLResourceRecord() const
Definition: Type.cpp:5415
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition: Type.cpp:2316
bool isVectorType() const
Definition: TypeBase.h:8719
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2324
bool isHLSLAttributedResourceType() const
Definition: TypeBase.h:8893
@ STK_FloatingComplex
Definition: TypeBase.h:2782
@ STK_BlockPointer
Definition: TypeBase.h:2775
@ STK_ObjCObjectPointer
Definition: TypeBase.h:2776
@ STK_FixedPoint
Definition: TypeBase.h:2783
@ STK_IntegralComplex
Definition: TypeBase.h:2781
@ STK_MemberPointer
Definition: TypeBase.h:2777
bool isFloatingType() const
Definition: Type.cpp:2308
bool isSamplerT() const
Definition: TypeBase.h:8814
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
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:8707
bool isHLSLResourceRecordArray() const
Definition: Type.cpp:5419
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:4191
unsigned getNumElements() const
Definition: TypeBase.h:4206
QualType getElementType() const
Definition: TypeBase.h:4205
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
The JSON file list parser is used to communicate input to InstallAPI.
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
BinaryOperatorKind
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
Definition: ParsedAttr.h:1067
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
ActionResult< Expr * > ExprResult
Definition: Ownership.h:249
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.
Definition: AddressSpaces.h:25
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
Definition: SemaHLSL.cpp:1666
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
Visibility
Describes the different kinds of visibility that a declaration may have.
Definition: Visibility.h:34
unsigned long uint64_t
unsigned int uint32_t
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:34
#define false
Definition: stdbool.h:26
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
llvm::dxil::ResourceClass ResourceClass
Definition: TypeBase.h:6713
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
const SourceLocation & getLocation() const
Definition: SemaHLSL.h:45
const llvm::hlsl::rootsig::RootElement & getElement() const
Definition: SemaHLSL.h:44