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->getDecl();
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->getDecl()->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_resource_getdimensions_x: {
3010 ASTContext &AST = SemaRef.getASTContext();
3011 if (SemaRef.checkArgCount(TheCall, 2) ||
3012 CheckResourceHandle(&SemaRef, TheCall, 0) ||
3013 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
3014 CheckModifiableLValue(&SemaRef, TheCall, 1))
3015 return true;
3016 break;
3017 }
3018 case Builtin::BI__builtin_hlsl_resource_getstride: {
3019 ASTContext &AST = SemaRef.getASTContext();
3020 if (SemaRef.checkArgCount(TheCall, 2) ||
3021 CheckResourceHandle(&SemaRef, TheCall, 0) ||
3022 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
3023 CheckModifiableLValue(&SemaRef, TheCall, 1))
3024 return true;
3025 break;
3026 }
3027 case Builtin::BI__builtin_hlsl_and:
3028 case Builtin::BI__builtin_hlsl_or: {
3029 if (SemaRef.checkArgCount(TheCall, 2))
3030 return true;
3031 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
3032 return true;
3033 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3034 return true;
3035
3036 ExprResult A = TheCall->getArg(0);
3037 QualType ArgTyA = A.get()->getType();
3038 // return type is the same as the input type
3039 TheCall->setType(ArgTyA);
3040 break;
3041 }
3042 case Builtin::BI__builtin_hlsl_all:
3043 case Builtin::BI__builtin_hlsl_any: {
3044 if (SemaRef.checkArgCount(TheCall, 1))
3045 return true;
3046 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3047 return true;
3048 break;
3049 }
3050 case Builtin::BI__builtin_hlsl_asdouble: {
3051 if (SemaRef.checkArgCount(TheCall, 2))
3052 return true;
3054 &SemaRef, TheCall,
3055 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
3056 /* arg index */ 0))
3057 return true;
3059 &SemaRef, TheCall,
3060 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
3061 /* arg index */ 1))
3062 return true;
3063 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3064 return true;
3065
3066 SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().DoubleTy);
3067 break;
3068 }
3069 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3070 if (SemaRef.BuiltinElementwiseTernaryMath(
3071 TheCall, /*ArgTyRestr=*/
3073 return true;
3074 break;
3075 }
3076 case Builtin::BI__builtin_hlsl_dot: {
3077 // arg count is checked by BuiltinVectorToScalarMath
3078 if (SemaRef.BuiltinVectorToScalarMath(TheCall))
3079 return true;
3081 return true;
3082 break;
3083 }
3084 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3085 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3086 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3087 return true;
3088
3089 const Expr *Arg = TheCall->getArg(0);
3090 QualType ArgTy = Arg->getType();
3091 QualType EltTy = ArgTy;
3092
3093 QualType ResTy = SemaRef.Context.UnsignedIntTy;
3094
3095 if (auto *VecTy = EltTy->getAs<VectorType>()) {
3096 EltTy = VecTy->getElementType();
3097 ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3098 }
3099
3100 if (!EltTy->isIntegerType()) {
3101 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
3102 << 1 << /* scalar or vector of */ 5 << /* integer ty */ 1
3103 << /* no fp */ 0 << ArgTy;
3104 return true;
3105 }
3106
3107 TheCall->setType(ResTy);
3108 break;
3109 }
3110 case Builtin::BI__builtin_hlsl_select: {
3111 if (SemaRef.checkArgCount(TheCall, 3))
3112 return true;
3113 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
3114 return true;
3115 QualType ArgTy = TheCall->getArg(0)->getType();
3116 if (ArgTy->isBooleanType() && CheckBoolSelect(&SemaRef, TheCall))
3117 return true;
3118 auto *VTy = ArgTy->getAs<VectorType>();
3119 if (VTy && VTy->getElementType()->isBooleanType() &&
3120 CheckVectorSelect(&SemaRef, TheCall))
3121 return true;
3122 break;
3123 }
3124 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3125 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3126 if (SemaRef.checkArgCount(TheCall, 1))
3127 return true;
3128 if (!TheCall->getArg(0)
3129 ->getType()
3130 ->hasFloatingRepresentation()) // half or float or double
3131 return SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
3132 diag::err_builtin_invalid_arg_type)
3133 << /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0
3134 << /* fp */ 1 << TheCall->getArg(0)->getType();
3135 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3136 return true;
3137 break;
3138 }
3139 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3140 case Builtin::BI__builtin_hlsl_elementwise_radians:
3141 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3142 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3143 if (SemaRef.checkArgCount(TheCall, 1))
3144 return true;
3145 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3147 return true;
3148 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3149 return true;
3150 break;
3151 }
3152 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3153 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3154 if (SemaRef.checkArgCount(TheCall, 1))
3155 return true;
3156 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3158 return true;
3159 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3160 return true;
3162 break;
3163 }
3164 case Builtin::BI__builtin_hlsl_lerp: {
3165 if (SemaRef.checkArgCount(TheCall, 3))
3166 return true;
3167 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3169 return true;
3170 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3171 return true;
3172 if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3173 return true;
3174 break;
3175 }
3176 case Builtin::BI__builtin_hlsl_mad: {
3177 if (SemaRef.BuiltinElementwiseTernaryMath(
3178 TheCall, /*ArgTyRestr=*/
3180 return true;
3181 break;
3182 }
3183 case Builtin::BI__builtin_hlsl_normalize: {
3184 if (SemaRef.checkArgCount(TheCall, 1))
3185 return true;
3186 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3188 return true;
3189 ExprResult A = TheCall->getArg(0);
3190 QualType ArgTyA = A.get()->getType();
3191 // return type is the same as the input type
3192 TheCall->setType(ArgTyA);
3193 break;
3194 }
3195 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3196 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3197 return true;
3198 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3200 return true;
3202 break;
3203 }
3204 case Builtin::BI__builtin_hlsl_step: {
3205 if (SemaRef.checkArgCount(TheCall, 2))
3206 return true;
3207 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3209 return true;
3210
3211 ExprResult A = TheCall->getArg(0);
3212 QualType ArgTyA = A.get()->getType();
3213 // return type is the same as the input type
3214 TheCall->setType(ArgTyA);
3215 break;
3216 }
3217 case Builtin::BI__builtin_hlsl_wave_active_max:
3218 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3219 if (SemaRef.checkArgCount(TheCall, 1))
3220 return true;
3221
3222 // Ensure input expr type is a scalar/vector and the same as the return type
3223 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3224 return true;
3225 if (CheckWaveActive(&SemaRef, TheCall))
3226 return true;
3227 ExprResult Expr = TheCall->getArg(0);
3228 QualType ArgTyExpr = Expr.get()->getType();
3229 TheCall->setType(ArgTyExpr);
3230 break;
3231 }
3232 // Note these are llvm builtins that we want to catch invalid intrinsic
3233 // generation. Normal handling of these builitns will occur elsewhere.
3234 case Builtin::BI__builtin_elementwise_bitreverse: {
3235 // does not include a check for number of arguments
3236 // because that is done previously
3237 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3239 return true;
3240 break;
3241 }
3242 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3243 if (SemaRef.checkArgCount(TheCall, 2))
3244 return true;
3245
3246 // Ensure index parameter type can be interpreted as a uint
3247 ExprResult Index = TheCall->getArg(1);
3248 QualType ArgTyIndex = Index.get()->getType();
3249 if (!ArgTyIndex->isIntegerType()) {
3250 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3251 diag::err_typecheck_convert_incompatible)
3252 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3253 return true;
3254 }
3255
3256 // Ensure input expr type is a scalar/vector and the same as the return type
3257 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3258 return true;
3259
3260 ExprResult Expr = TheCall->getArg(0);
3261 QualType ArgTyExpr = Expr.get()->getType();
3262 TheCall->setType(ArgTyExpr);
3263 break;
3264 }
3265 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3266 if (SemaRef.checkArgCount(TheCall, 0))
3267 return true;
3268 break;
3269 }
3270 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3271 if (SemaRef.checkArgCount(TheCall, 3))
3272 return true;
3273
3274 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.DoubleTy, 0) ||
3275 CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,
3276 1) ||
3277 CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,
3278 2))
3279 return true;
3280
3281 if (CheckModifiableLValue(&SemaRef, TheCall, 1) ||
3282 CheckModifiableLValue(&SemaRef, TheCall, 2))
3283 return true;
3284 break;
3285 }
3286 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3287 if (SemaRef.checkArgCount(TheCall, 1))
3288 return true;
3289
3290 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0))
3291 return true;
3292 break;
3293 }
3294 case Builtin::BI__builtin_elementwise_acos:
3295 case Builtin::BI__builtin_elementwise_asin:
3296 case Builtin::BI__builtin_elementwise_atan:
3297 case Builtin::BI__builtin_elementwise_atan2:
3298 case Builtin::BI__builtin_elementwise_ceil:
3299 case Builtin::BI__builtin_elementwise_cos:
3300 case Builtin::BI__builtin_elementwise_cosh:
3301 case Builtin::BI__builtin_elementwise_exp:
3302 case Builtin::BI__builtin_elementwise_exp2:
3303 case Builtin::BI__builtin_elementwise_exp10:
3304 case Builtin::BI__builtin_elementwise_floor:
3305 case Builtin::BI__builtin_elementwise_fmod:
3306 case Builtin::BI__builtin_elementwise_log:
3307 case Builtin::BI__builtin_elementwise_log2:
3308 case Builtin::BI__builtin_elementwise_log10:
3309 case Builtin::BI__builtin_elementwise_pow:
3310 case Builtin::BI__builtin_elementwise_roundeven:
3311 case Builtin::BI__builtin_elementwise_sin:
3312 case Builtin::BI__builtin_elementwise_sinh:
3313 case Builtin::BI__builtin_elementwise_sqrt:
3314 case Builtin::BI__builtin_elementwise_tan:
3315 case Builtin::BI__builtin_elementwise_tanh:
3316 case Builtin::BI__builtin_elementwise_trunc: {
3317 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3319 return true;
3320 break;
3321 }
3322 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3323 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
3324 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3325 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3326 };
3327 if (SemaRef.checkArgCount(TheCall, 2) ||
3328 CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy) ||
3329 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
3330 SemaRef.getASTContext().IntTy))
3331 return true;
3332 Expr *OffsetExpr = TheCall->getArg(1);
3333 std::optional<llvm::APSInt> Offset =
3334 OffsetExpr->getIntegerConstantExpr(SemaRef.getASTContext());
3335 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
3336 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3337 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3338 << 1;
3339 return true;
3340 }
3341 break;
3342 }
3343 }
3344 return false;
3345}
3346
3350 WorkList.push_back(BaseTy);
3351 while (!WorkList.empty()) {
3352 QualType T = WorkList.pop_back_val();
3353 T = T.getCanonicalType().getUnqualifiedType();
3354 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3355 llvm::SmallVector<QualType, 16> ElementFields;
3356 // Generally I've avoided recursion in this algorithm, but arrays of
3357 // structs could be time-consuming to flatten and churn through on the
3358 // work list. Hopefully nesting arrays of structs containing arrays
3359 // of structs too many levels deep is unlikely.
3360 BuildFlattenedTypeList(AT->getElementType(), ElementFields);
3361 // Repeat the element's field list n times.
3362 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3363 llvm::append_range(List, ElementFields);
3364 continue;
3365 }
3366 // Vectors can only have element types that are builtin types, so this can
3367 // add directly to the list instead of to the WorkList.
3368 if (const auto *VT = dyn_cast<VectorType>(T)) {
3369 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3370 continue;
3371 }
3372 if (const auto *RD = T->getAsCXXRecordDecl()) {
3373 if (RD->isStandardLayout())
3374 RD = RD->getStandardLayoutBaseWithFields();
3375
3376 // For types that we shouldn't decompose (unions and non-aggregates), just
3377 // add the type itself to the list.
3378 if (RD->isUnion() || !RD->isAggregate()) {
3379 List.push_back(T);
3380 continue;
3381 }
3382
3384 for (const auto *FD : RD->fields())
3385 if (!FD->isUnnamedBitField())
3386 FieldTypes.push_back(FD->getType());
3387 // Reverse the newly added sub-range.
3388 std::reverse(FieldTypes.begin(), FieldTypes.end());
3389 llvm::append_range(WorkList, FieldTypes);
3390
3391 // If this wasn't a standard layout type we may also have some base
3392 // classes to deal with.
3393 if (!RD->isStandardLayout()) {
3394 FieldTypes.clear();
3395 for (const auto &Base : RD->bases())
3396 FieldTypes.push_back(Base.getType());
3397 std::reverse(FieldTypes.begin(), FieldTypes.end());
3398 llvm::append_range(WorkList, FieldTypes);
3399 }
3400 continue;
3401 }
3402 List.push_back(T);
3403 }
3404}
3405
3407 // null and array types are not allowed.
3408 if (QT.isNull() || QT->isArrayType())
3409 return false;
3410
3411 // UDT types are not allowed
3412 if (QT->isRecordType())
3413 return false;
3414
3415 if (QT->isBooleanType() || QT->isEnumeralType())
3416 return false;
3417
3418 // the only other valid builtin types are scalars or vectors
3419 if (QT->isArithmeticType()) {
3420 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3421 return false;
3422 return true;
3423 }
3424
3425 if (const VectorType *VT = QT->getAs<VectorType>()) {
3426 int ArraySize = VT->getNumElements();
3427
3428 if (ArraySize > 4)
3429 return false;
3430
3431 QualType ElTy = VT->getElementType();
3432 if (ElTy->isBooleanType())
3433 return false;
3434
3435 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3436 return false;
3437 return true;
3438 }
3439
3440 return false;
3441}
3442
3444 if (T1.isNull() || T2.isNull())
3445 return false;
3446
3449
3450 // If both types are the same canonical type, they're obviously compatible.
3451 if (SemaRef.getASTContext().hasSameType(T1, T2))
3452 return true;
3453
3455 BuildFlattenedTypeList(T1, T1Types);
3457 BuildFlattenedTypeList(T2, T2Types);
3458
3459 // Check the flattened type list
3460 return llvm::equal(T1Types, T2Types,
3461 [this](QualType LHS, QualType RHS) -> bool {
3462 return SemaRef.IsLayoutCompatible(LHS, RHS);
3463 });
3464}
3465
3467 FunctionDecl *Old) {
3468 if (New->getNumParams() != Old->getNumParams())
3469 return true;
3470
3471 bool HadError = false;
3472
3473 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
3474 ParmVarDecl *NewParam = New->getParamDecl(i);
3475 ParmVarDecl *OldParam = Old->getParamDecl(i);
3476
3477 // HLSL parameter declarations for inout and out must match between
3478 // declarations. In HLSL inout and out are ambiguous at the call site,
3479 // but have different calling behavior, so you cannot overload a
3480 // method based on a difference between inout and out annotations.
3481 const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>();
3482 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3483 const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>();
3484 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3485
3486 if (NSpellingIdx != OSpellingIdx) {
3487 SemaRef.Diag(NewParam->getLocation(),
3488 diag::err_hlsl_param_qualifier_mismatch)
3489 << NDAttr << NewParam;
3490 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
3491 << ODAttr;
3492 HadError = true;
3493 }
3494 }
3495 return HadError;
3496}
3497
3498// Generally follows PerformScalarCast, with cases reordered for
3499// clarity of what types are supported
3501
3502 if (!SrcTy->isScalarType() || !DestTy->isScalarType())
3503 return false;
3504
3505 if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3506 return true;
3507
3508 switch (SrcTy->getScalarTypeKind()) {
3509 case Type::STK_Bool: // casting from bool is like casting from an integer
3510 case Type::STK_Integral:
3511 switch (DestTy->getScalarTypeKind()) {
3512 case Type::STK_Bool:
3513 case Type::STK_Integral:
3514 case Type::STK_Floating:
3515 return true;
3516 case Type::STK_CPointer:
3520 llvm_unreachable("HLSL doesn't support pointers.");
3523 llvm_unreachable("HLSL doesn't support complex types.");
3525 llvm_unreachable("HLSL doesn't support fixed point types.");
3526 }
3527 llvm_unreachable("Should have returned before this");
3528
3529 case Type::STK_Floating:
3530 switch (DestTy->getScalarTypeKind()) {
3531 case Type::STK_Floating:
3532 case Type::STK_Bool:
3533 case Type::STK_Integral:
3534 return true;
3537 llvm_unreachable("HLSL doesn't support complex types.");
3539 llvm_unreachable("HLSL doesn't support fixed point types.");
3540 case Type::STK_CPointer:
3544 llvm_unreachable("HLSL doesn't support pointers.");
3545 }
3546 llvm_unreachable("Should have returned before this");
3547
3549 case Type::STK_CPointer:
3552 llvm_unreachable("HLSL doesn't support pointers.");
3553
3555 llvm_unreachable("HLSL doesn't support fixed point types.");
3556
3559 llvm_unreachable("HLSL doesn't support complex types.");
3560 }
3561
3562 llvm_unreachable("Unhandled scalar cast");
3563}
3564
3565// Can perform an HLSL Aggregate splat cast if the Dest is an aggregate and the
3566// Src is a scalar or a vector of length 1
3567// Or if Dest is a vector and Src is a vector of length 1
3569
3570 QualType SrcTy = Src->getType();
3571 // Not a valid HLSL Aggregate Splat cast if Dest is a scalar or if this is
3572 // going to be a vector splat from a scalar.
3573 if ((SrcTy->isScalarType() && DestTy->isVectorType()) ||
3574 DestTy->isScalarType())
3575 return false;
3576
3577 const VectorType *SrcVecTy = SrcTy->getAs<VectorType>();
3578
3579 // Src isn't a scalar or a vector of length 1
3580 if (!SrcTy->isScalarType() && !(SrcVecTy && SrcVecTy->getNumElements() == 1))
3581 return false;
3582
3583 if (SrcVecTy)
3584 SrcTy = SrcVecTy->getElementType();
3585
3587 BuildFlattenedTypeList(DestTy, DestTypes);
3588
3589 for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3590 if (DestTypes[I]->isUnionType())
3591 return false;
3592 if (!CanPerformScalarCast(SrcTy, DestTypes[I]))
3593 return false;
3594 }
3595 return true;
3596}
3597
3598// Can we perform an HLSL Elementwise cast?
3599// TODO: update this code when matrices are added; see issue #88060
3601
3602 // Don't handle casts where LHS and RHS are any combination of scalar/vector
3603 // There must be an aggregate somewhere
3604 QualType SrcTy = Src->getType();
3605 if (SrcTy->isScalarType()) // always a splat and this cast doesn't handle that
3606 return false;
3607
3608 if (SrcTy->isVectorType() &&
3609 (DestTy->isScalarType() || DestTy->isVectorType()))
3610 return false;
3611
3613 BuildFlattenedTypeList(DestTy, DestTypes);
3615 BuildFlattenedTypeList(SrcTy, SrcTypes);
3616
3617 // Usually the size of SrcTypes must be greater than or equal to the size of
3618 // DestTypes.
3619 if (SrcTypes.size() < DestTypes.size())
3620 return false;
3621
3622 unsigned SrcSize = SrcTypes.size();
3623 unsigned DstSize = DestTypes.size();
3624 unsigned I;
3625 for (I = 0; I < DstSize && I < SrcSize; I++) {
3626 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3627 return false;
3628 if (!CanPerformScalarCast(SrcTypes[I], DestTypes[I])) {
3629 return false;
3630 }
3631 }
3632
3633 // check the rest of the source type for unions.
3634 for (; I < SrcSize; I++) {
3635 if (SrcTypes[I]->isUnionType())
3636 return false;
3637 }
3638 return true;
3639}
3640
3642 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3643 "We should not get here without a parameter modifier expression");
3644 const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();
3645 if (Attr->getABI() == ParameterABI::Ordinary)
3646 return ExprResult(Arg);
3647
3648 bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut;
3649 if (!Arg->isLValue()) {
3650 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue)
3651 << Arg << (IsInOut ? 1 : 0);
3652 return ExprError();
3653 }
3654
3655 ASTContext &Ctx = SemaRef.getASTContext();
3656
3657 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3658
3659 // HLSL allows implicit conversions from scalars to vectors, but not the
3660 // inverse, so we need to disallow `inout` with scalar->vector or
3661 // scalar->matrix conversions.
3662 if (Arg->getType()->isScalarType() != Ty->isScalarType()) {
3663 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)
3664 << Arg << (IsInOut ? 1 : 0);
3665 return ExprError();
3666 }
3667
3668 auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), Arg->getType(),
3669 VK_LValue, OK_Ordinary, Arg);
3670
3671 // Parameters are initialized via copy initialization. This allows for
3672 // overload resolution of argument constructors.
3673 InitializedEntity Entity =
3675 ExprResult Res =
3676 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3677 if (Res.isInvalid())
3678 return ExprError();
3679 Expr *Base = Res.get();
3680 // After the cast, drop the reference type when creating the exprs.
3681 Ty = Ty.getNonLValueExprType(Ctx);
3682 auto *OpV = new (Ctx)
3683 OpaqueValueExpr(Param->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);
3684
3685 // Writebacks are performed with `=` binary operator, which allows for
3686 // overload resolution on writeback result expressions.
3687 Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Param->getBeginLoc(),
3688 tok::equal, ArgOpV, OpV);
3689
3690 if (Res.isInvalid())
3691 return ExprError();
3692 Expr *Writeback = Res.get();
3693 auto *OutExpr =
3694 HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
3695
3696 return ExprResult(OutExpr);
3697}
3698
3700 // If HLSL gains support for references, all the cites that use this will need
3701 // to be updated with semantic checking to produce errors for
3702 // pointers/references.
3703 assert(!Ty->isReferenceType() &&
3704 "Pointer and reference types cannot be inout or out parameters");
3705 Ty = SemaRef.getASTContext().getLValueReferenceType(Ty);
3706 Ty.addRestrict();
3707 return Ty;
3708}
3709
3711 QualType QT = VD->getType();
3712 return VD->getDeclContext()->isTranslationUnit() &&
3714 VD->getStorageClass() != SC_Static &&
3715 !VD->hasAttr<HLSLVkConstantIdAttr>() &&
3717}
3718
3720 // The variable already has an address space (groupshared for ex).
3721 if (Decl->getType().hasAddressSpace())
3722 return;
3723
3724 if (Decl->getType()->isDependentType())
3725 return;
3726
3727 QualType Type = Decl->getType();
3728
3729 if (Decl->hasAttr<HLSLVkExtBuiltinInputAttr>()) {
3730 LangAS ImplAS = LangAS::hlsl_input;
3731 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3732 Decl->setType(Type);
3733 return;
3734 }
3735
3736 if (Type->isSamplerT() || Type->isVoidType())
3737 return;
3738
3739 // Resource handles.
3741 return;
3742
3743 // Only static globals belong to the Private address space.
3744 // Non-static globals belongs to the cbuffer.
3745 if (Decl->getStorageClass() != SC_Static && !Decl->isStaticDataMember())
3746 return;
3747
3749 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3750 Decl->setType(Type);
3751}
3752
3754 if (VD->hasGlobalStorage()) {
3755 // make sure the declaration has a complete type
3756 if (SemaRef.RequireCompleteType(
3757 VD->getLocation(),
3758 SemaRef.getASTContext().getBaseElementType(VD->getType()),
3759 diag::err_typecheck_decl_incomplete_type)) {
3760 VD->setInvalidDecl();
3762 return;
3763 }
3764
3765 // Global variables outside a cbuffer block that are not a resource, static,
3766 // groupshared, or an empty array or struct belong to the default constant
3767 // buffer $Globals (to be created at the end of the translation unit).
3769 // update address space to hlsl_constant
3772 VD->setType(NewTy);
3773 DefaultCBufferDecls.push_back(VD);
3774 }
3775
3776 // find all resources bindings on decl
3777 if (VD->getType()->isHLSLIntangibleType())
3778 collectResourceBindingsOnVarDecl(VD);
3779
3781 VD->hasAttr<HLSLVkConstantIdAttr>()) {
3782 // Make the variable for resources static. The global externally visible
3783 // storage is accessed through the handle, which is a member. The variable
3784 // itself is not externally visible.
3786 }
3787
3788 // process explicit bindings
3789 processExplicitBindingsOnDecl(VD);
3790
3791 if (VD->getType()->isHLSLResourceRecordArray()) {
3792 // If the resource array does not have an explicit binding attribute,
3793 // create an implicit one. It will be used to transfer implicit binding
3794 // order_ID to codegen.
3795 ResourceBindingAttrs Binding(VD);
3796 if (!Binding.isExplicit()) {
3797 uint32_t OrderID = getNextImplicitBindingOrderID();
3798 if (Binding.hasBinding())
3799 Binding.setImplicitOrderID(OrderID);
3800 else {
3803 OrderID);
3804 // Re-create the binding object to pick up the new attribute.
3805 Binding = ResourceBindingAttrs(VD);
3806 }
3807 }
3808
3809 // Get to the base type of a potentially multi-dimensional array.
3811
3812 const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
3813 if (hasCounterHandle(RD)) {
3814 if (!Binding.hasCounterImplicitOrderID()) {
3815 uint32_t OrderID = getNextImplicitBindingOrderID();
3816 Binding.setCounterImplicitOrderID(OrderID);
3817 }
3818 }
3819 }
3820 }
3821
3823}
3824
3825bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
3826 assert(VD->getType()->isHLSLResourceRecord() &&
3827 "expected resource record type");
3828
3830 uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
3831 uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
3832
3833 // Gather resource binding attributes.
3834 ResourceBindingAttrs Binding(VD);
3835
3836 // Find correct initialization method and create its arguments.
3837 QualType ResourceTy = VD->getType();
3838 CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();
3839 CXXMethodDecl *CreateMethod = nullptr;
3841
3842 bool HasCounter = hasCounterHandle(ResourceDecl);
3843 const char *CreateMethodName;
3844 if (Binding.isExplicit())
3845 CreateMethodName = HasCounter ? "__createFromBindingWithImplicitCounter"
3846 : "__createFromBinding";
3847 else
3848 CreateMethodName = HasCounter
3849 ? "__createFromImplicitBindingWithImplicitCounter"
3850 : "__createFromImplicitBinding";
3851
3852 CreateMethod =
3853 lookupMethod(SemaRef, ResourceDecl, CreateMethodName, VD->getLocation());
3854
3855 if (!CreateMethod)
3856 // This can happen if someone creates a struct that looks like an HLSL
3857 // resource record but does not have the required static create method.
3858 // No binding will be generated for it.
3859 return false;
3860
3861 if (Binding.isExplicit()) {
3862 IntegerLiteral *RegSlot =
3863 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, Binding.getSlot()),
3865 Args.push_back(RegSlot);
3866 } else {
3867 uint32_t OrderID = (Binding.hasImplicitOrderID())
3868 ? Binding.getImplicitOrderID()
3869 : getNextImplicitBindingOrderID();
3870 IntegerLiteral *OrderId =
3871 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
3873 Args.push_back(OrderId);
3874 }
3875
3876 IntegerLiteral *Space =
3877 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, Binding.getSpace()),
3878 AST.UnsignedIntTy, SourceLocation());
3879 Args.push_back(Space);
3880
3881 IntegerLiteral *RangeSize = IntegerLiteral::Create(
3882 AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
3883 Args.push_back(RangeSize);
3884
3885 IntegerLiteral *Index = IntegerLiteral::Create(
3886 AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
3887 Args.push_back(Index);
3888
3889 StringRef VarName = VD->getName();
3890 StringLiteral *Name = StringLiteral::Create(
3891 AST, VarName, StringLiteralKind::Ordinary, false,
3892 AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
3893 SourceLocation());
3894 ImplicitCastExpr *NameCast = ImplicitCastExpr::Create(
3895 AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay,
3896 Name, nullptr, VK_PRValue, FPOptionsOverride());
3897 Args.push_back(NameCast);
3898
3899 if (HasCounter) {
3900 // Will this be in the correct order?
3901 uint32_t CounterOrderID = getNextImplicitBindingOrderID();
3902 IntegerLiteral *CounterId =
3903 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, CounterOrderID),
3904 AST.UnsignedIntTy, SourceLocation());
3905 Args.push_back(CounterId);
3906 }
3907
3908 // Make sure the create method template is instantiated and emitted.
3909 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3910 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3911 true);
3912
3913 // Create CallExpr with a call to the static method and set it as the decl
3914 // initialization.
3915 DeclRefExpr *DRE = DeclRefExpr::Create(
3916 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,
3917 CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue);
3918
3919 auto *ImpCast = ImplicitCastExpr::Create(
3920 AST, AST.getPointerType(CreateMethod->getType()),
3921 CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());
3922
3923 CallExpr *InitExpr =
3924 CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue,
3925 SourceLocation(), FPOptionsOverride());
3926 VD->setInit(InitExpr);
3928 SemaRef.CheckCompleteVariableDeclaration(VD);
3929 return true;
3930}
3931
3932bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
3933 assert(VD->getType()->isHLSLResourceRecordArray() &&
3934 "expected array of resource records");
3935
3936 // Individual resources in a resource array are not initialized here. They
3937 // are initialized later on during codegen when the individual resources are
3938 // accessed. Codegen will emit a call to the resource initialization method
3939 // with the specified array index. We need to make sure though that the method
3940 // for the specific resource type is instantiated, so codegen can emit a call
3941 // to it when the array element is accessed.
3942
3943 // Find correct initialization method based on the resource binding
3944 // information.
3945 ASTContext &AST = SemaRef.getASTContext();
3946 QualType ResElementTy = AST.getBaseElementType(VD->getType());
3947 CXXRecordDecl *ResourceDecl = ResElementTy->getAsCXXRecordDecl();
3948 CXXMethodDecl *CreateMethod = nullptr;
3949
3950 bool HasCounter = hasCounterHandle(ResourceDecl);
3951 ResourceBindingAttrs ResourceAttrs(VD);
3952 if (ResourceAttrs.isExplicit())
3953 // Resource has explicit binding.
3954 CreateMethod =
3955 lookupMethod(SemaRef, ResourceDecl,
3956 HasCounter ? "__createFromBindingWithImplicitCounter"
3957 : "__createFromBinding",
3958 VD->getLocation());
3959 else
3960 // Resource has implicit binding.
3961 CreateMethod = lookupMethod(
3962 SemaRef, ResourceDecl,
3963 HasCounter ? "__createFromImplicitBindingWithImplicitCounter"
3964 : "__createFromImplicitBinding",
3965 VD->getLocation());
3966
3967 if (!CreateMethod)
3968 return false;
3969
3970 // Make sure the create method template is instantiated and emitted.
3971 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3972 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3973 true);
3974 return true;
3975}
3976
3977// Returns true if the initialization has been handled.
3978// Returns false to use default initialization.
3980 // Objects in the hlsl_constant address space are initialized
3981 // externally, so don't synthesize an implicit initializer.
3983 return true;
3984
3985 // Initialize resources at the global scope
3986 if (VD->hasGlobalStorage()) {
3987 const Type *Ty = VD->getType().getTypePtr();
3988 if (Ty->isHLSLResourceRecord())
3989 return initGlobalResourceDecl(VD);
3990 if (Ty->isHLSLResourceRecordArray())
3991 return initGlobalResourceArrayDecl(VD);
3992 }
3993 return false;
3994}
3995
3996// Return true if everything is ok; returns false if there was an error.
3998 Expr *RHSExpr, SourceLocation Loc) {
3999 assert((LHSExpr->getType()->isHLSLResourceRecord() ||
4000 LHSExpr->getType()->isHLSLResourceRecordArray()) &&
4001 "expected LHS to be a resource record or array of resource records");
4002 if (Opc != BO_Assign)
4003 return true;
4004
4005 // If LHS is an array subscript, get the underlying declaration.
4006 Expr *E = LHSExpr;
4007 while (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
4008 E = ASE->getBase()->IgnoreParenImpCasts();
4009
4010 // Report error if LHS is a resource declared at a global scope.
4011 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
4012 if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
4013 if (VD->hasGlobalStorage()) {
4014 // assignment to global resource is not allowed
4015 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
4016 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
4017 return false;
4018 }
4019 }
4020 }
4021 return true;
4022}
4023
4024// Walks though the global variable declaration, collects all resource binding
4025// requirements and adds them to Bindings
4026void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {
4027 assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() &&
4028 "expected global variable that contains HLSL resource");
4029
4030 // Cbuffers and Tbuffers are HLSLBufferDecl types
4031 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
4032 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
4033 ? ResourceClass::CBuffer
4034 : ResourceClass::SRV);
4035 return;
4036 }
4037
4038 // Unwrap arrays
4039 // FIXME: Calculate array size while unwrapping
4040 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
4041 while (Ty->isArrayType()) {
4042 const ArrayType *AT = cast<ArrayType>(Ty);
4044 }
4045
4046 // Resource (or array of resources)
4047 if (const HLSLAttributedResourceType *AttrResType =
4048 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4049 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4050 return;
4051 }
4052
4053 // User defined record type
4054 if (const RecordType *RT = dyn_cast<RecordType>(Ty))
4055 collectResourceBindingsOnUserRecordDecl(VD, RT);
4056}
4057
4058// Walks though the explicit resource binding attributes on the declaration,
4059// and makes sure there is a resource that matched the binding and updates
4060// DeclBindingInfoLists
4061void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
4062 assert(VD->hasGlobalStorage() && "expected global variable");
4063
4064 bool HasBinding = false;
4065 for (Attr *A : VD->attrs()) {
4067 HasBinding = true;
4068
4069 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4070 if (!RBA || !RBA->hasRegisterSlot())
4071 continue;
4072 HasBinding = true;
4073
4074 RegisterType RT = RBA->getRegisterType();
4075 assert(RT != RegisterType::I && "invalid or obsolete register type should "
4076 "never have an attribute created");
4077
4078 if (RT == RegisterType::C) {
4079 if (Bindings.hasBindingInfoForDecl(VD))
4080 SemaRef.Diag(VD->getLocation(),
4081 diag::warn_hlsl_user_defined_type_missing_member)
4082 << static_cast<int>(RT);
4083 continue;
4084 }
4085
4086 // Find DeclBindingInfo for this binding and update it, or report error
4087 // if it does not exist (user type does to contain resources with the
4088 // expected resource class).
4090 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4091 // update binding info
4092 BI->setBindingAttribute(RBA, BindingType::Explicit);
4093 } else {
4094 SemaRef.Diag(VD->getLocation(),
4095 diag::warn_hlsl_user_defined_type_missing_member)
4096 << static_cast<int>(RT);
4097 }
4098 }
4099
4100 if (!HasBinding && isResourceRecordTypeOrArrayOf(VD))
4101 SemaRef.Diag(VD->getLocation(), diag::warn_hlsl_implicit_binding);
4102}
4103namespace {
4104class InitListTransformer {
4105 Sema &S;
4106 ASTContext &Ctx;
4107 QualType InitTy;
4108 QualType *DstIt = nullptr;
4109 Expr **ArgIt = nullptr;
4110 // Is wrapping the destination type iterator required? This is only used for
4111 // incomplete array types where we loop over the destination type since we
4112 // don't know the full number of elements from the declaration.
4113 bool Wrap;
4114
4115 bool castInitializer(Expr *E) {
4116 assert(DstIt && "This should always be something!");
4117 if (DstIt == DestTypes.end()) {
4118 if (!Wrap) {
4119 ArgExprs.push_back(E);
4120 // This is odd, but it isn't technically a failure due to conversion, we
4121 // handle mismatched counts of arguments differently.
4122 return true;
4123 }
4124 DstIt = DestTypes.begin();
4125 }
4126 InitializedEntity Entity = InitializedEntity::InitializeParameter(
4127 Ctx, *DstIt, /* Consumed (ObjC) */ false);
4128 ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
4129 if (Res.isInvalid())
4130 return false;
4131 Expr *Init = Res.get();
4132 ArgExprs.push_back(Init);
4133 DstIt++;
4134 return true;
4135 }
4136
4137 bool buildInitializerListImpl(Expr *E) {
4138 // If this is an initialization list, traverse the sub initializers.
4139 if (auto *Init = dyn_cast<InitListExpr>(E)) {
4140 for (auto *SubInit : Init->inits())
4141 if (!buildInitializerListImpl(SubInit))
4142 return false;
4143 return true;
4144 }
4145
4146 // If this is a scalar type, just enqueue the expression.
4147 QualType Ty = E->getType();
4148
4149 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4150 return castInitializer(E);
4151
4152 if (auto *VecTy = Ty->getAs<VectorType>()) {
4153 uint64_t Size = VecTy->getNumElements();
4154
4155 QualType SizeTy = Ctx.getSizeType();
4156 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
4157 for (uint64_t I = 0; I < Size; ++I) {
4158 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
4159 SizeTy, SourceLocation());
4160
4162 E, E->getBeginLoc(), Idx, E->getEndLoc());
4163 if (ElExpr.isInvalid())
4164 return false;
4165 if (!castInitializer(ElExpr.get()))
4166 return false;
4167 }
4168 return true;
4169 }
4170
4171 if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {
4172 uint64_t Size = ArrTy->getZExtSize();
4173 QualType SizeTy = Ctx.getSizeType();
4174 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
4175 for (uint64_t I = 0; I < Size; ++I) {
4176 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
4177 SizeTy, SourceLocation());
4179 E, E->getBeginLoc(), Idx, E->getEndLoc());
4180 if (ElExpr.isInvalid())
4181 return false;
4182 if (!buildInitializerListImpl(ElExpr.get()))
4183 return false;
4184 }
4185 return true;
4186 }
4187
4188 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4189 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4190 RecordDecls.push_back(RD);
4191 while (RecordDecls.back()->getNumBases()) {
4192 CXXRecordDecl *D = RecordDecls.back();
4193 assert(D->getNumBases() == 1 &&
4194 "HLSL doesn't support multiple inheritance");
4195 RecordDecls.push_back(
4197 }
4198 while (!RecordDecls.empty()) {
4199 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4200 for (auto *FD : RD->fields()) {
4201 if (FD->isUnnamedBitField())
4202 continue;
4203 DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());
4204 DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
4206 E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
4207 if (Res.isInvalid())
4208 return false;
4209 if (!buildInitializerListImpl(Res.get()))
4210 return false;
4211 }
4212 }
4213 }
4214 return true;
4215 }
4216
4217 Expr *generateInitListsImpl(QualType Ty) {
4218 assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");
4219 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4220 return *(ArgIt++);
4221
4222 llvm::SmallVector<Expr *> Inits;
4223 assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL");
4224 Ty = Ty.getDesugaredType(Ctx);
4225 if (Ty->isVectorType() || Ty->isConstantArrayType()) {
4226 QualType ElTy;
4227 uint64_t Size = 0;
4228 if (auto *ATy = Ty->getAs<VectorType>()) {
4229 ElTy = ATy->getElementType();
4230 Size = ATy->getNumElements();
4231 } else {
4232 auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());
4233 ElTy = VTy->getElementType();
4234 Size = VTy->getZExtSize();
4235 }
4236 for (uint64_t I = 0; I < Size; ++I)
4237 Inits.push_back(generateInitListsImpl(ElTy));
4238 }
4239 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4240 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4241 RecordDecls.push_back(RD);
4242 while (RecordDecls.back()->getNumBases()) {
4243 CXXRecordDecl *D = RecordDecls.back();
4244 assert(D->getNumBases() == 1 &&
4245 "HLSL doesn't support multiple inheritance");
4246 RecordDecls.push_back(
4248 }
4249 while (!RecordDecls.empty()) {
4250 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4251 for (auto *FD : RD->fields())
4252 if (!FD->isUnnamedBitField())
4253 Inits.push_back(generateInitListsImpl(FD->getType()));
4254 }
4255 }
4256 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4257 Inits, Inits.back()->getEndLoc());
4258 NewInit->setType(Ty);
4259 return NewInit;
4260 }
4261
4262public:
4263 llvm::SmallVector<QualType, 16> DestTypes;
4264 llvm::SmallVector<Expr *, 16> ArgExprs;
4265 InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)
4266 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4267 Wrap(Entity.getType()->isIncompleteArrayType()) {
4268 InitTy = Entity.getType().getNonReferenceType();
4269 // When we're generating initializer lists for incomplete array types we
4270 // need to wrap around both when building the initializers and when
4271 // generating the final initializer lists.
4272 if (Wrap) {
4273 assert(InitTy->isIncompleteArrayType());
4274 const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType(InitTy);
4275 InitTy = IAT->getElementType();
4276 }
4277 BuildFlattenedTypeList(InitTy, DestTypes);
4278 DstIt = DestTypes.begin();
4279 }
4280
4281 bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }
4282
4283 Expr *generateInitLists() {
4284 assert(!ArgExprs.empty() &&
4285 "Call buildInitializerList to generate argument expressions.");
4286 ArgIt = ArgExprs.begin();
4287 if (!Wrap)
4288 return generateInitListsImpl(InitTy);
4289 llvm::SmallVector<Expr *> Inits;
4290 while (ArgIt != ArgExprs.end())
4291 Inits.push_back(generateInitListsImpl(InitTy));
4292
4293 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4294 Inits, Inits.back()->getEndLoc());
4295 llvm::APInt ArySize(64, Inits.size());
4296 NewInit->setType(Ctx.getConstantArrayType(InitTy, ArySize, nullptr,
4297 ArraySizeModifier::Normal, 0));
4298 return NewInit;
4299 }
4300};
4301} // namespace
4302
4304 InitListExpr *Init) {
4305 // If the initializer is a scalar, just return it.
4306 if (Init->getType()->isScalarType())
4307 return true;
4308 ASTContext &Ctx = SemaRef.getASTContext();
4309 InitListTransformer ILT(SemaRef, Entity);
4310
4311 for (unsigned I = 0; I < Init->getNumInits(); ++I) {
4312 Expr *E = Init->getInit(I);
4313 if (E->HasSideEffects(Ctx)) {
4314 QualType Ty = E->getType();
4315 if (Ty->isRecordType())
4316 E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());
4317 E = new (Ctx) OpaqueValueExpr(E->getBeginLoc(), Ty, E->getValueKind(),
4318 E->getObjectKind(), E);
4319 Init->setInit(I, E);
4320 }
4321 if (!ILT.buildInitializerList(E))
4322 return false;
4323 }
4324 size_t ExpectedSize = ILT.DestTypes.size();
4325 size_t ActualSize = ILT.ArgExprs.size();
4326 if (ExpectedSize == 0 && ActualSize == 0)
4327 return true;
4328
4329 // For incomplete arrays it is completely arbitrary to choose whether we think
4330 // the user intended fewer or more elements. This implementation assumes that
4331 // the user intended more, and errors that there are too few initializers to
4332 // complete the final element.
4333 if (Entity.getType()->isIncompleteArrayType())
4334 ExpectedSize =
4335 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4336
4337 // An initializer list might be attempting to initialize a reference or
4338 // rvalue-reference. When checking the initializer we should look through
4339 // the reference.
4340 QualType InitTy = Entity.getType().getNonReferenceType();
4341 if (InitTy.hasAddressSpace())
4342 InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4343 if (ExpectedSize != ActualSize) {
4344 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4345 SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4346 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4347 return false;
4348 }
4349
4350 // generateInitListsImpl will always return an InitListExpr here, because the
4351 // scalar case is handled above.
4352 auto *NewInit = cast<InitListExpr>(ILT.generateInitLists());
4353 Init->resizeInits(Ctx, NewInit->getNumInits());
4354 for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
4355 Init->updateInit(Ctx, I, NewInit->getInit(I));
4356 return true;
4357}
4358
4360 const HLSLVkConstantIdAttr *ConstIdAttr =
4361 VDecl->getAttr<HLSLVkConstantIdAttr>();
4362 if (!ConstIdAttr)
4363 return true;
4364
4365 ASTContext &Context = SemaRef.getASTContext();
4366
4367 APValue InitValue;
4368 if (!Init->isCXX11ConstantExpr(Context, &InitValue)) {
4369 Diag(VDecl->getLocation(), diag::err_specialization_const);
4370 VDecl->setInvalidDecl();
4371 return false;
4372 }
4373
4374 Builtin::ID BID =
4376
4377 // Argument 1: The ID from the attribute
4378 int ConstantID = ConstIdAttr->getId();
4379 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4380 Expr *IdExpr = IntegerLiteral::Create(Context, IDVal, Context.IntTy,
4381 ConstIdAttr->getLocation());
4382
4383 SmallVector<Expr *, 2> Args = {IdExpr, Init};
4384 Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);
4385 if (C->getType()->getCanonicalTypeUnqualified() !=
4387 C = SemaRef
4388 .BuildCStyleCastExpr(SourceLocation(),
4389 Context.getTrivialTypeSourceInfo(
4390 Init->getType(), Init->getExprLoc()),
4391 SourceLocation(), C)
4392 .get();
4393 }
4394 Init = C;
4395 return true;
4396}
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
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
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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
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
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:178
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:4689
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:3268
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:4246
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:3815
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2211
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3188
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:3235
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:5825
void addLayoutStruct(CXXRecordDecl *LS)
Definition Decl.cpp:5865
void setHasValidPackoffset(bool PO)
Definition Decl.h:5221
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
Definition Decl.cpp:5848
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:5524
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
Definition Decl.cpp:5911
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:3555
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:8278
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8404
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:8463
QualType getCanonicalType() const
Definition TypeBase.h:8330
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8372
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition TypeBase.h:8399
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:5202
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
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
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 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:9306
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
Definition Sema.h:9314
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:362
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:338
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:350
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:4895
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:8249
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isVoidType() const
Definition TypeBase.h:8871
bool isBooleanType() const
Definition TypeBase.h:9001
bool isIncompleteArrayType() const
Definition TypeBase.h:8622
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:8618
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:8614
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
bool isArithmeticType() const
Definition Type.cpp:2337
bool isHLSLBuiltinIntangibleType() const
Definition TypeBase.h:8816
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8915
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
bool isReferenceType() const
Definition TypeBase.h:8539
bool isHLSLIntangibleType() const
Definition Type.cpp:5375
bool isEnumeralType() const
Definition TypeBase.h:8646
bool isScalarType() const
Definition TypeBase.h:8973
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:5362
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:8654
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2320
bool isHLSLAttributedResourceType() const
Definition TypeBase.h:8828
@ 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:8749
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
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:8642
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5366
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