Thanks to visit codestin.com
Credit goes to clang.llvm.org

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