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