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::HLSLIsCounter:
1814 if (ResAttrs.IsCounter) {
1815 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1816 return false;
1817 }
1818 ResAttrs.IsCounter = true;
1819 break;
1820 case attr::HLSLContainedType: {
1821 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
1822 QualType Ty = CTAttr->getType();
1823 if (!ContainedTy.isNull()) {
1824 S.Diag(A->getLocation(), ContainedTy == Ty
1825 ? diag::warn_duplicate_attribute_exact
1826 : diag::warn_duplicate_attribute)
1827 << A;
1828 return false;
1829 }
1830 ContainedTy = Ty;
1831 ContainedTyInfo = CTAttr->getTypeLoc();
1832 break;
1833 }
1834 default:
1835 llvm_unreachable("unhandled resource attribute type");
1836 }
1837 }
1838
1839 if (!HasResourceClass) {
1840 S.Diag(AttrList.back()->getRange().getEnd(),
1841 diag::err_hlsl_missing_resource_class);
1842 return false;
1843 }
1844
1846 Wrapped, ContainedTy, ResAttrs);
1847
1848 if (LocInfo && ContainedTyInfo) {
1849 LocInfo->Range = SourceRange(LocBegin, LocEnd);
1850 LocInfo->ContainedTyInfo = ContainedTyInfo;
1851 }
1852 return true;
1853}
1854
1855// Validates and creates an HLSL attribute that is applied as type attribute on
1856// HLSL resource. The attributes are collected in HLSLResourcesTypeAttrs and at
1857// the end of the declaration they are applied to the declaration type by
1858// wrapping it in HLSLAttributedResourceType.
1860 // only allow resource type attributes on intangible types
1861 if (!T->isHLSLResourceType()) {
1862 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1863 << AL << getASTContext().HLSLResourceTy;
1864 return false;
1865 }
1866
1867 // validate number of arguments
1868 if (!AL.checkExactlyNumArgs(SemaRef, AL.getMinArgs()))
1869 return false;
1870
1871 Attr *A = nullptr;
1872
1876 {
1877 AttributeCommonInfo::AS_CXX11, 0, false /*IsAlignas*/,
1878 false /*IsRegularKeywordAttribute*/
1879 });
1880
1881 switch (AL.getKind()) {
1882 case ParsedAttr::AT_HLSLResourceClass: {
1883 if (!AL.isArgIdent(0)) {
1884 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1885 << AL << AANT_ArgumentIdentifier;
1886 return false;
1887 }
1888
1889 IdentifierLoc *Loc = AL.getArgAsIdent(0);
1890 StringRef Identifier = Loc->getIdentifierInfo()->getName();
1891 SourceLocation ArgLoc = Loc->getLoc();
1892
1893 // Validate resource class value
1894 ResourceClass RC;
1895 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1896 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1897 << "ResourceClass" << Identifier;
1898 return false;
1899 }
1900 A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);
1901 break;
1902 }
1903
1904 case ParsedAttr::AT_HLSLROV:
1905 A = HLSLROVAttr::Create(getASTContext(), ACI);
1906 break;
1907
1908 case ParsedAttr::AT_HLSLRawBuffer:
1909 A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
1910 break;
1911
1912 case ParsedAttr::AT_HLSLIsCounter:
1913 A = HLSLIsCounterAttr::Create(getASTContext(), ACI);
1914 break;
1915
1916 case ParsedAttr::AT_HLSLContainedType: {
1917 if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {
1918 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1919 return false;
1920 }
1921
1922 TypeSourceInfo *TSI = nullptr;
1923 QualType QT = SemaRef.GetTypeFromParser(AL.getTypeArg(), &TSI);
1924 assert(TSI && "no type source info for attribute argument");
1925 if (SemaRef.RequireCompleteType(TSI->getTypeLoc().getBeginLoc(), QT,
1926 diag::err_incomplete_type))
1927 return false;
1928 A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);
1929 break;
1930 }
1931
1932 default:
1933 llvm_unreachable("unhandled HLSL attribute");
1934 }
1935
1936 HLSLResourcesTypeAttrs.emplace_back(A);
1937 return true;
1938}
1939
1940// Combines all resource type attributes and creates HLSLAttributedResourceType.
1942 if (!HLSLResourcesTypeAttrs.size())
1943 return CurrentType;
1944
1945 QualType QT = CurrentType;
1948 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1949 const HLSLAttributedResourceType *RT =
1951
1952 // Temporarily store TypeLoc information for the new type.
1953 // It will be transferred to HLSLAttributesResourceTypeLoc
1954 // shortly after the type is created by TypeSpecLocFiller which
1955 // will call the TakeLocForHLSLAttribute method below.
1956 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1957 }
1958 HLSLResourcesTypeAttrs.clear();
1959 return QT;
1960}
1961
1962// Returns source location for the HLSLAttributedResourceType
1964SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) {
1965 HLSLAttributedResourceLocInfo LocInfo = {};
1966 auto I = LocsForHLSLAttributedResources.find(RT);
1967 if (I != LocsForHLSLAttributedResources.end()) {
1968 LocInfo = I->second;
1969 LocsForHLSLAttributedResources.erase(I);
1970 return LocInfo;
1971 }
1972 LocInfo.Range = SourceRange();
1973 return LocInfo;
1974}
1975
1976// Walks though the global variable declaration, collects all resource binding
1977// requirements and adds them to Bindings
1978void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
1979 const RecordType *RT) {
1980 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1981 for (FieldDecl *FD : RD->fields()) {
1982 const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();
1983
1984 // Unwrap arrays
1985 // FIXME: Calculate array size while unwrapping
1986 assert(!Ty->isIncompleteArrayType() &&
1987 "incomplete arrays inside user defined types are not supported");
1988 while (Ty->isConstantArrayType()) {
1991 }
1992
1993 if (!Ty->isRecordType())
1994 continue;
1995
1996 if (const HLSLAttributedResourceType *AttrResType =
1997 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
1998 // Add a new DeclBindingInfo to Bindings if it does not already exist
1999 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
2000 DeclBindingInfo *DBI = Bindings.getDeclBindingInfo(VD, RC);
2001 if (!DBI)
2002 Bindings.addDeclBindingInfo(VD, RC);
2003 } else if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2004 // Recursively scan embedded struct or class; it would be nice to do this
2005 // without recursion, but tricky to correctly calculate the size of the
2006 // binding, which is something we are probably going to need to do later
2007 // on. Hopefully nesting of structs in structs too many levels is
2008 // unlikely.
2009 collectResourceBindingsOnUserRecordDecl(VD, RT);
2010 }
2011 }
2012}
2013
2014// Diagnose localized register binding errors for a single binding; does not
2015// diagnose resource binding on user record types, that will be done later
2016// in processResourceBindingOnDecl based on the information collected in
2017// collectResourceBindingsOnVarDecl.
2018// Returns false if the register binding is not valid.
2020 Decl *D, RegisterType RegType,
2021 bool SpecifiedSpace) {
2022 int RegTypeNum = static_cast<int>(RegType);
2023
2024 // check if the decl type is groupshared
2025 if (D->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2026 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2027 return false;
2028 }
2029
2030 // Cbuffers and Tbuffers are HLSLBufferDecl types
2031 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2032 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2033 : ResourceClass::SRV;
2034 if (RegType == getRegisterType(RC))
2035 return true;
2036
2037 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
2038 << RegTypeNum;
2039 return false;
2040 }
2041
2042 // Samplers, UAVs, and SRVs are VarDecl types
2043 assert(isa<VarDecl>(D) && "D is expected to be VarDecl or HLSLBufferDecl");
2044 VarDecl *VD = cast<VarDecl>(D);
2045
2046 // Resource
2047 if (const HLSLAttributedResourceType *AttrResType =
2048 HLSLAttributedResourceType::findHandleTypeOnResource(
2049 VD->getType().getTypePtr())) {
2050 if (RegType == getRegisterType(AttrResType))
2051 return true;
2052
2053 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
2054 << RegTypeNum;
2055 return false;
2056 }
2057
2058 const clang::Type *Ty = VD->getType().getTypePtr();
2059 while (Ty->isArrayType())
2061
2062 // Basic types
2063 if (Ty->isArithmeticType() || Ty->isVectorType()) {
2064 bool DeclaredInCOrTBuffer = isa<HLSLBufferDecl>(D->getDeclContext());
2065 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2066 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2067
2068 if (!DeclaredInCOrTBuffer && (Ty->isIntegralType(S.getASTContext()) ||
2069 Ty->isFloatingType() || Ty->isVectorType())) {
2070 // Register annotation on default constant buffer declaration ($Globals)
2071 if (RegType == RegisterType::CBuffer)
2072 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2073 else if (RegType != RegisterType::C)
2074 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2075 else
2076 return true;
2077 } else {
2078 if (RegType == RegisterType::C)
2079 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2080 else
2081 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2082 }
2083 return false;
2084 }
2085 if (Ty->isRecordType())
2086 // RecordTypes will be diagnosed in processResourceBindingOnDecl
2087 // that is called from ActOnVariableDeclarator
2088 return true;
2089
2090 // Anything else is an error
2091 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2092 return false;
2093}
2094
2096 RegisterType regType) {
2097 // make sure that there are no two register annotations
2098 // applied to the decl with the same register type
2099 bool RegisterTypesDetected[5] = {false};
2100 RegisterTypesDetected[static_cast<int>(regType)] = true;
2101
2102 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {
2103 if (HLSLResourceBindingAttr *attr =
2104 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2105
2106 RegisterType otherRegType = attr->getRegisterType();
2107 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {
2108 int otherRegTypeNum = static_cast<int>(otherRegType);
2109 S.Diag(TheDecl->getLocation(),
2110 diag::err_hlsl_duplicate_register_annotation)
2111 << otherRegTypeNum;
2112 return false;
2113 }
2114 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;
2115 }
2116 }
2117 return true;
2118}
2119
2121 Decl *D, RegisterType RegType,
2122 bool SpecifiedSpace) {
2123
2124 // exactly one of these two types should be set
2125 assert(((isa<VarDecl>(D) && !isa<HLSLBufferDecl>(D)) ||
2126 (!isa<VarDecl>(D) && isa<HLSLBufferDecl>(D))) &&
2127 "expecting VarDecl or HLSLBufferDecl");
2128
2129 // check if the declaration contains resource matching the register type
2130 if (!DiagnoseLocalRegisterBinding(S, ArgLoc, D, RegType, SpecifiedSpace))
2131 return false;
2132
2133 // next, if multiple register annotations exist, check that none conflict.
2134 return ValidateMultipleRegisterAnnotations(S, D, RegType);
2135}
2136
2138 if (VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2139 QualType Ty = VD->getType();
2140 if (const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2141 Ty = IAT->getElementType();
2142 if (SemaRef.RequireCompleteType(TheDecl->getBeginLoc(), Ty,
2143 diag::err_incomplete_type))
2144 return;
2145 }
2146
2147 StringRef Slot = "";
2148 StringRef Space = "";
2149 SourceLocation SlotLoc, SpaceLoc;
2150
2151 if (!AL.isArgIdent(0)) {
2152 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2153 << AL << AANT_ArgumentIdentifier;
2154 return;
2155 }
2156 IdentifierLoc *Loc = AL.getArgAsIdent(0);
2157
2158 if (AL.getNumArgs() == 2) {
2159 Slot = Loc->getIdentifierInfo()->getName();
2160 SlotLoc = Loc->getLoc();
2161 if (!AL.isArgIdent(1)) {
2162 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2163 << AL << AANT_ArgumentIdentifier;
2164 return;
2165 }
2166 Loc = AL.getArgAsIdent(1);
2167 Space = Loc->getIdentifierInfo()->getName();
2168 SpaceLoc = Loc->getLoc();
2169 } else {
2170 StringRef Str = Loc->getIdentifierInfo()->getName();
2171 if (Str.starts_with("space")) {
2172 Space = Str;
2173 SpaceLoc = Loc->getLoc();
2174 } else {
2175 Slot = Str;
2176 SlotLoc = Loc->getLoc();
2177 Space = "space0";
2178 }
2179 }
2180
2181 RegisterType RegType = RegisterType::SRV;
2182 std::optional<unsigned> SlotNum;
2183 unsigned SpaceNum = 0;
2184
2185 // Validate slot
2186 if (!Slot.empty()) {
2187 if (!convertToRegisterType(Slot, &RegType)) {
2188 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2189 return;
2190 }
2191 if (RegType == RegisterType::I) {
2192 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2193 return;
2194 }
2195 StringRef SlotNumStr = Slot.substr(1);
2196 unsigned N;
2197 if (SlotNumStr.getAsInteger(10, N)) {
2198 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2199 return;
2200 }
2201 SlotNum = N;
2202 }
2203
2204 // Validate space
2205 if (!Space.starts_with("space")) {
2206 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2207 return;
2208 }
2209 StringRef SpaceNumStr = Space.substr(5);
2210 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2211 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2212 return;
2213 }
2214
2215 // If we have slot, diagnose it is the right register type for the decl
2216 if (SlotNum.has_value())
2217 if (!DiagnoseHLSLRegisterAttribute(SemaRef, SlotLoc, TheDecl, RegType,
2218 !SpaceLoc.isInvalid()))
2219 return;
2220
2221 HLSLResourceBindingAttr *NewAttr =
2222 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
2223 if (NewAttr) {
2224 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2225 TheDecl->addAttr(NewAttr);
2226 }
2227}
2228
2230 HLSLParamModifierAttr *NewAttr = mergeParamModifierAttr(
2231 D, AL,
2232 static_cast<HLSLParamModifierAttr::Spelling>(AL.getSemanticSpelling()));
2233 if (NewAttr)
2234 D->addAttr(NewAttr);
2235}
2236
2237namespace {
2238
2239/// This class implements HLSL availability diagnostics for default
2240/// and relaxed mode
2241///
2242/// The goal of this diagnostic is to emit an error or warning when an
2243/// unavailable API is found in code that is reachable from the shader
2244/// entry function or from an exported function (when compiling a shader
2245/// library).
2246///
2247/// This is done by traversing the AST of all shader entry point functions
2248/// and of all exported functions, and any functions that are referenced
2249/// from this AST. In other words, any functions that are reachable from
2250/// the entry points.
2251class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
2252 Sema &SemaRef;
2253
2254 // Stack of functions to be scaned
2256
2257 // Tracks which environments functions have been scanned in.
2258 //
2259 // Maps FunctionDecl to an unsigned number that represents the set of shader
2260 // environments the function has been scanned for.
2261 // The llvm::Triple::EnvironmentType enum values for shader stages guaranteed
2262 // to be numbered from llvm::Triple::Pixel to llvm::Triple::Amplification
2263 // (verified by static_asserts in Triple.cpp), we can use it to index
2264 // individual bits in the set, as long as we shift the values to start with 0
2265 // by subtracting the value of llvm::Triple::Pixel first.
2266 //
2267 // The N'th bit in the set will be set if the function has been scanned
2268 // in shader environment whose llvm::Triple::EnvironmentType integer value
2269 // equals (llvm::Triple::Pixel + N).
2270 //
2271 // For example, if a function has been scanned in compute and pixel stage
2272 // environment, the value will be 0x21 (100001 binary) because:
2273 //
2274 // (int)(llvm::Triple::Pixel - llvm::Triple::Pixel) == 0
2275 // (int)(llvm::Triple::Compute - llvm::Triple::Pixel) == 5
2276 //
2277 // A FunctionDecl is mapped to 0 (or not included in the map) if it has not
2278 // been scanned in any environment.
2279 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2280
2281 // Do not access these directly, use the get/set methods below to make
2282 // sure the values are in sync
2283 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2284 unsigned CurrentShaderStageBit;
2285
2286 // True if scanning a function that was already scanned in a different
2287 // shader stage context, and therefore we should not report issues that
2288 // depend only on shader model version because they would be duplicate.
2289 bool ReportOnlyShaderStageIssues;
2290
2291 // Helper methods for dealing with current stage context / environment
2292 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2293 static_assert(sizeof(unsigned) >= 4);
2294 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2295 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2296 "ShaderType is too big for this bitmap"); // 31 is reserved for
2297 // "unknown"
2298
2299 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2300 CurrentShaderEnvironment = ShaderType;
2301 CurrentShaderStageBit = (1 << bitmapIndex);
2302 }
2303
2304 void SetUnknownShaderStageContext() {
2305 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2306 CurrentShaderStageBit = (1 << 31);
2307 }
2308
2309 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
2310 return CurrentShaderEnvironment;
2311 }
2312
2313 bool InUnknownShaderStageContext() const {
2314 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2315 }
2316
2317 // Helper methods for dealing with shader stage bitmap
2318 void AddToScannedFunctions(const FunctionDecl *FD) {
2319 unsigned &ScannedStages = ScannedDecls[FD];
2320 ScannedStages |= CurrentShaderStageBit;
2321 }
2322
2323 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }
2324
2325 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
2326 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2327 }
2328
2329 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
2330 return ScannerStages & CurrentShaderStageBit;
2331 }
2332
2333 static bool NeverBeenScanned(unsigned ScannedStages) {
2334 return ScannedStages == 0;
2335 }
2336
2337 // Scanning methods
2338 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2339 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
2340 SourceRange Range);
2341 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
2342 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
2343
2344public:
2345 DiagnoseHLSLAvailability(Sema &SemaRef)
2346 : SemaRef(SemaRef),
2347 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2348 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
2349
2350 // AST traversal methods
2351 void RunOnTranslationUnit(const TranslationUnitDecl *TU);
2352 void RunOnFunction(const FunctionDecl *FD);
2353
2354 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
2355 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());
2356 if (FD)
2357 HandleFunctionOrMethodRef(FD, DRE);
2358 return true;
2359 }
2360
2361 bool VisitMemberExpr(MemberExpr *ME) override {
2362 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());
2363 if (FD)
2364 HandleFunctionOrMethodRef(FD, ME);
2365 return true;
2366 }
2367};
2368
2369void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
2370 Expr *RefExpr) {
2371 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
2372 "expected DeclRefExpr or MemberExpr");
2373
2374 // has a definition -> add to stack to be scanned
2375 const FunctionDecl *FDWithBody = nullptr;
2376 if (FD->hasBody(FDWithBody)) {
2377 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2378 DeclsToScan.push_back(FDWithBody);
2379 return;
2380 }
2381
2382 // no body -> diagnose availability
2383 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2384 if (AA)
2385 CheckDeclAvailability(
2386 FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));
2387}
2388
2389void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2390 const TranslationUnitDecl *TU) {
2391
2392 // Iterate over all shader entry functions and library exports, and for those
2393 // that have a body (definiton), run diag scan on each, setting appropriate
2394 // shader environment context based on whether it is a shader entry function
2395 // or an exported function. Exported functions can be in namespaces and in
2396 // export declarations so we need to scan those declaration contexts as well.
2398 DeclContextsToScan.push_back(TU);
2399
2400 while (!DeclContextsToScan.empty()) {
2401 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2402 for (auto &D : DC->decls()) {
2403 // do not scan implicit declaration generated by the implementation
2404 if (D->isImplicit())
2405 continue;
2406
2407 // for namespace or export declaration add the context to the list to be
2408 // scanned later
2409 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2410 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2411 continue;
2412 }
2413
2414 // skip over other decls or function decls without body
2415 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2416 if (!FD || !FD->isThisDeclarationADefinition())
2417 continue;
2418
2419 // shader entry point
2420 if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) {
2421 SetShaderStageContext(ShaderAttr->getType());
2422 RunOnFunction(FD);
2423 continue;
2424 }
2425 // exported library function
2426 // FIXME: replace this loop with external linkage check once issue #92071
2427 // is resolved
2428 bool isExport = FD->isInExportDeclContext();
2429 if (!isExport) {
2430 for (const auto *Redecl : FD->redecls()) {
2431 if (Redecl->isInExportDeclContext()) {
2432 isExport = true;
2433 break;
2434 }
2435 }
2436 }
2437 if (isExport) {
2438 SetUnknownShaderStageContext();
2439 RunOnFunction(FD);
2440 continue;
2441 }
2442 }
2443 }
2444}
2445
2446void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
2447 assert(DeclsToScan.empty() && "DeclsToScan should be empty");
2448 DeclsToScan.push_back(FD);
2449
2450 while (!DeclsToScan.empty()) {
2451 // Take one decl from the stack and check it by traversing its AST.
2452 // For any CallExpr found during the traversal add it's callee to the top of
2453 // the stack to be processed next. Functions already processed are stored in
2454 // ScannedDecls.
2455 const FunctionDecl *FD = DeclsToScan.pop_back_val();
2456
2457 // Decl was already scanned
2458 const unsigned ScannedStages = GetScannedStages(FD);
2459 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2460 continue;
2461
2462 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2463
2464 AddToScannedFunctions(FD);
2465 TraverseStmt(FD->getBody());
2466 }
2467}
2468
2469bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2470 const AvailabilityAttr *AA) {
2471 IdentifierInfo *IIEnvironment = AA->getEnvironment();
2472 if (!IIEnvironment)
2473 return true;
2474
2475 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2476 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2477 return false;
2478
2479 llvm::Triple::EnvironmentType AttrEnv =
2480 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
2481
2482 return CurrentEnv == AttrEnv;
2483}
2484
2485const AvailabilityAttr *
2486DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
2487 AvailabilityAttr const *PartialMatch = nullptr;
2488 // Check each AvailabilityAttr to find the one for this platform.
2489 // For multiple attributes with the same platform try to find one for this
2490 // environment.
2491 for (const auto *A : D->attrs()) {
2492 if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2493 StringRef AttrPlatform = Avail->getPlatform()->getName();
2494 StringRef TargetPlatform =
2496
2497 // Match the platform name.
2498 if (AttrPlatform == TargetPlatform) {
2499 // Find the best matching attribute for this environment
2500 if (HasMatchingEnvironmentOrNone(Avail))
2501 return Avail;
2502 PartialMatch = Avail;
2503 }
2504 }
2505 }
2506 return PartialMatch;
2507}
2508
2509// Check availability against target shader model version and current shader
2510// stage and emit diagnostic
2511void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
2512 const AvailabilityAttr *AA,
2513 SourceRange Range) {
2514
2515 IdentifierInfo *IIEnv = AA->getEnvironment();
2516
2517 if (!IIEnv) {
2518 // The availability attribute does not have environment -> it depends only
2519 // on shader model version and not on specific the shader stage.
2520
2521 // Skip emitting the diagnostics if the diagnostic mode is set to
2522 // strict (-fhlsl-strict-availability) because all relevant diagnostics
2523 // were already emitted in the DiagnoseUnguardedAvailability scan
2524 // (SemaAvailability.cpp).
2525 if (SemaRef.getLangOpts().HLSLStrictAvailability)
2526 return;
2527
2528 // Do not report shader-stage-independent issues if scanning a function
2529 // that was already scanned in a different shader stage context (they would
2530 // be duplicate)
2531 if (ReportOnlyShaderStageIssues)
2532 return;
2533
2534 } else {
2535 // The availability attribute has environment -> we need to know
2536 // the current stage context to property diagnose it.
2537 if (InUnknownShaderStageContext())
2538 return;
2539 }
2540
2541 // Check introduced version and if environment matches
2542 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2543 VersionTuple Introduced = AA->getIntroduced();
2544 VersionTuple TargetVersion =
2546
2547 if (TargetVersion >= Introduced && EnvironmentMatches)
2548 return;
2549
2550 // Emit diagnostic message
2551 const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
2552 llvm::StringRef PlatformName(
2553 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
2554
2555 llvm::StringRef CurrentEnvStr =
2556 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2557
2558 llvm::StringRef AttrEnvStr =
2559 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";
2560 bool UseEnvironment = !AttrEnvStr.empty();
2561
2562 if (EnvironmentMatches) {
2563 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)
2564 << Range << D << PlatformName << Introduced.getAsString()
2565 << UseEnvironment << CurrentEnvStr;
2566 } else {
2567 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2568 << Range << D;
2569 }
2570
2571 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
2572 << D << PlatformName << Introduced.getAsString()
2573 << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
2574 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2575}
2576
2577} // namespace
2578
2580 // process default CBuffer - create buffer layout struct and invoke codegenCGH
2581 if (!DefaultCBufferDecls.empty()) {
2583 SemaRef.getASTContext(), SemaRef.getCurLexicalContext(),
2584 DefaultCBufferDecls);
2585 addImplicitBindingAttrToDecl(SemaRef, DefaultCBuffer, RegisterType::CBuffer,
2586 getNextImplicitBindingOrderID());
2587 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2589
2590 // Set HasValidPackoffset if any of the decls has a register(c#) annotation;
2591 for (const Decl *VD : DefaultCBufferDecls) {
2592 const HLSLResourceBindingAttr *RBA =
2593 VD->getAttr<HLSLResourceBindingAttr>();
2594 if (RBA && RBA->hasRegisterSlot() &&
2595 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2596 DefaultCBuffer->setHasValidPackoffset(true);
2597 break;
2598 }
2599 }
2600
2601 DeclGroupRef DG(DefaultCBuffer);
2602 SemaRef.Consumer.HandleTopLevelDecl(DG);
2603 }
2604 diagnoseAvailabilityViolations(TU);
2605}
2606
2607void SemaHLSL::diagnoseAvailabilityViolations(TranslationUnitDecl *TU) {
2608 // Skip running the diagnostics scan if the diagnostic mode is
2609 // strict (-fhlsl-strict-availability) and the target shader stage is known
2610 // because all relevant diagnostics were already emitted in the
2611 // DiagnoseUnguardedAvailability scan (SemaAvailability.cpp).
2613 if (SemaRef.getLangOpts().HLSLStrictAvailability &&
2614 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2615 return;
2616
2617 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
2618}
2619
2620static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {
2621 assert(TheCall->getNumArgs() > 1);
2622 QualType ArgTy0 = TheCall->getArg(0)->getType();
2623
2624 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {
2626 ArgTy0, TheCall->getArg(I)->getType())) {
2627 S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2628 << TheCall->getDirectCallee() << /*useAllTerminology*/ true
2629 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
2630 TheCall->getArg(N - 1)->getEndLoc());
2631 return true;
2632 }
2633 }
2634 return false;
2635}
2636
2638 QualType ArgType = Arg->getType();
2640 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
2641 << ArgType << ExpectedType << 1 << 0 << 0;
2642 return true;
2643 }
2644 return false;
2645}
2646
2648 Sema *S, CallExpr *TheCall,
2649 llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,
2650 clang::QualType PassedType)>
2651 Check) {
2652 for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {
2653 Expr *Arg = TheCall->getArg(I);
2654 if (Check(S, Arg->getBeginLoc(), I + 1, Arg->getType()))
2655 return true;
2656 }
2657 return false;
2658}
2659
2661 int ArgOrdinal,
2662 clang::QualType PassedType) {
2663 clang::QualType BaseType =
2664 PassedType->isVectorType()
2665 ? PassedType->castAs<clang::VectorType>()->getElementType()
2666 : PassedType;
2667 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2668 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2669 << ArgOrdinal << /* scalar or vector of */ 5 << /* no int */ 0
2670 << /* half or float */ 2 << PassedType;
2671 return false;
2672}
2673
2674static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall,
2675 unsigned ArgIndex) {
2676 auto *Arg = TheCall->getArg(ArgIndex);
2677 SourceLocation OrigLoc = Arg->getExprLoc();
2678 if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==
2680 return false;
2681 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2682 return true;
2683}
2684
2685static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal,
2686 clang::QualType PassedType) {
2687 const auto *VecTy = PassedType->getAs<VectorType>();
2688 if (!VecTy)
2689 return false;
2690
2691 if (VecTy->getElementType()->isDoubleType())
2692 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2693 << ArgOrdinal << /* scalar */ 1 << /* no int */ 0 << /* fp */ 1
2694 << PassedType;
2695 return false;
2696}
2697
2699 int ArgOrdinal,
2700 clang::QualType PassedType) {
2701 if (!PassedType->hasIntegerRepresentation() &&
2702 !PassedType->hasFloatingRepresentation())
2703 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2704 << ArgOrdinal << /* scalar or vector of */ 5 << /* integer */ 1
2705 << /* fp */ 1 << PassedType;
2706 return false;
2707}
2708
2710 int ArgOrdinal,
2711 clang::QualType PassedType) {
2712 if (auto *VecTy = PassedType->getAs<VectorType>())
2713 if (VecTy->getElementType()->isUnsignedIntegerType())
2714 return false;
2715
2716 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2717 << ArgOrdinal << /* vector of */ 4 << /* uint */ 3 << /* no fp */ 0
2718 << PassedType;
2719}
2720
2721// checks for unsigned ints of all sizes
2723 int ArgOrdinal,
2724 clang::QualType PassedType) {
2725 if (!PassedType->hasUnsignedIntegerRepresentation())
2726 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2727 << ArgOrdinal << /* scalar or vector of */ 5 << /* unsigned int */ 3
2728 << /* no fp */ 0 << PassedType;
2729 return false;
2730}
2731
2733 QualType ReturnType) {
2734 auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
2735 if (VecTyA)
2736 ReturnType =
2737 S->Context.getExtVectorType(ReturnType, VecTyA->getNumElements());
2738
2739 TheCall->setType(ReturnType);
2740}
2741
2742static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar,
2743 unsigned ArgIndex) {
2744 assert(TheCall->getNumArgs() >= ArgIndex);
2745 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2746 auto *VTy = ArgType->getAs<VectorType>();
2747 // not the scalar or vector<scalar>
2748 if (!(S->Context.hasSameUnqualifiedType(ArgType, Scalar) ||
2749 (VTy &&
2750 S->Context.hasSameUnqualifiedType(VTy->getElementType(), Scalar)))) {
2751 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2752 diag::err_typecheck_expect_scalar_or_vector)
2753 << ArgType << Scalar;
2754 return true;
2755 }
2756 return false;
2757}
2758
2759static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall,
2760 unsigned ArgIndex) {
2761 assert(TheCall->getNumArgs() >= ArgIndex);
2762 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2763 auto *VTy = ArgType->getAs<VectorType>();
2764 // not the scalar or vector<scalar>
2765 if (!(ArgType->isScalarType() ||
2766 (VTy && VTy->getElementType()->isScalarType()))) {
2767 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2768 diag::err_typecheck_expect_any_scalar_or_vector)
2769 << ArgType << 1;
2770 return true;
2771 }
2772 return false;
2773}
2774
2775static bool CheckWaveActive(Sema *S, CallExpr *TheCall) {
2776 QualType BoolType = S->getASTContext().BoolTy;
2777 assert(TheCall->getNumArgs() >= 1);
2778 QualType ArgType = TheCall->getArg(0)->getType();
2779 auto *VTy = ArgType->getAs<VectorType>();
2780 // is the bool or vector<bool>
2781 if (S->Context.hasSameUnqualifiedType(ArgType, BoolType) ||
2782 (VTy &&
2783 S->Context.hasSameUnqualifiedType(VTy->getElementType(), BoolType))) {
2784 S->Diag(TheCall->getArg(0)->getBeginLoc(),
2785 diag::err_typecheck_expect_any_scalar_or_vector)
2786 << ArgType << 0;
2787 return true;
2788 }
2789 return false;
2790}
2791
2792static bool CheckBoolSelect(Sema *S, CallExpr *TheCall) {
2793 assert(TheCall->getNumArgs() == 3);
2794 Expr *Arg1 = TheCall->getArg(1);
2795 Expr *Arg2 = TheCall->getArg(2);
2796 if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), Arg2->getType())) {
2797 S->Diag(TheCall->getBeginLoc(),
2798 diag::err_typecheck_call_different_arg_types)
2799 << Arg1->getType() << Arg2->getType() << Arg1->getSourceRange()
2800 << Arg2->getSourceRange();
2801 return true;
2802 }
2803
2804 TheCall->setType(Arg1->getType());
2805 return false;
2806}
2807
2808static bool CheckVectorSelect(Sema *S, CallExpr *TheCall) {
2809 assert(TheCall->getNumArgs() == 3);
2810 Expr *Arg1 = TheCall->getArg(1);
2811 QualType Arg1Ty = Arg1->getType();
2812 Expr *Arg2 = TheCall->getArg(2);
2813 QualType Arg2Ty = Arg2->getType();
2814
2815 QualType Arg1ScalarTy = Arg1Ty;
2816 if (auto VTy = Arg1ScalarTy->getAs<VectorType>())
2817 Arg1ScalarTy = VTy->getElementType();
2818
2819 QualType Arg2ScalarTy = Arg2Ty;
2820 if (auto VTy = Arg2ScalarTy->getAs<VectorType>())
2821 Arg2ScalarTy = VTy->getElementType();
2822
2823 if (!S->Context.hasSameUnqualifiedType(Arg1ScalarTy, Arg2ScalarTy))
2824 S->Diag(Arg1->getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2825 << /* second and third */ 1 << TheCall->getCallee() << Arg1Ty << Arg2Ty;
2826
2827 QualType Arg0Ty = TheCall->getArg(0)->getType();
2828 unsigned Arg0Length = Arg0Ty->getAs<VectorType>()->getNumElements();
2829 unsigned Arg1Length = Arg1Ty->isVectorType()
2830 ? Arg1Ty->getAs<VectorType>()->getNumElements()
2831 : 0;
2832 unsigned Arg2Length = Arg2Ty->isVectorType()
2833 ? Arg2Ty->getAs<VectorType>()->getNumElements()
2834 : 0;
2835 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2836 S->Diag(TheCall->getBeginLoc(),
2837 diag::err_typecheck_vector_lengths_not_equal)
2838 << Arg0Ty << Arg1Ty << TheCall->getArg(0)->getSourceRange()
2839 << Arg1->getSourceRange();
2840 return true;
2841 }
2842
2843 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2844 S->Diag(TheCall->getBeginLoc(),
2845 diag::err_typecheck_vector_lengths_not_equal)
2846 << Arg0Ty << Arg2Ty << TheCall->getArg(0)->getSourceRange()
2847 << Arg2->getSourceRange();
2848 return true;
2849 }
2850
2851 TheCall->setType(
2852 S->getASTContext().getExtVectorType(Arg1ScalarTy, Arg0Length));
2853 return false;
2854}
2855
2857 Sema *S, CallExpr *TheCall, unsigned ArgIndex,
2858 llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =
2859 nullptr) {
2860 assert(TheCall->getNumArgs() >= ArgIndex);
2861 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
2862 const HLSLAttributedResourceType *ResTy =
2863 ArgType.getTypePtr()->getAs<HLSLAttributedResourceType>();
2864 if (!ResTy) {
2865 S->Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),
2866 diag::err_typecheck_expect_hlsl_resource)
2867 << ArgType;
2868 return true;
2869 }
2870 if (Check && Check(ResTy)) {
2871 S->Diag(TheCall->getArg(ArgIndex)->getExprLoc(),
2872 diag::err_invalid_hlsl_resource_type)
2873 << ArgType;
2874 return true;
2875 }
2876 return false;
2877}
2878
2879// Note: returning true in this case results in CheckBuiltinFunctionCall
2880// returning an ExprError
2881bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
2882 switch (BuiltinID) {
2883 case Builtin::BI__builtin_hlsl_adduint64: {
2884 if (SemaRef.checkArgCount(TheCall, 2))
2885 return true;
2886
2887 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
2889 return true;
2890
2891 auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
2892 // ensure arg integers are 32-bits
2893 uint64_t ElementBitCount = getASTContext()
2894 .getTypeSizeInChars(VTy->getElementType())
2895 .getQuantity() *
2896 8;
2897 if (ElementBitCount != 32) {
2898 SemaRef.Diag(TheCall->getBeginLoc(),
2899 diag::err_integer_incorrect_bit_count)
2900 << 32 << ElementBitCount;
2901 return true;
2902 }
2903
2904 // ensure both args are vectors of total bit size of a multiple of 64
2905 int NumElementsArg = VTy->getNumElements();
2906 if (NumElementsArg != 2 && NumElementsArg != 4) {
2907 SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count)
2908 << 1 /*a multiple of*/ << 64 << NumElementsArg * ElementBitCount;
2909 return true;
2910 }
2911
2912 // ensure first arg and second arg have the same type
2913 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2914 return true;
2915
2916 ExprResult A = TheCall->getArg(0);
2917 QualType ArgTyA = A.get()->getType();
2918 // return type is the same as the input type
2919 TheCall->setType(ArgTyA);
2920 break;
2921 }
2922 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2923 if (SemaRef.checkArgCount(TheCall, 2) ||
2924 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2925 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
2926 SemaRef.getASTContext().UnsignedIntTy))
2927 return true;
2928
2929 auto *ResourceTy =
2930 TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
2931 QualType ContainedTy = ResourceTy->getContainedType();
2932 auto ReturnType =
2933 SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
2934 ReturnType = SemaRef.Context.getPointerType(ReturnType);
2935 TheCall->setType(ReturnType);
2936 TheCall->setValueKind(VK_LValue);
2937
2938 break;
2939 }
2940 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2941 if (SemaRef.checkArgCount(TheCall, 1) ||
2942 CheckResourceHandle(&SemaRef, TheCall, 0))
2943 return true;
2944 // use the type of the handle (arg0) as a return type
2945 QualType ResourceTy = TheCall->getArg(0)->getType();
2946 TheCall->setType(ResourceTy);
2947 break;
2948 }
2949 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2950 ASTContext &AST = SemaRef.getASTContext();
2951 if (SemaRef.checkArgCount(TheCall, 6) ||
2952 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2953 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
2954 CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
2955 CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
2956 CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
2957 CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
2958 AST.getPointerType(AST.CharTy.withConst())))
2959 return true;
2960 // use the type of the handle (arg0) as a return type
2961 QualType ResourceTy = TheCall->getArg(0)->getType();
2962 TheCall->setType(ResourceTy);
2963 break;
2964 }
2965 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2966 ASTContext &AST = SemaRef.getASTContext();
2967 if (SemaRef.checkArgCount(TheCall, 6) ||
2968 CheckResourceHandle(&SemaRef, TheCall, 0) ||
2969 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
2970 CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
2971 CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
2972 CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
2973 CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
2974 AST.getPointerType(AST.CharTy.withConst())))
2975 return true;
2976 // use the type of the handle (arg0) as a return type
2977 QualType ResourceTy = TheCall->getArg(0)->getType();
2978 TheCall->setType(ResourceTy);
2979 break;
2980 }
2981 case Builtin::BI__builtin_hlsl_and:
2982 case Builtin::BI__builtin_hlsl_or: {
2983 if (SemaRef.checkArgCount(TheCall, 2))
2984 return true;
2985 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
2986 return true;
2987 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
2988 return true;
2989
2990 ExprResult A = TheCall->getArg(0);
2991 QualType ArgTyA = A.get()->getType();
2992 // return type is the same as the input type
2993 TheCall->setType(ArgTyA);
2994 break;
2995 }
2996 case Builtin::BI__builtin_hlsl_all:
2997 case Builtin::BI__builtin_hlsl_any: {
2998 if (SemaRef.checkArgCount(TheCall, 1))
2999 return true;
3000 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3001 return true;
3002 break;
3003 }
3004 case Builtin::BI__builtin_hlsl_asdouble: {
3005 if (SemaRef.checkArgCount(TheCall, 2))
3006 return true;
3008 &SemaRef, TheCall,
3009 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
3010 /* arg index */ 0))
3011 return true;
3013 &SemaRef, TheCall,
3014 /*only check for uint*/ SemaRef.Context.UnsignedIntTy,
3015 /* arg index */ 1))
3016 return true;
3017 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3018 return true;
3019
3020 SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().DoubleTy);
3021 break;
3022 }
3023 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3024 if (SemaRef.BuiltinElementwiseTernaryMath(
3025 TheCall, /*ArgTyRestr=*/
3027 return true;
3028 break;
3029 }
3030 case Builtin::BI__builtin_hlsl_dot: {
3031 // arg count is checked by BuiltinVectorToScalarMath
3032 if (SemaRef.BuiltinVectorToScalarMath(TheCall))
3033 return true;
3035 return true;
3036 break;
3037 }
3038 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3039 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3040 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3041 return true;
3042
3043 const Expr *Arg = TheCall->getArg(0);
3044 QualType ArgTy = Arg->getType();
3045 QualType EltTy = ArgTy;
3046
3047 QualType ResTy = SemaRef.Context.UnsignedIntTy;
3048
3049 if (auto *VecTy = EltTy->getAs<VectorType>()) {
3050 EltTy = VecTy->getElementType();
3051 ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3052 }
3053
3054 if (!EltTy->isIntegerType()) {
3055 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
3056 << 1 << /* scalar or vector of */ 5 << /* integer ty */ 1
3057 << /* no fp */ 0 << ArgTy;
3058 return true;
3059 }
3060
3061 TheCall->setType(ResTy);
3062 break;
3063 }
3064 case Builtin::BI__builtin_hlsl_select: {
3065 if (SemaRef.checkArgCount(TheCall, 3))
3066 return true;
3067 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
3068 return true;
3069 QualType ArgTy = TheCall->getArg(0)->getType();
3070 if (ArgTy->isBooleanType() && CheckBoolSelect(&SemaRef, TheCall))
3071 return true;
3072 auto *VTy = ArgTy->getAs<VectorType>();
3073 if (VTy && VTy->getElementType()->isBooleanType() &&
3074 CheckVectorSelect(&SemaRef, TheCall))
3075 return true;
3076 break;
3077 }
3078 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3079 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3080 if (SemaRef.checkArgCount(TheCall, 1))
3081 return true;
3082 if (!TheCall->getArg(0)
3083 ->getType()
3084 ->hasFloatingRepresentation()) // half or float or double
3085 return SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
3086 diag::err_builtin_invalid_arg_type)
3087 << /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0
3088 << /* fp */ 1 << TheCall->getArg(0)->getType();
3089 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3090 return true;
3091 break;
3092 }
3093 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3094 case Builtin::BI__builtin_hlsl_elementwise_radians:
3095 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3096 case Builtin::BI__builtin_hlsl_elementwise_frac: {
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;
3104 break;
3105 }
3106 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3107 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3108 if (SemaRef.checkArgCount(TheCall, 1))
3109 return true;
3110 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3112 return true;
3113 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3114 return true;
3116 break;
3117 }
3118 case Builtin::BI__builtin_hlsl_lerp: {
3119 if (SemaRef.checkArgCount(TheCall, 3))
3120 return true;
3121 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3123 return true;
3124 if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
3125 return true;
3126 if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3127 return true;
3128 break;
3129 }
3130 case Builtin::BI__builtin_hlsl_mad: {
3131 if (SemaRef.BuiltinElementwiseTernaryMath(
3132 TheCall, /*ArgTyRestr=*/
3134 return true;
3135 break;
3136 }
3137 case Builtin::BI__builtin_hlsl_normalize: {
3138 if (SemaRef.checkArgCount(TheCall, 1))
3139 return true;
3140 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3142 return true;
3143 ExprResult A = TheCall->getArg(0);
3144 QualType ArgTyA = A.get()->getType();
3145 // return type is the same as the input type
3146 TheCall->setType(ArgTyA);
3147 break;
3148 }
3149 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3150 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3151 return true;
3152 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3154 return true;
3156 break;
3157 }
3158 case Builtin::BI__builtin_hlsl_step: {
3159 if (SemaRef.checkArgCount(TheCall, 2))
3160 return true;
3161 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3163 return true;
3164
3165 ExprResult A = TheCall->getArg(0);
3166 QualType ArgTyA = A.get()->getType();
3167 // return type is the same as the input type
3168 TheCall->setType(ArgTyA);
3169 break;
3170 }
3171 case Builtin::BI__builtin_hlsl_wave_active_max:
3172 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3173 if (SemaRef.checkArgCount(TheCall, 1))
3174 return true;
3175
3176 // Ensure input expr type is a scalar/vector and the same as the return type
3177 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3178 return true;
3179 if (CheckWaveActive(&SemaRef, TheCall))
3180 return true;
3181 ExprResult Expr = TheCall->getArg(0);
3182 QualType ArgTyExpr = Expr.get()->getType();
3183 TheCall->setType(ArgTyExpr);
3184 break;
3185 }
3186 // Note these are llvm builtins that we want to catch invalid intrinsic
3187 // generation. Normal handling of these builitns will occur elsewhere.
3188 case Builtin::BI__builtin_elementwise_bitreverse: {
3189 // does not include a check for number of arguments
3190 // because that is done previously
3191 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3193 return true;
3194 break;
3195 }
3196 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3197 if (SemaRef.checkArgCount(TheCall, 2))
3198 return true;
3199
3200 // Ensure index parameter type can be interpreted as a uint
3201 ExprResult Index = TheCall->getArg(1);
3202 QualType ArgTyIndex = Index.get()->getType();
3203 if (!ArgTyIndex->isIntegerType()) {
3204 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3205 diag::err_typecheck_convert_incompatible)
3206 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3207 return true;
3208 }
3209
3210 // Ensure input expr type is a scalar/vector and the same as the return type
3211 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
3212 return true;
3213
3214 ExprResult Expr = TheCall->getArg(0);
3215 QualType ArgTyExpr = Expr.get()->getType();
3216 TheCall->setType(ArgTyExpr);
3217 break;
3218 }
3219 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3220 if (SemaRef.checkArgCount(TheCall, 0))
3221 return true;
3222 break;
3223 }
3224 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3225 if (SemaRef.checkArgCount(TheCall, 3))
3226 return true;
3227
3228 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.DoubleTy, 0) ||
3229 CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,
3230 1) ||
3231 CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,
3232 2))
3233 return true;
3234
3235 if (CheckModifiableLValue(&SemaRef, TheCall, 1) ||
3236 CheckModifiableLValue(&SemaRef, TheCall, 2))
3237 return true;
3238 break;
3239 }
3240 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3241 if (SemaRef.checkArgCount(TheCall, 1))
3242 return true;
3243
3244 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0))
3245 return true;
3246 break;
3247 }
3248 case Builtin::BI__builtin_elementwise_acos:
3249 case Builtin::BI__builtin_elementwise_asin:
3250 case Builtin::BI__builtin_elementwise_atan:
3251 case Builtin::BI__builtin_elementwise_atan2:
3252 case Builtin::BI__builtin_elementwise_ceil:
3253 case Builtin::BI__builtin_elementwise_cos:
3254 case Builtin::BI__builtin_elementwise_cosh:
3255 case Builtin::BI__builtin_elementwise_exp:
3256 case Builtin::BI__builtin_elementwise_exp2:
3257 case Builtin::BI__builtin_elementwise_exp10:
3258 case Builtin::BI__builtin_elementwise_floor:
3259 case Builtin::BI__builtin_elementwise_fmod:
3260 case Builtin::BI__builtin_elementwise_log:
3261 case Builtin::BI__builtin_elementwise_log2:
3262 case Builtin::BI__builtin_elementwise_log10:
3263 case Builtin::BI__builtin_elementwise_pow:
3264 case Builtin::BI__builtin_elementwise_roundeven:
3265 case Builtin::BI__builtin_elementwise_sin:
3266 case Builtin::BI__builtin_elementwise_sinh:
3267 case Builtin::BI__builtin_elementwise_sqrt:
3268 case Builtin::BI__builtin_elementwise_tan:
3269 case Builtin::BI__builtin_elementwise_tanh:
3270 case Builtin::BI__builtin_elementwise_trunc: {
3271 if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
3273 return true;
3274 break;
3275 }
3276 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3277 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
3278 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3279 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3280 };
3281 if (SemaRef.checkArgCount(TheCall, 2) ||
3282 CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy) ||
3283 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
3284 SemaRef.getASTContext().IntTy))
3285 return true;
3286 Expr *OffsetExpr = TheCall->getArg(1);
3287 std::optional<llvm::APSInt> Offset =
3288 OffsetExpr->getIntegerConstantExpr(SemaRef.getASTContext());
3289 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
3290 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
3291 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3292 << 1;
3293 return true;
3294 }
3295 break;
3296 }
3297 }
3298 return false;
3299}
3300
3304 WorkList.push_back(BaseTy);
3305 while (!WorkList.empty()) {
3306 QualType T = WorkList.pop_back_val();
3307 T = T.getCanonicalType().getUnqualifiedType();
3308 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3309 llvm::SmallVector<QualType, 16> ElementFields;
3310 // Generally I've avoided recursion in this algorithm, but arrays of
3311 // structs could be time-consuming to flatten and churn through on the
3312 // work list. Hopefully nesting arrays of structs containing arrays
3313 // of structs too many levels deep is unlikely.
3314 BuildFlattenedTypeList(AT->getElementType(), ElementFields);
3315 // Repeat the element's field list n times.
3316 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3317 llvm::append_range(List, ElementFields);
3318 continue;
3319 }
3320 // Vectors can only have element types that are builtin types, so this can
3321 // add directly to the list instead of to the WorkList.
3322 if (const auto *VT = dyn_cast<VectorType>(T)) {
3323 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3324 continue;
3325 }
3326 if (const auto *RD = T->getAsCXXRecordDecl()) {
3327 if (RD->isStandardLayout())
3328 RD = RD->getStandardLayoutBaseWithFields();
3329
3330 // For types that we shouldn't decompose (unions and non-aggregates), just
3331 // add the type itself to the list.
3332 if (RD->isUnion() || !RD->isAggregate()) {
3333 List.push_back(T);
3334 continue;
3335 }
3336
3338 for (const auto *FD : RD->fields())
3339 if (!FD->isUnnamedBitField())
3340 FieldTypes.push_back(FD->getType());
3341 // Reverse the newly added sub-range.
3342 std::reverse(FieldTypes.begin(), FieldTypes.end());
3343 llvm::append_range(WorkList, FieldTypes);
3344
3345 // If this wasn't a standard layout type we may also have some base
3346 // classes to deal with.
3347 if (!RD->isStandardLayout()) {
3348 FieldTypes.clear();
3349 for (const auto &Base : RD->bases())
3350 FieldTypes.push_back(Base.getType());
3351 std::reverse(FieldTypes.begin(), FieldTypes.end());
3352 llvm::append_range(WorkList, FieldTypes);
3353 }
3354 continue;
3355 }
3356 List.push_back(T);
3357 }
3358}
3359
3361 // null and array types are not allowed.
3362 if (QT.isNull() || QT->isArrayType())
3363 return false;
3364
3365 // UDT types are not allowed
3366 if (QT->isRecordType())
3367 return false;
3368
3369 if (QT->isBooleanType() || QT->isEnumeralType())
3370 return false;
3371
3372 // the only other valid builtin types are scalars or vectors
3373 if (QT->isArithmeticType()) {
3374 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3375 return false;
3376 return true;
3377 }
3378
3379 if (const VectorType *VT = QT->getAs<VectorType>()) {
3380 int ArraySize = VT->getNumElements();
3381
3382 if (ArraySize > 4)
3383 return false;
3384
3385 QualType ElTy = VT->getElementType();
3386 if (ElTy->isBooleanType())
3387 return false;
3388
3389 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3390 return false;
3391 return true;
3392 }
3393
3394 return false;
3395}
3396
3398 if (T1.isNull() || T2.isNull())
3399 return false;
3400
3403
3404 // If both types are the same canonical type, they're obviously compatible.
3405 if (SemaRef.getASTContext().hasSameType(T1, T2))
3406 return true;
3407
3409 BuildFlattenedTypeList(T1, T1Types);
3411 BuildFlattenedTypeList(T2, T2Types);
3412
3413 // Check the flattened type list
3414 return llvm::equal(T1Types, T2Types,
3415 [this](QualType LHS, QualType RHS) -> bool {
3416 return SemaRef.IsLayoutCompatible(LHS, RHS);
3417 });
3418}
3419
3421 FunctionDecl *Old) {
3422 if (New->getNumParams() != Old->getNumParams())
3423 return true;
3424
3425 bool HadError = false;
3426
3427 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
3428 ParmVarDecl *NewParam = New->getParamDecl(i);
3429 ParmVarDecl *OldParam = Old->getParamDecl(i);
3430
3431 // HLSL parameter declarations for inout and out must match between
3432 // declarations. In HLSL inout and out are ambiguous at the call site,
3433 // but have different calling behavior, so you cannot overload a
3434 // method based on a difference between inout and out annotations.
3435 const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>();
3436 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3437 const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>();
3438 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3439
3440 if (NSpellingIdx != OSpellingIdx) {
3441 SemaRef.Diag(NewParam->getLocation(),
3442 diag::err_hlsl_param_qualifier_mismatch)
3443 << NDAttr << NewParam;
3444 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
3445 << ODAttr;
3446 HadError = true;
3447 }
3448 }
3449 return HadError;
3450}
3451
3452// Generally follows PerformScalarCast, with cases reordered for
3453// clarity of what types are supported
3455
3456 if (!SrcTy->isScalarType() || !DestTy->isScalarType())
3457 return false;
3458
3459 if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3460 return true;
3461
3462 switch (SrcTy->getScalarTypeKind()) {
3463 case Type::STK_Bool: // casting from bool is like casting from an integer
3464 case Type::STK_Integral:
3465 switch (DestTy->getScalarTypeKind()) {
3466 case Type::STK_Bool:
3467 case Type::STK_Integral:
3468 case Type::STK_Floating:
3469 return true;
3470 case Type::STK_CPointer:
3474 llvm_unreachable("HLSL doesn't support pointers.");
3477 llvm_unreachable("HLSL doesn't support complex types.");
3479 llvm_unreachable("HLSL doesn't support fixed point types.");
3480 }
3481 llvm_unreachable("Should have returned before this");
3482
3483 case Type::STK_Floating:
3484 switch (DestTy->getScalarTypeKind()) {
3485 case Type::STK_Floating:
3486 case Type::STK_Bool:
3487 case Type::STK_Integral:
3488 return true;
3491 llvm_unreachable("HLSL doesn't support complex types.");
3493 llvm_unreachable("HLSL doesn't support fixed point types.");
3494 case Type::STK_CPointer:
3498 llvm_unreachable("HLSL doesn't support pointers.");
3499 }
3500 llvm_unreachable("Should have returned before this");
3501
3503 case Type::STK_CPointer:
3506 llvm_unreachable("HLSL doesn't support pointers.");
3507
3509 llvm_unreachable("HLSL doesn't support fixed point types.");
3510
3513 llvm_unreachable("HLSL doesn't support complex types.");
3514 }
3515
3516 llvm_unreachable("Unhandled scalar cast");
3517}
3518
3519// Detect if a type contains a bitfield. Will be removed when
3520// bitfield support is added to HLSLElementwiseCast and HLSLAggregateSplatCast
3523 WorkList.push_back(BaseTy);
3524 while (!WorkList.empty()) {
3525 QualType T = WorkList.pop_back_val();
3526 T = T.getCanonicalType().getUnqualifiedType();
3527 // only check aggregate types
3528 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
3529 WorkList.push_back(AT->getElementType());
3530 continue;
3531 }
3532 if (const auto *RT = dyn_cast<RecordType>(T)) {
3533 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3534 if (RD->isUnion())
3535 continue;
3536
3537 const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(RD);
3538
3539 if (CXXD && CXXD->isStandardLayout())
3541
3542 for (const auto *FD : RD->fields()) {
3543 if (FD->isBitField())
3544 return true;
3545 WorkList.push_back(FD->getType());
3546 }
3547 continue;
3548 }
3549 }
3550 return false;
3551}
3552
3553// Can perform an HLSL Aggregate splat cast if the Dest is an aggregate and the
3554// Src is a scalar or a vector of length 1
3555// Or if Dest is a vector and Src is a vector of length 1
3557
3558 QualType SrcTy = Src->getType();
3559 // Not a valid HLSL Aggregate Splat cast if Dest is a scalar or if this is
3560 // going to be a vector splat from a scalar.
3561 if ((SrcTy->isScalarType() && DestTy->isVectorType()) ||
3562 DestTy->isScalarType())
3563 return false;
3564
3565 const VectorType *SrcVecTy = SrcTy->getAs<VectorType>();
3566
3567 // Src isn't a scalar or a vector of length 1
3568 if (!SrcTy->isScalarType() && !(SrcVecTy && SrcVecTy->getNumElements() == 1))
3569 return false;
3570
3571 if (SrcVecTy)
3572 SrcTy = SrcVecTy->getElementType();
3573
3574 if (ContainsBitField(DestTy))
3575 return false;
3576
3578 BuildFlattenedTypeList(DestTy, DestTypes);
3579
3580 for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3581 if (DestTypes[I]->isUnionType())
3582 return false;
3583 if (!CanPerformScalarCast(SrcTy, DestTypes[I]))
3584 return false;
3585 }
3586 return true;
3587}
3588
3589// Can we perform an HLSL Elementwise cast?
3590// TODO: update this code when matrices are added; see issue #88060
3592
3593 // Don't handle casts where LHS and RHS are any combination of scalar/vector
3594 // There must be an aggregate somewhere
3595 QualType SrcTy = Src->getType();
3596 if (SrcTy->isScalarType()) // always a splat and this cast doesn't handle that
3597 return false;
3598
3599 if (SrcTy->isVectorType() &&
3600 (DestTy->isScalarType() || DestTy->isVectorType()))
3601 return false;
3602
3603 if (ContainsBitField(DestTy) || ContainsBitField(SrcTy))
3604 return false;
3605
3607 BuildFlattenedTypeList(DestTy, DestTypes);
3609 BuildFlattenedTypeList(SrcTy, SrcTypes);
3610
3611 // Usually the size of SrcTypes must be greater than or equal to the size of
3612 // DestTypes.
3613 if (SrcTypes.size() < DestTypes.size())
3614 return false;
3615
3616 unsigned SrcSize = SrcTypes.size();
3617 unsigned DstSize = DestTypes.size();
3618 unsigned I;
3619 for (I = 0; I < DstSize && I < SrcSize; I++) {
3620 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3621 return false;
3622 if (!CanPerformScalarCast(SrcTypes[I], DestTypes[I])) {
3623 return false;
3624 }
3625 }
3626
3627 // check the rest of the source type for unions.
3628 for (; I < SrcSize; I++) {
3629 if (SrcTypes[I]->isUnionType())
3630 return false;
3631 }
3632 return true;
3633}
3634
3636 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3637 "We should not get here without a parameter modifier expression");
3638 const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();
3639 if (Attr->getABI() == ParameterABI::Ordinary)
3640 return ExprResult(Arg);
3641
3642 bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut;
3643 if (!Arg->isLValue()) {
3644 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue)
3645 << Arg << (IsInOut ? 1 : 0);
3646 return ExprError();
3647 }
3648
3649 ASTContext &Ctx = SemaRef.getASTContext();
3650
3651 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3652
3653 // HLSL allows implicit conversions from scalars to vectors, but not the
3654 // inverse, so we need to disallow `inout` with scalar->vector or
3655 // scalar->matrix conversions.
3656 if (Arg->getType()->isScalarType() != Ty->isScalarType()) {
3657 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)
3658 << Arg << (IsInOut ? 1 : 0);
3659 return ExprError();
3660 }
3661
3662 auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), Arg->getType(),
3663 VK_LValue, OK_Ordinary, Arg);
3664
3665 // Parameters are initialized via copy initialization. This allows for
3666 // overload resolution of argument constructors.
3667 InitializedEntity Entity =
3669 ExprResult Res =
3670 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3671 if (Res.isInvalid())
3672 return ExprError();
3673 Expr *Base = Res.get();
3674 // After the cast, drop the reference type when creating the exprs.
3675 Ty = Ty.getNonLValueExprType(Ctx);
3676 auto *OpV = new (Ctx)
3677 OpaqueValueExpr(Param->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);
3678
3679 // Writebacks are performed with `=` binary operator, which allows for
3680 // overload resolution on writeback result expressions.
3681 Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Param->getBeginLoc(),
3682 tok::equal, ArgOpV, OpV);
3683
3684 if (Res.isInvalid())
3685 return ExprError();
3686 Expr *Writeback = Res.get();
3687 auto *OutExpr =
3688 HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
3689
3690 return ExprResult(OutExpr);
3691}
3692
3694 // If HLSL gains support for references, all the cites that use this will need
3695 // to be updated with semantic checking to produce errors for
3696 // pointers/references.
3697 assert(!Ty->isReferenceType() &&
3698 "Pointer and reference types cannot be inout or out parameters");
3699 Ty = SemaRef.getASTContext().getLValueReferenceType(Ty);
3700 Ty.addRestrict();
3701 return Ty;
3702}
3703
3705 QualType QT = VD->getType();
3706 return VD->getDeclContext()->isTranslationUnit() &&
3708 VD->getStorageClass() != SC_Static &&
3709 !VD->hasAttr<HLSLVkConstantIdAttr>() &&
3711}
3712
3714 // The variable already has an address space (groupshared for ex).
3715 if (Decl->getType().hasAddressSpace())
3716 return;
3717
3718 if (Decl->getType()->isDependentType())
3719 return;
3720
3721 QualType Type = Decl->getType();
3722
3723 if (Decl->hasAttr<HLSLVkExtBuiltinInputAttr>()) {
3724 LangAS ImplAS = LangAS::hlsl_input;
3725 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3726 Decl->setType(Type);
3727 return;
3728 }
3729
3730 if (Type->isSamplerT() || Type->isVoidType())
3731 return;
3732
3733 // Resource handles.
3735 return;
3736
3737 // Only static globals belong to the Private address space.
3738 // Non-static globals belongs to the cbuffer.
3739 if (Decl->getStorageClass() != SC_Static && !Decl->isStaticDataMember())
3740 return;
3741
3743 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3744 Decl->setType(Type);
3745}
3746
3748 if (VD->hasGlobalStorage()) {
3749 // make sure the declaration has a complete type
3750 if (SemaRef.RequireCompleteType(
3751 VD->getLocation(),
3752 SemaRef.getASTContext().getBaseElementType(VD->getType()),
3753 diag::err_typecheck_decl_incomplete_type)) {
3754 VD->setInvalidDecl();
3756 return;
3757 }
3758
3759 // Global variables outside a cbuffer block that are not a resource, static,
3760 // groupshared, or an empty array or struct belong to the default constant
3761 // buffer $Globals (to be created at the end of the translation unit).
3763 // update address space to hlsl_constant
3766 VD->setType(NewTy);
3767 DefaultCBufferDecls.push_back(VD);
3768 }
3769
3770 // find all resources bindings on decl
3771 if (VD->getType()->isHLSLIntangibleType())
3772 collectResourceBindingsOnVarDecl(VD);
3773
3775 VD->hasAttr<HLSLVkConstantIdAttr>()) {
3776 // Make the variable for resources static. The global externally visible
3777 // storage is accessed through the handle, which is a member. The variable
3778 // itself is not externally visible.
3780 }
3781
3782 // process explicit bindings
3783 processExplicitBindingsOnDecl(VD);
3784
3785 if (VD->getType()->isHLSLResourceRecordArray()) {
3786 // If the resource array does not have an explicit binding attribute,
3787 // create an implicit one. It will be used to transfer implicit binding
3788 // order_ID to codegen.
3789 if (!VD->hasAttr<HLSLVkBindingAttr>()) {
3790 HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3791 if (!RBA || !RBA->hasRegisterSlot()) {
3792 uint32_t OrderID = getNextImplicitBindingOrderID();
3793 if (RBA)
3794 RBA->setImplicitBindingOrderID(OrderID);
3795 else
3798 OrderID);
3799 }
3800 }
3801 }
3802 }
3803
3805}
3806
3807bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
3808 assert(VD->getType()->isHLSLResourceRecord() &&
3809 "expected resource record type");
3810
3812 uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
3813 uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
3814
3815 // Gather resource binding attributes.
3816 ResourceBindingAttrs Binding(VD);
3817
3818 // Find correct initialization method and create its arguments.
3819 QualType ResourceTy = VD->getType();
3820 CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();
3821 CXXMethodDecl *CreateMethod = nullptr;
3823
3824 if (Binding.isExplicit()) {
3825 // The resource has explicit binding.
3826 CreateMethod = lookupMethod(SemaRef, ResourceDecl, "__createFromBinding",
3827 VD->getLocation());
3828 IntegerLiteral *RegSlot =
3829 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, Binding.getSlot()),
3831 Args.push_back(RegSlot);
3832 } else {
3833 // The resource has implicit binding.
3834 CreateMethod =
3835 lookupMethod(SemaRef, ResourceDecl, "__createFromImplicitBinding",
3836 VD->getLocation());
3837 uint32_t OrderID = (Binding.hasImplicitOrderID())
3838 ? Binding.getImplicitOrderID()
3839 : getNextImplicitBindingOrderID();
3840 IntegerLiteral *OrderId =
3841 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
3843 Args.push_back(OrderId);
3844 }
3845
3846 if (!CreateMethod)
3847 // This can happen if someone creates a struct that looks like an HLSL
3848 // resource record but does not have the required static create method.
3849 // No binding will be generated for it.
3850 return false;
3851
3852 IntegerLiteral *Space =
3853 IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, Binding.getSpace()),
3854 AST.UnsignedIntTy, SourceLocation());
3855 Args.push_back(Space);
3856
3857 IntegerLiteral *RangeSize = IntegerLiteral::Create(
3858 AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
3859 Args.push_back(RangeSize);
3860
3861 IntegerLiteral *Index = IntegerLiteral::Create(
3862 AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
3863 Args.push_back(Index);
3864
3865 StringRef VarName = VD->getName();
3866 StringLiteral *Name = StringLiteral::Create(
3867 AST, VarName, StringLiteralKind::Ordinary, false,
3868 AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
3869 SourceLocation());
3870 ImplicitCastExpr *NameCast = ImplicitCastExpr::Create(
3871 AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay,
3872 Name, nullptr, VK_PRValue, FPOptionsOverride());
3873 Args.push_back(NameCast);
3874
3875 // Make sure the create method template is instantiated and emitted.
3876 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3877 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3878 true);
3879
3880 // Create CallExpr with a call to the static method and set it as the decl
3881 // initialization.
3882 DeclRefExpr *DRE = DeclRefExpr::Create(
3883 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,
3884 CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue);
3885
3886 auto *ImpCast = ImplicitCastExpr::Create(
3887 AST, AST.getPointerType(CreateMethod->getType()),
3888 CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());
3889
3890 CallExpr *InitExpr =
3891 CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue,
3892 SourceLocation(), FPOptionsOverride());
3893 VD->setInit(InitExpr);
3895 SemaRef.CheckCompleteVariableDeclaration(VD);
3896 return true;
3897}
3898
3899bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
3900 assert(VD->getType()->isHLSLResourceRecordArray() &&
3901 "expected array of resource records");
3902
3903 // Individual resources in a resource array are not initialized here. They
3904 // are initialized later on during codegen when the individual resources are
3905 // accessed. Codegen will emit a call to the resource initialization method
3906 // with the specified array index. We need to make sure though that the method
3907 // for the specific resource type is instantiated, so codegen can emit a call
3908 // to it when the array element is accessed.
3909
3910 // Find correct initialization method based on the resource binding
3911 // information.
3912 ASTContext &AST = SemaRef.getASTContext();
3913 QualType ResElementTy = AST.getBaseElementType(VD->getType());
3914 CXXRecordDecl *ResourceDecl = ResElementTy->getAsCXXRecordDecl();
3915
3916 HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3917 HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>();
3918 CXXMethodDecl *CreateMethod = nullptr;
3919
3920 if (VkBinding || (RBA && RBA->hasRegisterSlot()))
3921 // Resource has explicit binding.
3922 CreateMethod = lookupMethod(SemaRef, ResourceDecl, "__createFromBinding",
3923 VD->getLocation());
3924 else
3925 // Resource has implicit binding.
3926 CreateMethod =
3927 lookupMethod(SemaRef, ResourceDecl, "__createFromImplicitBinding",
3928 VD->getLocation());
3929
3930 if (!CreateMethod)
3931 return false;
3932
3933 // Make sure the create method template is instantiated and emitted.
3934 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3935 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3936 true);
3937 return true;
3938}
3939
3940// Returns true if the initialization has been handled.
3941// Returns false to use default initialization.
3943 // Objects in the hlsl_constant address space are initialized
3944 // externally, so don't synthesize an implicit initializer.
3946 return true;
3947
3948 // Initialize resources at the global scope
3949 if (VD->hasGlobalStorage()) {
3950 const Type *Ty = VD->getType().getTypePtr();
3951 if (Ty->isHLSLResourceRecord())
3952 return initGlobalResourceDecl(VD);
3953 if (Ty->isHLSLResourceRecordArray())
3954 return initGlobalResourceArrayDecl(VD);
3955 }
3956 return false;
3957}
3958
3959// Return true if everything is ok; returns false if there was an error.
3961 Expr *RHSExpr, SourceLocation Loc) {
3962 assert((LHSExpr->getType()->isHLSLResourceRecord() ||
3963 LHSExpr->getType()->isHLSLResourceRecordArray()) &&
3964 "expected LHS to be a resource record or array of resource records");
3965 if (Opc != BO_Assign)
3966 return true;
3967
3968 // If LHS is an array subscript, get the underlying declaration.
3969 Expr *E = LHSExpr;
3970 while (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
3971 E = ASE->getBase()->IgnoreParenImpCasts();
3972
3973 // Report error if LHS is a resource declared at a global scope.
3974 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
3975 if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
3976 if (VD->hasGlobalStorage()) {
3977 // assignment to global resource is not allowed
3978 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
3979 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
3980 return false;
3981 }
3982 }
3983 }
3984 return true;
3985}
3986
3987// Walks though the global variable declaration, collects all resource binding
3988// requirements and adds them to Bindings
3989void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {
3990 assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() &&
3991 "expected global variable that contains HLSL resource");
3992
3993 // Cbuffers and Tbuffers are HLSLBufferDecl types
3994 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3995 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3996 ? ResourceClass::CBuffer
3997 : ResourceClass::SRV);
3998 return;
3999 }
4000
4001 // Unwrap arrays
4002 // FIXME: Calculate array size while unwrapping
4003 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
4004 while (Ty->isArrayType()) {
4005 const ArrayType *AT = cast<ArrayType>(Ty);
4007 }
4008
4009 // Resource (or array of resources)
4010 if (const HLSLAttributedResourceType *AttrResType =
4011 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4012 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4013 return;
4014 }
4015
4016 // User defined record type
4017 if (const RecordType *RT = dyn_cast<RecordType>(Ty))
4018 collectResourceBindingsOnUserRecordDecl(VD, RT);
4019}
4020
4021// Walks though the explicit resource binding attributes on the declaration,
4022// and makes sure there is a resource that matched the binding and updates
4023// DeclBindingInfoLists
4024void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
4025 assert(VD->hasGlobalStorage() && "expected global variable");
4026
4027 bool HasBinding = false;
4028 for (Attr *A : VD->attrs()) {
4030 HasBinding = true;
4031
4032 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4033 if (!RBA || !RBA->hasRegisterSlot())
4034 continue;
4035 HasBinding = true;
4036
4037 RegisterType RT = RBA->getRegisterType();
4038 assert(RT != RegisterType::I && "invalid or obsolete register type should "
4039 "never have an attribute created");
4040
4041 if (RT == RegisterType::C) {
4042 if (Bindings.hasBindingInfoForDecl(VD))
4043 SemaRef.Diag(VD->getLocation(),
4044 diag::warn_hlsl_user_defined_type_missing_member)
4045 << static_cast<int>(RT);
4046 continue;
4047 }
4048
4049 // Find DeclBindingInfo for this binding and update it, or report error
4050 // if it does not exist (user type does to contain resources with the
4051 // expected resource class).
4053 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4054 // update binding info
4055 BI->setBindingAttribute(RBA, BindingType::Explicit);
4056 } else {
4057 SemaRef.Diag(VD->getLocation(),
4058 diag::warn_hlsl_user_defined_type_missing_member)
4059 << static_cast<int>(RT);
4060 }
4061 }
4062
4063 if (!HasBinding && isResourceRecordTypeOrArrayOf(VD))
4064 SemaRef.Diag(VD->getLocation(), diag::warn_hlsl_implicit_binding);
4065}
4066namespace {
4067class InitListTransformer {
4068 Sema &S;
4069 ASTContext &Ctx;
4070 QualType InitTy;
4071 QualType *DstIt = nullptr;
4072 Expr **ArgIt = nullptr;
4073 // Is wrapping the destination type iterator required? This is only used for
4074 // incomplete array types where we loop over the destination type since we
4075 // don't know the full number of elements from the declaration.
4076 bool Wrap;
4077
4078 bool castInitializer(Expr *E) {
4079 assert(DstIt && "This should always be something!");
4080 if (DstIt == DestTypes.end()) {
4081 if (!Wrap) {
4082 ArgExprs.push_back(E);
4083 // This is odd, but it isn't technically a failure due to conversion, we
4084 // handle mismatched counts of arguments differently.
4085 return true;
4086 }
4087 DstIt = DestTypes.begin();
4088 }
4089 InitializedEntity Entity = InitializedEntity::InitializeParameter(
4090 Ctx, *DstIt, /* Consumed (ObjC) */ false);
4091 ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
4092 if (Res.isInvalid())
4093 return false;
4094 Expr *Init = Res.get();
4095 ArgExprs.push_back(Init);
4096 DstIt++;
4097 return true;
4098 }
4099
4100 bool buildInitializerListImpl(Expr *E) {
4101 // If this is an initialization list, traverse the sub initializers.
4102 if (auto *Init = dyn_cast<InitListExpr>(E)) {
4103 for (auto *SubInit : Init->inits())
4104 if (!buildInitializerListImpl(SubInit))
4105 return false;
4106 return true;
4107 }
4108
4109 // If this is a scalar type, just enqueue the expression.
4110 QualType Ty = E->getType();
4111
4112 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4113 return castInitializer(E);
4114
4115 if (auto *VecTy = Ty->getAs<VectorType>()) {
4116 uint64_t Size = VecTy->getNumElements();
4117
4118 QualType SizeTy = Ctx.getSizeType();
4119 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
4120 for (uint64_t I = 0; I < Size; ++I) {
4121 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
4122 SizeTy, SourceLocation());
4123
4125 E, E->getBeginLoc(), Idx, E->getEndLoc());
4126 if (ElExpr.isInvalid())
4127 return false;
4128 if (!castInitializer(ElExpr.get()))
4129 return false;
4130 }
4131 return true;
4132 }
4133
4134 if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {
4135 uint64_t Size = ArrTy->getZExtSize();
4136 QualType SizeTy = Ctx.getSizeType();
4137 uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
4138 for (uint64_t I = 0; I < Size; ++I) {
4139 auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
4140 SizeTy, SourceLocation());
4142 E, E->getBeginLoc(), Idx, E->getEndLoc());
4143 if (ElExpr.isInvalid())
4144 return false;
4145 if (!buildInitializerListImpl(ElExpr.get()))
4146 return false;
4147 }
4148 return true;
4149 }
4150
4151 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4152 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4153 RecordDecls.push_back(RD);
4154 while (RecordDecls.back()->getNumBases()) {
4155 CXXRecordDecl *D = RecordDecls.back();
4156 assert(D->getNumBases() == 1 &&
4157 "HLSL doesn't support multiple inheritance");
4158 RecordDecls.push_back(
4160 }
4161 while (!RecordDecls.empty()) {
4162 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4163 for (auto *FD : RD->fields()) {
4164 if (FD->isUnnamedBitField())
4165 continue;
4166 DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());
4167 DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
4169 E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
4170 if (Res.isInvalid())
4171 return false;
4172 if (!buildInitializerListImpl(Res.get()))
4173 return false;
4174 }
4175 }
4176 }
4177 return true;
4178 }
4179
4180 Expr *generateInitListsImpl(QualType Ty) {
4181 assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");
4182 if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
4183 return *(ArgIt++);
4184
4185 llvm::SmallVector<Expr *> Inits;
4186 assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL");
4187 Ty = Ty.getDesugaredType(Ctx);
4188 if (Ty->isVectorType() || Ty->isConstantArrayType()) {
4189 QualType ElTy;
4190 uint64_t Size = 0;
4191 if (auto *ATy = Ty->getAs<VectorType>()) {
4192 ElTy = ATy->getElementType();
4193 Size = ATy->getNumElements();
4194 } else {
4195 auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());
4196 ElTy = VTy->getElementType();
4197 Size = VTy->getZExtSize();
4198 }
4199 for (uint64_t I = 0; I < Size; ++I)
4200 Inits.push_back(generateInitListsImpl(ElTy));
4201 }
4202 if (auto *RD = Ty->getAsCXXRecordDecl()) {
4203 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4204 RecordDecls.push_back(RD);
4205 while (RecordDecls.back()->getNumBases()) {
4206 CXXRecordDecl *D = RecordDecls.back();
4207 assert(D->getNumBases() == 1 &&
4208 "HLSL doesn't support multiple inheritance");
4209 RecordDecls.push_back(
4211 }
4212 while (!RecordDecls.empty()) {
4213 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4214 for (auto *FD : RD->fields())
4215 if (!FD->isUnnamedBitField())
4216 Inits.push_back(generateInitListsImpl(FD->getType()));
4217 }
4218 }
4219 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4220 Inits, Inits.back()->getEndLoc());
4221 NewInit->setType(Ty);
4222 return NewInit;
4223 }
4224
4225public:
4226 llvm::SmallVector<QualType, 16> DestTypes;
4227 llvm::SmallVector<Expr *, 16> ArgExprs;
4228 InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)
4229 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4230 Wrap(Entity.getType()->isIncompleteArrayType()) {
4231 InitTy = Entity.getType().getNonReferenceType();
4232 // When we're generating initializer lists for incomplete array types we
4233 // need to wrap around both when building the initializers and when
4234 // generating the final initializer lists.
4235 if (Wrap) {
4236 assert(InitTy->isIncompleteArrayType());
4237 const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType(InitTy);
4238 InitTy = IAT->getElementType();
4239 }
4240 BuildFlattenedTypeList(InitTy, DestTypes);
4241 DstIt = DestTypes.begin();
4242 }
4243
4244 bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }
4245
4246 Expr *generateInitLists() {
4247 assert(!ArgExprs.empty() &&
4248 "Call buildInitializerList to generate argument expressions.");
4249 ArgIt = ArgExprs.begin();
4250 if (!Wrap)
4251 return generateInitListsImpl(InitTy);
4252 llvm::SmallVector<Expr *> Inits;
4253 while (ArgIt != ArgExprs.end())
4254 Inits.push_back(generateInitListsImpl(InitTy));
4255
4256 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4257 Inits, Inits.back()->getEndLoc());
4258 llvm::APInt ArySize(64, Inits.size());
4259 NewInit->setType(Ctx.getConstantArrayType(InitTy, ArySize, nullptr,
4260 ArraySizeModifier::Normal, 0));
4261 return NewInit;
4262 }
4263};
4264} // namespace
4265
4267 InitListExpr *Init) {
4268 // If the initializer is a scalar, just return it.
4269 if (Init->getType()->isScalarType())
4270 return true;
4271 ASTContext &Ctx = SemaRef.getASTContext();
4272 InitListTransformer ILT(SemaRef, Entity);
4273
4274 for (unsigned I = 0; I < Init->getNumInits(); ++I) {
4275 Expr *E = Init->getInit(I);
4276 if (E->HasSideEffects(Ctx)) {
4277 QualType Ty = E->getType();
4278 if (Ty->isRecordType())
4279 E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());
4280 E = new (Ctx) OpaqueValueExpr(E->getBeginLoc(), Ty, E->getValueKind(),
4281 E->getObjectKind(), E);
4282 Init->setInit(I, E);
4283 }
4284 if (!ILT.buildInitializerList(E))
4285 return false;
4286 }
4287 size_t ExpectedSize = ILT.DestTypes.size();
4288 size_t ActualSize = ILT.ArgExprs.size();
4289 if (ExpectedSize == 0 && ActualSize == 0)
4290 return true;
4291
4292 // For incomplete arrays it is completely arbitrary to choose whether we think
4293 // the user intended fewer or more elements. This implementation assumes that
4294 // the user intended more, and errors that there are too few initializers to
4295 // complete the final element.
4296 if (Entity.getType()->isIncompleteArrayType())
4297 ExpectedSize =
4298 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4299
4300 // An initializer list might be attempting to initialize a reference or
4301 // rvalue-reference. When checking the initializer we should look through
4302 // the reference.
4303 QualType InitTy = Entity.getType().getNonReferenceType();
4304 if (InitTy.hasAddressSpace())
4305 InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4306 if (ExpectedSize != ActualSize) {
4307 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4308 SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4309 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4310 return false;
4311 }
4312
4313 // generateInitListsImpl will always return an InitListExpr here, because the
4314 // scalar case is handled above.
4315 auto *NewInit = cast<InitListExpr>(ILT.generateInitLists());
4316 Init->resizeInits(Ctx, NewInit->getNumInits());
4317 for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
4318 Init->updateInit(Ctx, I, NewInit->getInit(I));
4319 return true;
4320}
4321
4323 const HLSLVkConstantIdAttr *ConstIdAttr =
4324 VDecl->getAttr<HLSLVkConstantIdAttr>();
4325 if (!ConstIdAttr)
4326 return true;
4327
4328 ASTContext &Context = SemaRef.getASTContext();
4329
4330 APValue InitValue;
4331 if (!Init->isCXX11ConstantExpr(Context, &InitValue)) {
4332 Diag(VDecl->getLocation(), diag::err_specialization_const);
4333 VDecl->setInvalidDecl();
4334 return false;
4335 }
4336
4337 Builtin::ID BID =
4339
4340 // Argument 1: The ID from the attribute
4341 int ConstantID = ConstIdAttr->getId();
4342 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4343 Expr *IdExpr = IntegerLiteral::Create(Context, IDVal, Context.IntTy,
4344 ConstIdAttr->getLocation());
4345
4346 SmallVector<Expr *, 2> Args = {IdExpr, Init};
4347 Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);
4348 if (C->getType()->getCanonicalTypeUnqualified() !=
4350 C = SemaRef
4351 .BuildCStyleCastExpr(SourceLocation(),
4352 Context.getTrivialTypeSourceInfo(
4353 Init->getType(), Init->getExprLoc()),
4354 SourceLocation(), C)
4355 .get();
4356 }
4357 Init = C;
4358 return true;
4359}
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:780
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
This represents one expression.
Definition Expr.h:112
void setType(QualType t)
Definition Expr.h:145
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:444
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3085
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3081
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:451
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3665
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
Definition Expr.h:461
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
@ MLV_Valid
Definition Expr.h:305
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3160
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Definition Decl.cpp:4688
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition Diagnostic.h:140
Represents a function declaration or definition.
Definition Decl.h:2000
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3271
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition Decl.h:2314
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4245
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3814
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2211
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3191
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition Decl.cpp:3238
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5176
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
Definition Decl.cpp:5824
void addLayoutStruct(CXXRecordDecl *LS)
Definition Decl.cpp:5864
void setHasValidPackoffset(bool PO)
Definition Decl.h:5221
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
Definition Decl.cpp:5847
buffer_decl_range buffer_decls() const
Definition Decl.h:5251
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
Definition Expr.cpp:5499
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
Definition Decl.cpp:5910
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2068
Describes an C or C++ initializer list.
Definition Expr.h:5233
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:971
Represents the results of name lookup.
Definition Lookup.h:147
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition Lookup.h:569
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4922
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3381
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Represents a parameter to a function.
Definition Decl.h:1790
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition ParsedAttr.h:389
bool hasParsedType() const
Definition ParsedAttr.h:337
const ParsedType & getTypeArg() const
Definition ParsedAttr.h:459
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition ParsedAttr.h:371
bool isArgIdent(unsigned Arg) const
Definition ParsedAttr.h:385
Expr * getArgAsExpr(unsigned Arg) const
Definition ParsedAttr.h:383
AttributeCommonInfo::Kind getKind() const
Definition ParsedAttr.h:610
A (possibly-)qualified type.
Definition TypeBase.h:937
void addRestrict()
Add the restrict qualifier to this QualType.
Definition TypeBase.h:1172
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3556
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1296
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8294
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8420
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:8479
QualType getCanonicalType() const
Definition TypeBase.h:8346
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8388
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition TypeBase.h:8415
Represents a struct/union/class.
Definition Decl.h:4312
field_range fields() const
Definition Decl.h:4515
bool field_empty() const
Definition Decl.h:4523
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:854
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9291
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
Definition Sema.h:9299
ASTContext & Context
Definition Sema.h:1283
ASTContext & getASTContext() const
Definition Sema.h:925
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
Definition Sema.cpp:756
const LangOptions & getLangOpts() const
Definition Sema.h:918
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:358
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
Definition Expr.cpp:1184
void startDefinition()
Starts the definition of this tag declaration.
Definition Decl.cpp:4894
bool isUnion() const
Definition Decl.h:3922
bool isClass() const
Definition Decl.h:3921
Exposes information about the current target.
Definition TargetInfo.h:226
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:323
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
The top declaration context.
Definition Decl.h:105
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8265
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:8887
bool isBooleanType() const
Definition TypeBase.h:9017
bool isIncompleteArrayType() const
Definition TypeBase.h:8638
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:8634
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:8630
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
bool isArithmeticType() const
Definition Type.cpp:2337
bool isHLSLBuiltinIntangibleType() const
Definition TypeBase.h:8832
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8931
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9174
bool isReferenceType() const
Definition TypeBase.h:8555
bool isHLSLIntangibleType() const
Definition Type.cpp:5383
bool isEnumeralType() const
Definition TypeBase.h:8662
bool isScalarType() const
Definition TypeBase.h:8989
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:8670
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2320
bool isHLSLAttributedResourceType() const
Definition TypeBase.h:8844
@ 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:8765
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9107
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:8658
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5374
void setType(QualType newType)
Definition Decl.h:724
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1452
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:934
void setStorageClass(StorageClass SC)
Definition Decl.cpp:2163
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1226
void setInit(Expr *I)
Definition Decl.cpp:2477
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1168
Represents a GCC generic vector type.
Definition TypeBase.h:4175
unsigned getNumElements() const
Definition TypeBase.h:4190
QualType getElementType() const
Definition TypeBase.h:4189
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition SemaSPIRV.cpp:66
@ ICIS_NoInit
No in-class initializer.
Definition Specifiers.h:272
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
Definition SemaSPIRV.cpp:49
@ AS_public
Definition Specifiers.h:124
@ AS_none
Definition Specifiers.h:127
@ SC_Static
Definition Specifiers.h:252
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
Definition TypeBase.h:905
@ Ordinary
This parameter uses ordinary ABI rules for its type.
Definition Specifiers.h:380
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
Definition SemaSPIRV.cpp:32
ExprResult ExprError()
Definition Ownership.h:265
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
Visibility
Describes the different kinds of visibility that a declaration may have.
Definition Visibility.h:34
unsigned long uint64_t
unsigned int uint32_t
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
#define false
Definition stdbool.h:26
Describes how types, statements, expressions, and declarations should be printed.
const SourceLocation & getLocation() const
Definition SemaHLSL.h:46
const llvm::hlsl::rootsig::RootElement & getElement() const
Definition SemaHLSL.h:45