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