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