clang 20.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"
13#include "clang/AST/Attr.h"
14#include "clang/AST/Attrs.inc"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclBase.h"
17#include "clang/AST/DeclCXX.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/Type.h"
21#include "clang/AST/TypeLoc.h"
24#include "clang/Basic/LLVM.h"
29#include "clang/Sema/Sema.h"
30#include "clang/Sema/Template.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/SmallVector.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/ADT/StringRef.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/DXILABI.h"
37#include "llvm/Support/ErrorHandling.h"
38#include "llvm/TargetParser/Triple.h"
39#include <iterator>
40#include <utility>
41
42using namespace clang;
43using RegisterType = HLSLResourceBindingAttr::RegisterType;
44
45static RegisterType getRegisterType(ResourceClass RC) {
46 switch (RC) {
47 case ResourceClass::SRV:
48 return RegisterType::SRV;
49 case ResourceClass::UAV:
50 return RegisterType::UAV;
51 case ResourceClass::CBuffer:
52 return RegisterType::CBuffer;
53 case ResourceClass::Sampler:
54 return RegisterType::Sampler;
55 }
56 llvm_unreachable("unexpected ResourceClass value");
57}
58
59// Converts the first letter of string Slot to RegisterType.
60// Returns false if the letter does not correspond to a valid register type.
61static bool convertToRegisterType(StringRef Slot, RegisterType *RT) {
62 assert(RT != nullptr);
63 switch (Slot[0]) {
64 case 't':
65 case 'T':
66 *RT = RegisterType::SRV;
67 return true;
68 case 'u':
69 case 'U':
70 *RT = RegisterType::UAV;
71 return true;
72 case 'b':
73 case 'B':
74 *RT = RegisterType::CBuffer;
75 return true;
76 case 's':
77 case 'S':
78 *RT = RegisterType::Sampler;
79 return true;
80 case 'c':
81 case 'C':
82 *RT = RegisterType::C;
83 return true;
84 case 'i':
85 case 'I':
86 *RT = RegisterType::I;
87 return true;
88 default:
89 return false;
90 }
91}
92
93static ResourceClass getResourceClass(RegisterType RT) {
94 switch (RT) {
95 case RegisterType::SRV:
96 return ResourceClass::SRV;
97 case RegisterType::UAV:
98 return ResourceClass::UAV;
99 case RegisterType::CBuffer:
100 return ResourceClass::CBuffer;
101 case RegisterType::Sampler:
102 return ResourceClass::Sampler;
103 case RegisterType::C:
104 case RegisterType::I:
105 // Deliberately falling through to the unreachable below.
106 break;
107 }
108 llvm_unreachable("unexpected RegisterType value");
109}
110
112 ResourceClass ResClass) {
113 assert(getDeclBindingInfo(VD, ResClass) == nullptr &&
114 "DeclBindingInfo already added");
115 assert(!hasBindingInfoForDecl(VD) || BindingsList.back().Decl == VD);
116 // VarDecl may have multiple entries for different resource classes.
117 // DeclToBindingListIndex stores the index of the first binding we saw
118 // for this decl. If there are any additional ones then that index
119 // shouldn't be updated.
120 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
121 return &BindingsList.emplace_back(VD, ResClass);
122}
123
125 ResourceClass ResClass) {
126 auto Entry = DeclToBindingListIndex.find(VD);
127 if (Entry != DeclToBindingListIndex.end()) {
128 for (unsigned Index = Entry->getSecond();
129 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
130 ++Index) {
131 if (BindingsList[Index].ResClass == ResClass)
132 return &BindingsList[Index];
133 }
134 }
135 return nullptr;
136}
137
139 return DeclToBindingListIndex.contains(VD);
140}
141
143
144Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
145 SourceLocation KwLoc, IdentifierInfo *Ident,
146 SourceLocation IdentLoc,
147 SourceLocation LBrace) {
148 // For anonymous namespace, take the location of the left brace.
149 DeclContext *LexicalParent = SemaRef.getCurLexicalContext();
151 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
152
153 // if CBuffer is false, then it's a TBuffer
154 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
155 : llvm::hlsl::ResourceClass::SRV;
156 auto RK = CBuffer ? llvm::hlsl::ResourceKind::CBuffer
157 : llvm::hlsl::ResourceKind::TBuffer;
158 Result->addAttr(HLSLResourceClassAttr::CreateImplicit(getASTContext(), RC));
159 Result->addAttr(HLSLResourceAttr::CreateImplicit(getASTContext(), RK));
160
161 SemaRef.PushOnScopeChains(Result, BufferScope);
162 SemaRef.PushDeclContext(BufferScope, Result);
163
164 return Result;
165}
166
167// Calculate the size of a legacy cbuffer type based on
168// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
169static unsigned calculateLegacyCbufferSize(const ASTContext &Context,
170 QualType T) {
171 unsigned Size = 0;
172 constexpr unsigned CBufferAlign = 128;
173 if (const RecordType *RT = T->getAs<RecordType>()) {
174 const RecordDecl *RD = RT->getDecl();
175 for (const FieldDecl *Field : RD->fields()) {
176 QualType Ty = Field->getType();
177 unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty);
178 unsigned FieldAlign = 32;
179 if (Ty->isAggregateType())
180 FieldAlign = CBufferAlign;
181 Size = llvm::alignTo(Size, FieldAlign);
182 Size += FieldSize;
183 }
184 } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
185 if (unsigned ElementCount = AT->getSize().getZExtValue()) {
186 unsigned ElementSize =
187 calculateLegacyCbufferSize(Context, AT->getElementType());
188 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
189 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
190 }
191 } else if (const VectorType *VT = T->getAs<VectorType>()) {
192 unsigned ElementCount = VT->getNumElements();
193 unsigned ElementSize =
194 calculateLegacyCbufferSize(Context, VT->getElementType());
195 Size = ElementSize * ElementCount;
196 } else {
197 Size = Context.getTypeSize(T);
198 }
199 return Size;
200}
201
203 auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
204 BufDecl->setRBraceLoc(RBrace);
205
206 // Validate packoffset.
208 bool HasPackOffset = false;
209 bool HasNonPackOffset = false;
210 for (auto *Field : BufDecl->decls()) {
211 VarDecl *Var = dyn_cast<VarDecl>(Field);
212 if (!Var)
213 continue;
214 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
215 PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
216 HasPackOffset = true;
217 } else {
218 HasNonPackOffset = true;
219 }
220 }
221
222 if (HasPackOffset && HasNonPackOffset)
223 Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);
224
225 if (HasPackOffset) {
226 ASTContext &Context = getASTContext();
227 // Make sure no overlap in packoffset.
228 // Sort PackOffsetVec by offset.
229 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
230 [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
231 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
232 return LHS.second->getOffset() < RHS.second->getOffset();
233 });
234
235 for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
236 VarDecl *Var = PackOffsetVec[i].first;
237 HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;
238 unsigned Size = calculateLegacyCbufferSize(Context, Var->getType());
239 unsigned Begin = Attr->getOffset() * 32;
240 unsigned End = Begin + Size;
241 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffset() * 32;
242 if (End > NextBegin) {
243 VarDecl *NextVar = PackOffsetVec[i + 1].first;
244 Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)
245 << NextVar << Var;
246 }
247 }
248 }
249
251}
252
254 const AttributeCommonInfo &AL,
255 int X, int Y, int Z) {
256 if (HLSLNumThreadsAttr *NT = D->getAttr<HLSLNumThreadsAttr>()) {
257 if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) {
258 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
259 Diag(AL.getLoc(), diag::note_conflicting_attribute);
260 }
261 return nullptr;
262 }
263 return ::new (getASTContext())
264 HLSLNumThreadsAttr(getASTContext(), AL, X, Y, Z);
265}
266
268 const AttributeCommonInfo &AL,
269 int Min, int Max, int Preferred,
270 int SpelledArgsCount) {
271 if (HLSLWaveSizeAttr *WS = D->getAttr<HLSLWaveSizeAttr>()) {
272 if (WS->getMin() != Min || WS->getMax() != Max ||
273 WS->getPreferred() != Preferred ||
274 WS->getSpelledArgsCount() != SpelledArgsCount) {
275 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
276 Diag(AL.getLoc(), diag::note_conflicting_attribute);
277 }
278 return nullptr;
279 }
280 HLSLWaveSizeAttr *Result = ::new (getASTContext())
281 HLSLWaveSizeAttr(getASTContext(), AL, Min, Max, Preferred);
282 Result->setSpelledArgsCount(SpelledArgsCount);
283 return Result;
284}
285
286HLSLShaderAttr *
288 llvm::Triple::EnvironmentType ShaderType) {
289 if (HLSLShaderAttr *NT = D->getAttr<HLSLShaderAttr>()) {
290 if (NT->getType() != ShaderType) {
291 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
292 Diag(AL.getLoc(), diag::note_conflicting_attribute);
293 }
294 return nullptr;
295 }
296 return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL);
297}
298
299HLSLParamModifierAttr *
301 HLSLParamModifierAttr::Spelling Spelling) {
302 // We can only merge an `in` attribute with an `out` attribute. All other
303 // combinations of duplicated attributes are ill-formed.
304 if (HLSLParamModifierAttr *PA = D->getAttr<HLSLParamModifierAttr>()) {
305 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
306 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
307 D->dropAttr<HLSLParamModifierAttr>();
308 SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()};
309 return HLSLParamModifierAttr::Create(
310 getASTContext(), /*MergedSpelling=*/true, AdjustedRange,
311 HLSLParamModifierAttr::Keyword_inout);
312 }
313 Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
314 Diag(PA->getLocation(), diag::note_conflicting_attribute);
315 return nullptr;
316 }
317 return HLSLParamModifierAttr::Create(getASTContext(), AL);
318}
319
322
324 return;
325
326 llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment();
327 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
328 if (const auto *Shader = FD->getAttr<HLSLShaderAttr>()) {
329 // The entry point is already annotated - check that it matches the
330 // triple.
331 if (Shader->getType() != Env) {
332 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
333 << Shader;
334 FD->setInvalidDecl();
335 }
336 } else {
337 // Implicitly add the shader attribute if the entry function isn't
338 // explicitly annotated.
339 FD->addAttr(HLSLShaderAttr::CreateImplicit(getASTContext(), Env,
340 FD->getBeginLoc()));
341 }
342 } else {
343 switch (Env) {
344 case llvm::Triple::UnknownEnvironment:
345 case llvm::Triple::Library:
346 break;
347 default:
348 llvm_unreachable("Unhandled environment in triple");
349 }
350 }
351}
352
354 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
355 assert(ShaderAttr && "Entry point has no shader attribute");
356 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
358 VersionTuple Ver = TargetInfo.getTriple().getOSVersion();
359 switch (ST) {
360 case llvm::Triple::Pixel:
361 case llvm::Triple::Vertex:
362 case llvm::Triple::Geometry:
363 case llvm::Triple::Hull:
364 case llvm::Triple::Domain:
365 case llvm::Triple::RayGeneration:
366 case llvm::Triple::Intersection:
367 case llvm::Triple::AnyHit:
368 case llvm::Triple::ClosestHit:
369 case llvm::Triple::Miss:
370 case llvm::Triple::Callable:
371 if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {
373 {llvm::Triple::Compute,
374 llvm::Triple::Amplification,
375 llvm::Triple::Mesh});
376 FD->setInvalidDecl();
377 }
378 if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
380 {llvm::Triple::Compute,
381 llvm::Triple::Amplification,
382 llvm::Triple::Mesh});
383 FD->setInvalidDecl();
384 }
385 break;
386
387 case llvm::Triple::Compute:
388 case llvm::Triple::Amplification:
389 case llvm::Triple::Mesh:
390 if (!FD->hasAttr<HLSLNumThreadsAttr>()) {
391 Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)
392 << llvm::Triple::getEnvironmentTypeName(ST);
393 FD->setInvalidDecl();
394 }
395 if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {
396 if (Ver < VersionTuple(6, 6)) {
397 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
398 << WS << "6.6";
399 FD->setInvalidDecl();
400 } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
401 Diag(
402 WS->getLocation(),
403 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
404 << WS << WS->getSpelledArgsCount() << "6.8";
405 FD->setInvalidDecl();
406 }
407 }
408 break;
409 default:
410 llvm_unreachable("Unhandled environment in triple");
411 }
412
413 for (ParmVarDecl *Param : FD->parameters()) {
414 if (const auto *AnnotationAttr = Param->getAttr<HLSLAnnotationAttr>()) {
415 CheckSemanticAnnotation(FD, Param, AnnotationAttr);
416 } else {
417 // FIXME: Handle struct parameters where annotations are on struct fields.
418 // See: https://github.com/llvm/llvm-project/issues/57875
419 Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation);
420 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
421 FD->setInvalidDecl();
422 }
423 }
424 // FIXME: Verify return type semantic annotation.
425}
426
428 FunctionDecl *EntryPoint, const Decl *Param,
429 const HLSLAnnotationAttr *AnnotationAttr) {
430 auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>();
431 assert(ShaderAttr && "Entry point has no shader attribute");
432 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
433
434 switch (AnnotationAttr->getKind()) {
435 case attr::HLSLSV_DispatchThreadID:
436 case attr::HLSLSV_GroupIndex:
437 case attr::HLSLSV_GroupThreadID:
438 case attr::HLSLSV_GroupID:
439 if (ST == llvm::Triple::Compute)
440 return;
441 DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute});
442 break;
443 default:
444 llvm_unreachable("Unknown HLSLAnnotationAttr");
445 }
446}
447
449 const Attr *A, llvm::Triple::EnvironmentType Stage,
450 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
451 SmallVector<StringRef, 8> StageStrings;
452 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
453 [](llvm::Triple::EnvironmentType ST) {
454 return StringRef(
455 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
456 });
457 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
458 << A << llvm::Triple::getEnvironmentTypeName(Stage)
459 << (AllowedStages.size() != 1) << join(StageStrings, ", ");
460}
461
462template <CastKind Kind>
463static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
464 if (const auto *VTy = Ty->getAs<VectorType>())
465 Ty = VTy->getElementType();
466 Ty = S.getASTContext().getExtVectorType(Ty, Sz);
467 E = S.ImpCastExprToType(E.get(), Ty, Kind);
468}
469
470template <CastKind Kind>
472 E = S.ImpCastExprToType(E.get(), Ty, Kind);
473 return Ty;
474}
475
477 Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
478 QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
479 bool LHSFloat = LElTy->isRealFloatingType();
480 bool RHSFloat = RElTy->isRealFloatingType();
481
482 if (LHSFloat && RHSFloat) {
483 if (IsCompAssign ||
484 SemaRef.getASTContext().getFloatingTypeOrder(LElTy, RElTy) > 0)
485 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
486
487 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
488 }
489
490 if (LHSFloat)
491 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
492
493 assert(RHSFloat);
494 if (IsCompAssign)
495 return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
496
497 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
498}
499
501 Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
502 QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
503
504 int IntOrder = SemaRef.Context.getIntegerTypeOrder(LElTy, RElTy);
505 bool LHSSigned = LElTy->hasSignedIntegerRepresentation();
506 bool RHSSigned = RElTy->hasSignedIntegerRepresentation();
507 auto &Ctx = SemaRef.getASTContext();
508
509 // If both types have the same signedness, use the higher ranked type.
510 if (LHSSigned == RHSSigned) {
511 if (IsCompAssign || IntOrder >= 0)
512 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
513
514 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
515 }
516
517 // If the unsigned type has greater than or equal rank of the signed type, use
518 // the unsigned type.
519 if (IntOrder != (LHSSigned ? 1 : -1)) {
520 if (IsCompAssign || RHSSigned)
521 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
522 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
523 }
524
525 // At this point the signed type has higher rank than the unsigned type, which
526 // means it will be the same size or bigger. If the signed type is bigger, it
527 // can represent all the values of the unsigned type, so select it.
528 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
529 if (IsCompAssign || LHSSigned)
530 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
531 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
532 }
533
534 // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due
535 // to C/C++ leaking through. The place this happens today is long vs long
536 // long. When arguments are vector<unsigned long, N> and vector<long long, N>,
537 // the long long has higher rank than long even though they are the same size.
538
539 // If this is a compound assignment cast the right hand side to the left hand
540 // side's type.
541 if (IsCompAssign)
542 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
543
544 // If this isn't a compound assignment we convert to unsigned long long.
545 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
546 QualType NewTy = Ctx.getExtVectorType(
547 ElTy, RHSType->castAs<VectorType>()->getNumElements());
548 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
549
550 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
551}
552
554 QualType SrcTy) {
555 if (DestTy->isRealFloatingType() && SrcTy->isRealFloatingType())
556 return CK_FloatingCast;
557 if (DestTy->isIntegralType(Ctx) && SrcTy->isIntegralType(Ctx))
558 return CK_IntegralCast;
559 if (DestTy->isRealFloatingType())
560 return CK_IntegralToFloating;
561 assert(SrcTy->isRealFloatingType() && DestTy->isIntegralType(Ctx));
562 return CK_FloatingToIntegral;
563}
564
566 QualType LHSType,
567 QualType RHSType,
568 bool IsCompAssign) {
569 const auto *LVecTy = LHSType->getAs<VectorType>();
570 const auto *RVecTy = RHSType->getAs<VectorType>();
571 auto &Ctx = getASTContext();
572
573 // If the LHS is not a vector and this is a compound assignment, we truncate
574 // the argument to a scalar then convert it to the LHS's type.
575 if (!LVecTy && IsCompAssign) {
576 QualType RElTy = RHSType->castAs<VectorType>()->getElementType();
577 RHS = SemaRef.ImpCastExprToType(RHS.get(), RElTy, CK_HLSLVectorTruncation);
578 RHSType = RHS.get()->getType();
579 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
580 return LHSType;
581 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSType,
582 getScalarCastKind(Ctx, LHSType, RHSType));
583 return LHSType;
584 }
585
586 unsigned EndSz = std::numeric_limits<unsigned>::max();
587 unsigned LSz = 0;
588 if (LVecTy)
589 LSz = EndSz = LVecTy->getNumElements();
590 if (RVecTy)
591 EndSz = std::min(RVecTy->getNumElements(), EndSz);
592 assert(EndSz != std::numeric_limits<unsigned>::max() &&
593 "one of the above should have had a value");
594
595 // In a compound assignment, the left operand does not change type, the right
596 // operand is converted to the type of the left operand.
597 if (IsCompAssign && LSz != EndSz) {
598 Diag(LHS.get()->getBeginLoc(),
599 diag::err_hlsl_vector_compound_assignment_truncation)
600 << LHSType << RHSType;
601 return QualType();
602 }
603
604 if (RVecTy && RVecTy->getNumElements() > EndSz)
605 castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);
606 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
607 castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);
608
609 if (!RVecTy)
610 castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);
611 if (!IsCompAssign && !LVecTy)
612 castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);
613
614 // If we're at the same type after resizing we can stop here.
615 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
616 return Ctx.getCommonSugaredType(LHSType, RHSType);
617
618 QualType LElTy = LHSType->castAs<VectorType>()->getElementType();
619 QualType RElTy = RHSType->castAs<VectorType>()->getElementType();
620
621 // Handle conversion for floating point vectors.
622 if (LElTy->isRealFloatingType() || RElTy->isRealFloatingType())
623 return handleFloatVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,
624 LElTy, RElTy, IsCompAssign);
625
626 assert(LElTy->isIntegralType(Ctx) && RElTy->isIntegralType(Ctx) &&
627 "HLSL Vectors can only contain integer or floating point types");
628 return handleIntegerVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,
629 LElTy, RElTy, IsCompAssign);
630}
631
633 BinaryOperatorKind Opc) {
634 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
635 "Called with non-logical operator");
637 llvm::raw_svector_ostream OS(Buff);
639 StringRef NewFnName = Opc == BO_LOr ? "or" : "and";
640 OS << NewFnName << "(";
641 LHS->printPretty(OS, nullptr, PP);
642 OS << ", ";
643 RHS->printPretty(OS, nullptr, PP);
644 OS << ")";
645 SourceRange FullRange = SourceRange(LHS->getBeginLoc(), RHS->getEndLoc());
646 SemaRef.Diag(LHS->getBeginLoc(), diag::note_function_suggestion)
647 << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
648}
649
651 llvm::VersionTuple SMVersion =
652 getASTContext().getTargetInfo().getTriple().getOSVersion();
653 uint32_t ZMax = 1024;
654 uint32_t ThreadMax = 1024;
655 if (SMVersion.getMajor() <= 4) {
656 ZMax = 1;
657 ThreadMax = 768;
658 } else if (SMVersion.getMajor() == 5) {
659 ZMax = 64;
660 ThreadMax = 1024;
661 }
662
663 uint32_t X;
664 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), X))
665 return;
666 if (X > 1024) {
668 diag::err_hlsl_numthreads_argument_oor)
669 << 0 << 1024;
670 return;
671 }
672 uint32_t Y;
673 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Y))
674 return;
675 if (Y > 1024) {
677 diag::err_hlsl_numthreads_argument_oor)
678 << 1 << 1024;
679 return;
680 }
681 uint32_t Z;
682 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Z))
683 return;
684 if (Z > ZMax) {
686 diag::err_hlsl_numthreads_argument_oor)
687 << 2 << ZMax;
688 return;
689 }
690
691 if (X * Y * Z > ThreadMax) {
692 Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
693 return;
694 }
695
696 HLSLNumThreadsAttr *NewAttr = mergeNumThreadsAttr(D, AL, X, Y, Z);
697 if (NewAttr)
698 D->addAttr(NewAttr);
699}
700
701static bool isValidWaveSizeValue(unsigned Value) {
702 return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;
703}
704
706 // validate that the wavesize argument is a power of 2 between 4 and 128
707 // inclusive
708 unsigned SpelledArgsCount = AL.getNumArgs();
709 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
710 return;
711
712 uint32_t Min;
714 return;
715
716 uint32_t Max = 0;
717 if (SpelledArgsCount > 1 &&
719 return;
720
721 uint32_t Preferred = 0;
722 if (SpelledArgsCount > 2 &&
723 !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Preferred))
724 return;
725
726 if (SpelledArgsCount > 2) {
727 if (!isValidWaveSizeValue(Preferred)) {
729 diag::err_attribute_power_of_two_in_range)
730 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
731 << Preferred;
732 return;
733 }
734 // Preferred not in range.
735 if (Preferred < Min || Preferred > Max) {
737 diag::err_attribute_power_of_two_in_range)
738 << AL << Min << Max << Preferred;
739 return;
740 }
741 } else if (SpelledArgsCount > 1) {
744 diag::err_attribute_power_of_two_in_range)
745 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;
746 return;
747 }
748 if (Max < Min) {
749 Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
750 return;
751 } else if (Max == Min) {
752 Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;
753 }
754 } else {
757 diag::err_attribute_power_of_two_in_range)
758 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;
759 return;
760 }
761 }
762
763 HLSLWaveSizeAttr *NewAttr =
764 mergeWaveSizeAttr(D, AL, Min, Max, Preferred, SpelledArgsCount);
765 if (NewAttr)
766 D->addAttr(NewAttr);
767}
768
770 const auto *VT = T->getAs<VectorType>();
771
773 (VT && VT->getNumElements() > 3)) {
774 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
775 << AL << "uint/uint2/uint3";
776 return false;
777 }
778
779 return true;
780}
781
783 auto *VD = cast<ValueDecl>(D);
784 if (!diagnoseInputIDType(VD->getType(), AL))
785 return;
786
787 D->addAttr(::new (getASTContext())
788 HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
789}
790
792 auto *VD = cast<ValueDecl>(D);
793 if (!diagnoseInputIDType(VD->getType(), AL))
794 return;
795
796 D->addAttr(::new (getASTContext())
797 HLSLSV_GroupThreadIDAttr(getASTContext(), AL));
798}
799
801 auto *VD = cast<ValueDecl>(D);
802 if (!diagnoseInputIDType(VD->getType(), AL))
803 return;
804
805 D->addAttr(::new (getASTContext()) HLSLSV_GroupIDAttr(getASTContext(), AL));
806}
807
809 if (!isa<VarDecl>(D) || !isa<HLSLBufferDecl>(D->getDeclContext())) {
810 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)
811 << AL << "shader constant in a constant buffer";
812 return;
813 }
814
815 uint32_t SubComponent;
816 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), SubComponent))
817 return;
818 uint32_t Component;
819 if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Component))
820 return;
821
822 QualType T = cast<VarDecl>(D)->getType().getCanonicalType();
823 // Check if T is an array or struct type.
824 // TODO: mark matrix type as aggregate type.
825 bool IsAggregateTy = (T->isArrayType() || T->isStructureType());
826
827 // Check Component is valid for T.
828 if (Component) {
829 unsigned Size = getASTContext().getTypeSize(T);
830 if (IsAggregateTy || Size > 128) {
831 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
832 return;
833 } else {
834 // Make sure Component + sizeof(T) <= 4.
835 if ((Component * 32 + Size) > 128) {
836 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
837 return;
838 }
839 QualType EltTy = T;
840 if (const auto *VT = T->getAs<VectorType>())
841 EltTy = VT->getElementType();
842 unsigned Align = getASTContext().getTypeAlign(EltTy);
843 if (Align > 32 && Component == 1) {
844 // NOTE: Component 3 will hit err_hlsl_packoffset_cross_reg_boundary.
845 // So we only need to check Component 1 here.
846 Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
847 << Align << EltTy;
848 return;
849 }
850 }
851 }
852
853 D->addAttr(::new (getASTContext()) HLSLPackOffsetAttr(
854 getASTContext(), AL, SubComponent, Component));
855}
856
858 StringRef Str;
859 SourceLocation ArgLoc;
860 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
861 return;
862
863 llvm::Triple::EnvironmentType ShaderType;
864 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
865 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
866 << AL << Str << ArgLoc;
867 return;
868 }
869
870 // FIXME: check function match the shader stage.
871
872 HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);
873 if (NewAttr)
874 D->addAttr(NewAttr);
875}
876
878 Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,
879 QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo) {
880 assert(AttrList.size() && "expected list of resource attributes");
881
882 QualType ContainedTy = QualType();
883 TypeSourceInfo *ContainedTyInfo = nullptr;
884 SourceLocation LocBegin = AttrList[0]->getRange().getBegin();
885 SourceLocation LocEnd = AttrList[0]->getRange().getEnd();
886
888
889 bool HasResourceClass = false;
890 for (const Attr *A : AttrList) {
891 if (!A)
892 continue;
893 LocEnd = A->getRange().getEnd();
894 switch (A->getKind()) {
895 case attr::HLSLResourceClass: {
896 ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
897 if (HasResourceClass) {
898 S.Diag(A->getLocation(), ResAttrs.ResourceClass == RC
899 ? diag::warn_duplicate_attribute_exact
900 : diag::warn_duplicate_attribute)
901 << A;
902 return false;
903 }
904 ResAttrs.ResourceClass = RC;
905 HasResourceClass = true;
906 break;
907 }
908 case attr::HLSLROV:
909 if (ResAttrs.IsROV) {
910 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
911 return false;
912 }
913 ResAttrs.IsROV = true;
914 break;
915 case attr::HLSLRawBuffer:
916 if (ResAttrs.RawBuffer) {
917 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
918 return false;
919 }
920 ResAttrs.RawBuffer = true;
921 break;
922 case attr::HLSLContainedType: {
923 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
924 QualType Ty = CTAttr->getType();
925 if (!ContainedTy.isNull()) {
926 S.Diag(A->getLocation(), ContainedTy == Ty
927 ? diag::warn_duplicate_attribute_exact
928 : diag::warn_duplicate_attribute)
929 << A;
930 return false;
931 }
932 ContainedTy = Ty;
933 ContainedTyInfo = CTAttr->getTypeLoc();
934 break;
935 }
936 default:
937 llvm_unreachable("unhandled resource attribute type");
938 }
939 }
940
941 if (!HasResourceClass) {
942 S.Diag(AttrList.back()->getRange().getEnd(),
943 diag::err_hlsl_missing_resource_class);
944 return false;
945 }
946
948 Wrapped, ContainedTy, ResAttrs);
949
950 if (LocInfo && ContainedTyInfo) {
951 LocInfo->Range = SourceRange(LocBegin, LocEnd);
952 LocInfo->ContainedTyInfo = ContainedTyInfo;
953 }
954 return true;
955}
956
957// Validates and creates an HLSL attribute that is applied as type attribute on
958// HLSL resource. The attributes are collected in HLSLResourcesTypeAttrs and at
959// the end of the declaration they are applied to the declaration type by
960// wrapping it in HLSLAttributedResourceType.
962 // only allow resource type attributes on intangible types
963 if (!T->isHLSLResourceType()) {
964 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
965 << AL << getASTContext().HLSLResourceTy;
966 return false;
967 }
968
969 // validate number of arguments
971 return false;
972
973 Attr *A = nullptr;
974 switch (AL.getKind()) {
975 case ParsedAttr::AT_HLSLResourceClass: {
976 if (!AL.isArgIdent(0)) {
977 Diag(AL.getLoc(), diag::err_attribute_argument_type)
979 return false;
980 }
981
983 StringRef Identifier = Loc->Ident->getName();
984 SourceLocation ArgLoc = Loc->Loc;
985
986 // Validate resource class value
987 ResourceClass RC;
988 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
989 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
990 << "ResourceClass" << Identifier;
991 return false;
992 }
993 A = HLSLResourceClassAttr::Create(getASTContext(), RC, AL.getLoc());
994 break;
995 }
996
997 case ParsedAttr::AT_HLSLROV:
998 A = HLSLROVAttr::Create(getASTContext(), AL.getLoc());
999 break;
1000
1001 case ParsedAttr::AT_HLSLRawBuffer:
1002 A = HLSLRawBufferAttr::Create(getASTContext(), AL.getLoc());
1003 break;
1004
1005 case ParsedAttr::AT_HLSLContainedType: {
1006 if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {
1007 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1008 return false;
1009 }
1010
1011 TypeSourceInfo *TSI = nullptr;
1013 assert(TSI && "no type source info for attribute argument");
1015 diag::err_incomplete_type))
1016 return false;
1017 A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, AL.getLoc());
1018 break;
1019 }
1020
1021 default:
1022 llvm_unreachable("unhandled HLSL attribute");
1023 }
1024
1025 HLSLResourcesTypeAttrs.emplace_back(A);
1026 return true;
1027}
1028
1029// Combines all resource type attributes and creates HLSLAttributedResourceType.
1031 if (!HLSLResourcesTypeAttrs.size())
1032 return CurrentType;
1033
1034 QualType QT = CurrentType;
1037 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1038 const HLSLAttributedResourceType *RT =
1039 cast<HLSLAttributedResourceType>(QT.getTypePtr());
1040
1041 // Temporarily store TypeLoc information for the new type.
1042 // It will be transferred to HLSLAttributesResourceTypeLoc
1043 // shortly after the type is created by TypeSpecLocFiller which
1044 // will call the TakeLocForHLSLAttribute method below.
1045 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1046 }
1047 HLSLResourcesTypeAttrs.clear();
1048 return QT;
1049}
1050
1051// Returns source location for the HLSLAttributedResourceType
1054 HLSLAttributedResourceLocInfo LocInfo = {};
1055 auto I = LocsForHLSLAttributedResources.find(RT);
1056 if (I != LocsForHLSLAttributedResources.end()) {
1057 LocInfo = I->second;
1058 LocsForHLSLAttributedResources.erase(I);
1059 return LocInfo;
1060 }
1061 LocInfo.Range = SourceRange();
1062 return LocInfo;
1063}
1064
1065// Walks though the global variable declaration, collects all resource binding
1066// requirements and adds them to Bindings
1067void SemaHLSL::collectResourcesOnUserRecordDecl(const VarDecl *VD,
1068 const RecordType *RT) {
1069 const RecordDecl *RD = RT->getDecl();
1070 for (FieldDecl *FD : RD->fields()) {
1071 const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();
1072
1073 // Unwrap arrays
1074 // FIXME: Calculate array size while unwrapping
1075 assert(!Ty->isIncompleteArrayType() &&
1076 "incomplete arrays inside user defined types are not supported");
1077 while (Ty->isConstantArrayType()) {
1078 const ConstantArrayType *CAT = cast<ConstantArrayType>(Ty);
1080 }
1081
1082 if (!Ty->isRecordType())
1083 continue;
1084
1085 if (const HLSLAttributedResourceType *AttrResType =
1087 // Add a new DeclBindingInfo to Bindings if it does not already exist
1088 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1089 DeclBindingInfo *DBI = Bindings.getDeclBindingInfo(VD, RC);
1090 if (!DBI)
1091 Bindings.addDeclBindingInfo(VD, RC);
1092 } else if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1093 // Recursively scan embedded struct or class; it would be nice to do this
1094 // without recursion, but tricky to correctly calculate the size of the
1095 // binding, which is something we are probably going to need to do later
1096 // on. Hopefully nesting of structs in structs too many levels is
1097 // unlikely.
1098 collectResourcesOnUserRecordDecl(VD, RT);
1099 }
1100 }
1101}
1102
1103// Diagnore localized register binding errors for a single binding; does not
1104// diagnose resource binding on user record types, that will be done later
1105// in processResourceBindingOnDecl based on the information collected in
1106// collectResourcesOnVarDecl.
1107// Returns false if the register binding is not valid.
1109 Decl *D, RegisterType RegType,
1110 bool SpecifiedSpace) {
1111 int RegTypeNum = static_cast<int>(RegType);
1112
1113 // check if the decl type is groupshared
1114 if (D->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
1115 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1116 return false;
1117 }
1118
1119 // Cbuffers and Tbuffers are HLSLBufferDecl types
1120 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
1121 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1122 : ResourceClass::SRV;
1123 if (RegType == getRegisterType(RC))
1124 return true;
1125
1126 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
1127 << RegTypeNum;
1128 return false;
1129 }
1130
1131 // Samplers, UAVs, and SRVs are VarDecl types
1132 assert(isa<VarDecl>(D) && "D is expected to be VarDecl or HLSLBufferDecl");
1133 VarDecl *VD = cast<VarDecl>(D);
1134
1135 // Resource
1136 if (const HLSLAttributedResourceType *AttrResType =
1138 VD->getType().getTypePtr())) {
1139 if (RegType == getRegisterType(AttrResType->getAttrs().ResourceClass))
1140 return true;
1141
1142 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
1143 << RegTypeNum;
1144 return false;
1145 }
1146
1147 const clang::Type *Ty = VD->getType().getTypePtr();
1148 while (Ty->isArrayType())
1150
1151 // Basic types
1152 if (Ty->isArithmeticType()) {
1153 bool DeclaredInCOrTBuffer = isa<HLSLBufferDecl>(D->getDeclContext());
1154 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
1155 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1156
1157 if (!DeclaredInCOrTBuffer &&
1158 (Ty->isIntegralType(S.getASTContext()) || Ty->isFloatingType())) {
1159 // Default Globals
1160 if (RegType == RegisterType::CBuffer)
1161 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1162 else if (RegType != RegisterType::C)
1163 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1164 } else {
1165 if (RegType == RegisterType::C)
1166 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1167 else
1168 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1169 }
1170 return false;
1171 }
1172 if (Ty->isRecordType())
1173 // RecordTypes will be diagnosed in processResourceBindingOnDecl
1174 // that is called from ActOnVariableDeclarator
1175 return true;
1176
1177 // Anything else is an error
1178 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1179 return false;
1180}
1181
1183 RegisterType regType) {
1184 // make sure that there are no two register annotations
1185 // applied to the decl with the same register type
1186 bool RegisterTypesDetected[5] = {false};
1187 RegisterTypesDetected[static_cast<int>(regType)] = true;
1188
1189 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {
1190 if (HLSLResourceBindingAttr *attr =
1191 dyn_cast<HLSLResourceBindingAttr>(*it)) {
1192
1193 RegisterType otherRegType = attr->getRegisterType();
1194 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {
1195 int otherRegTypeNum = static_cast<int>(otherRegType);
1196 S.Diag(TheDecl->getLocation(),
1197 diag::err_hlsl_duplicate_register_annotation)
1198 << otherRegTypeNum;
1199 return false;
1200 }
1201 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;
1202 }
1203 }
1204 return true;
1205}
1206
1208 Decl *D, RegisterType RegType,
1209 bool SpecifiedSpace) {
1210
1211 // exactly one of these two types should be set
1212 assert(((isa<VarDecl>(D) && !isa<HLSLBufferDecl>(D)) ||
1213 (!isa<VarDecl>(D) && isa<HLSLBufferDecl>(D))) &&
1214 "expecting VarDecl or HLSLBufferDecl");
1215
1216 // check if the declaration contains resource matching the register type
1217 if (!DiagnoseLocalRegisterBinding(S, ArgLoc, D, RegType, SpecifiedSpace))
1218 return false;
1219
1220 // next, if multiple register annotations exist, check that none conflict.
1221 return ValidateMultipleRegisterAnnotations(S, D, RegType);
1222}
1223
1225 if (isa<VarDecl>(TheDecl)) {
1227 cast<ValueDecl>(TheDecl)->getType(),
1228 diag::err_incomplete_type))
1229 return;
1230 }
1231 StringRef Space = "space0";
1232 StringRef Slot = "";
1233
1234 if (!AL.isArgIdent(0)) {
1235 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1236 << AL << AANT_ArgumentIdentifier;
1237 return;
1238 }
1239
1241 StringRef Str = Loc->Ident->getName();
1242 SourceLocation ArgLoc = Loc->Loc;
1243
1244 SourceLocation SpaceArgLoc;
1245 bool SpecifiedSpace = false;
1246 if (AL.getNumArgs() == 2) {
1247 SpecifiedSpace = true;
1248 Slot = Str;
1249 if (!AL.isArgIdent(1)) {
1250 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1251 << AL << AANT_ArgumentIdentifier;
1252 return;
1253 }
1254
1256 Space = Loc->Ident->getName();
1257 SpaceArgLoc = Loc->Loc;
1258 } else {
1259 Slot = Str;
1260 }
1261
1262 RegisterType RegType;
1263 unsigned SlotNum = 0;
1264 unsigned SpaceNum = 0;
1265
1266 // Validate.
1267 if (!Slot.empty()) {
1268 if (!convertToRegisterType(Slot, &RegType)) {
1269 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1270 return;
1271 }
1272 if (RegType == RegisterType::I) {
1273 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1274 return;
1275 }
1276
1277 StringRef SlotNumStr = Slot.substr(1);
1278 if (SlotNumStr.getAsInteger(10, SlotNum)) {
1279 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1280 return;
1281 }
1282 }
1283
1284 if (!Space.starts_with("space")) {
1285 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1286 return;
1287 }
1288 StringRef SpaceNumStr = Space.substr(5);
1289 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
1290 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1291 return;
1292 }
1293
1294 if (!DiagnoseHLSLRegisterAttribute(SemaRef, ArgLoc, TheDecl, RegType,
1295 SpecifiedSpace))
1296 return;
1297
1298 HLSLResourceBindingAttr *NewAttr =
1299 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
1300 if (NewAttr) {
1301 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
1302 TheDecl->addAttr(NewAttr);
1303 }
1304}
1305
1307 HLSLParamModifierAttr *NewAttr = mergeParamModifierAttr(
1308 D, AL,
1309 static_cast<HLSLParamModifierAttr::Spelling>(AL.getSemanticSpelling()));
1310 if (NewAttr)
1311 D->addAttr(NewAttr);
1312}
1313
1314namespace {
1315
1316/// This class implements HLSL availability diagnostics for default
1317/// and relaxed mode
1318///
1319/// The goal of this diagnostic is to emit an error or warning when an
1320/// unavailable API is found in code that is reachable from the shader
1321/// entry function or from an exported function (when compiling a shader
1322/// library).
1323///
1324/// This is done by traversing the AST of all shader entry point functions
1325/// and of all exported functions, and any functions that are referenced
1326/// from this AST. In other words, any functions that are reachable from
1327/// the entry points.
1328class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
1329 Sema &SemaRef;
1330
1331 // Stack of functions to be scaned
1333
1334 // Tracks which environments functions have been scanned in.
1335 //
1336 // Maps FunctionDecl to an unsigned number that represents the set of shader
1337 // environments the function has been scanned for.
1338 // The llvm::Triple::EnvironmentType enum values for shader stages guaranteed
1339 // to be numbered from llvm::Triple::Pixel to llvm::Triple::Amplification
1340 // (verified by static_asserts in Triple.cpp), we can use it to index
1341 // individual bits in the set, as long as we shift the values to start with 0
1342 // by subtracting the value of llvm::Triple::Pixel first.
1343 //
1344 // The N'th bit in the set will be set if the function has been scanned
1345 // in shader environment whose llvm::Triple::EnvironmentType integer value
1346 // equals (llvm::Triple::Pixel + N).
1347 //
1348 // For example, if a function has been scanned in compute and pixel stage
1349 // environment, the value will be 0x21 (100001 binary) because:
1350 //
1351 // (int)(llvm::Triple::Pixel - llvm::Triple::Pixel) == 0
1352 // (int)(llvm::Triple::Compute - llvm::Triple::Pixel) == 5
1353 //
1354 // A FunctionDecl is mapped to 0 (or not included in the map) if it has not
1355 // been scanned in any environment.
1356 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
1357
1358 // Do not access these directly, use the get/set methods below to make
1359 // sure the values are in sync
1360 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
1361 unsigned CurrentShaderStageBit;
1362
1363 // True if scanning a function that was already scanned in a different
1364 // shader stage context, and therefore we should not report issues that
1365 // depend only on shader model version because they would be duplicate.
1366 bool ReportOnlyShaderStageIssues;
1367
1368 // Helper methods for dealing with current stage context / environment
1369 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
1370 static_assert(sizeof(unsigned) >= 4);
1371 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
1372 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
1373 "ShaderType is too big for this bitmap"); // 31 is reserved for
1374 // "unknown"
1375
1376 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
1377 CurrentShaderEnvironment = ShaderType;
1378 CurrentShaderStageBit = (1 << bitmapIndex);
1379 }
1380
1381 void SetUnknownShaderStageContext() {
1382 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
1383 CurrentShaderStageBit = (1 << 31);
1384 }
1385
1386 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
1387 return CurrentShaderEnvironment;
1388 }
1389
1390 bool InUnknownShaderStageContext() const {
1391 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
1392 }
1393
1394 // Helper methods for dealing with shader stage bitmap
1395 void AddToScannedFunctions(const FunctionDecl *FD) {
1396 unsigned &ScannedStages = ScannedDecls[FD];
1397 ScannedStages |= CurrentShaderStageBit;
1398 }
1399
1400 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }
1401
1402 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
1403 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
1404 }
1405
1406 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
1407 return ScannerStages & CurrentShaderStageBit;
1408 }
1409
1410 static bool NeverBeenScanned(unsigned ScannedStages) {
1411 return ScannedStages == 0;
1412 }
1413
1414 // Scanning methods
1415 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
1416 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
1418 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
1419 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
1420
1421public:
1422 DiagnoseHLSLAvailability(Sema &SemaRef)
1423 : SemaRef(SemaRef),
1424 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
1425 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
1426
1427 // AST traversal methods
1428 void RunOnTranslationUnit(const TranslationUnitDecl *TU);
1429 void RunOnFunction(const FunctionDecl *FD);
1430
1431 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
1432 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());
1433 if (FD)
1434 HandleFunctionOrMethodRef(FD, DRE);
1435 return true;
1436 }
1437
1438 bool VisitMemberExpr(MemberExpr *ME) override {
1439 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());
1440 if (FD)
1441 HandleFunctionOrMethodRef(FD, ME);
1442 return true;
1443 }
1444};
1445
1446void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
1447 Expr *RefExpr) {
1448 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
1449 "expected DeclRefExpr or MemberExpr");
1450
1451 // has a definition -> add to stack to be scanned
1452 const FunctionDecl *FDWithBody = nullptr;
1453 if (FD->hasBody(FDWithBody)) {
1454 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
1455 DeclsToScan.push_back(FDWithBody);
1456 return;
1457 }
1458
1459 // no body -> diagnose availability
1460 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
1461 if (AA)
1462 CheckDeclAvailability(
1463 FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));
1464}
1465
1466void DiagnoseHLSLAvailability::RunOnTranslationUnit(
1467 const TranslationUnitDecl *TU) {
1468
1469 // Iterate over all shader entry functions and library exports, and for those
1470 // that have a body (definiton), run diag scan on each, setting appropriate
1471 // shader environment context based on whether it is a shader entry function
1472 // or an exported function. Exported functions can be in namespaces and in
1473 // export declarations so we need to scan those declaration contexts as well.
1475 DeclContextsToScan.push_back(TU);
1476
1477 while (!DeclContextsToScan.empty()) {
1478 const DeclContext *DC = DeclContextsToScan.pop_back_val();
1479 for (auto &D : DC->decls()) {
1480 // do not scan implicit declaration generated by the implementation
1481 if (D->isImplicit())
1482 continue;
1483
1484 // for namespace or export declaration add the context to the list to be
1485 // scanned later
1486 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
1487 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
1488 continue;
1489 }
1490
1491 // skip over other decls or function decls without body
1492 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
1493 if (!FD || !FD->isThisDeclarationADefinition())
1494 continue;
1495
1496 // shader entry point
1497 if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) {
1498 SetShaderStageContext(ShaderAttr->getType());
1499 RunOnFunction(FD);
1500 continue;
1501 }
1502 // exported library function
1503 // FIXME: replace this loop with external linkage check once issue #92071
1504 // is resolved
1505 bool isExport = FD->isInExportDeclContext();
1506 if (!isExport) {
1507 for (const auto *Redecl : FD->redecls()) {
1508 if (Redecl->isInExportDeclContext()) {
1509 isExport = true;
1510 break;
1511 }
1512 }
1513 }
1514 if (isExport) {
1515 SetUnknownShaderStageContext();
1516 RunOnFunction(FD);
1517 continue;
1518 }
1519 }
1520 }
1521}
1522
1523void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
1524 assert(DeclsToScan.empty() && "DeclsToScan should be empty");
1525 DeclsToScan.push_back(FD);
1526
1527 while (!DeclsToScan.empty()) {
1528 // Take one decl from the stack and check it by traversing its AST.
1529 // For any CallExpr found during the traversal add it's callee to the top of
1530 // the stack to be processed next. Functions already processed are stored in
1531 // ScannedDecls.
1532 const FunctionDecl *FD = DeclsToScan.pop_back_val();
1533
1534 // Decl was already scanned
1535 const unsigned ScannedStages = GetScannedStages(FD);
1536 if (WasAlreadyScannedInCurrentStage(ScannedStages))
1537 continue;
1538
1539 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
1540
1541 AddToScannedFunctions(FD);
1542 TraverseStmt(FD->getBody());
1543 }
1544}
1545
1546bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
1547 const AvailabilityAttr *AA) {
1548 IdentifierInfo *IIEnvironment = AA->getEnvironment();
1549 if (!IIEnvironment)
1550 return true;
1551
1552 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
1553 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
1554 return false;
1555
1556 llvm::Triple::EnvironmentType AttrEnv =
1557 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
1558
1559 return CurrentEnv == AttrEnv;
1560}
1561
1562const AvailabilityAttr *
1563DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
1564 AvailabilityAttr const *PartialMatch = nullptr;
1565 // Check each AvailabilityAttr to find the one for this platform.
1566 // For multiple attributes with the same platform try to find one for this
1567 // environment.
1568 for (const auto *A : D->attrs()) {
1569 if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
1570 StringRef AttrPlatform = Avail->getPlatform()->getName();
1571 StringRef TargetPlatform =
1573
1574 // Match the platform name.
1575 if (AttrPlatform == TargetPlatform) {
1576 // Find the best matching attribute for this environment
1577 if (HasMatchingEnvironmentOrNone(Avail))
1578 return Avail;
1579 PartialMatch = Avail;
1580 }
1581 }
1582 }
1583 return PartialMatch;
1584}
1585
1586// Check availability against target shader model version and current shader
1587// stage and emit diagnostic
1588void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
1589 const AvailabilityAttr *AA,
1591
1592 IdentifierInfo *IIEnv = AA->getEnvironment();
1593
1594 if (!IIEnv) {
1595 // The availability attribute does not have environment -> it depends only
1596 // on shader model version and not on specific the shader stage.
1597
1598 // Skip emitting the diagnostics if the diagnostic mode is set to
1599 // strict (-fhlsl-strict-availability) because all relevant diagnostics
1600 // were already emitted in the DiagnoseUnguardedAvailability scan
1601 // (SemaAvailability.cpp).
1602 if (SemaRef.getLangOpts().HLSLStrictAvailability)
1603 return;
1604
1605 // Do not report shader-stage-independent issues if scanning a function
1606 // that was already scanned in a different shader stage context (they would
1607 // be duplicate)
1608 if (ReportOnlyShaderStageIssues)
1609 return;
1610
1611 } else {
1612 // The availability attribute has environment -> we need to know
1613 // the current stage context to property diagnose it.
1614 if (InUnknownShaderStageContext())
1615 return;
1616 }
1617
1618 // Check introduced version and if environment matches
1619 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
1620 VersionTuple Introduced = AA->getIntroduced();
1621 VersionTuple TargetVersion =
1623
1624 if (TargetVersion >= Introduced && EnvironmentMatches)
1625 return;
1626
1627 // Emit diagnostic message
1628 const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
1629 llvm::StringRef PlatformName(
1630 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
1631
1632 llvm::StringRef CurrentEnvStr =
1633 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
1634
1635 llvm::StringRef AttrEnvStr =
1636 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";
1637 bool UseEnvironment = !AttrEnvStr.empty();
1638
1639 if (EnvironmentMatches) {
1640 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)
1641 << Range << D << PlatformName << Introduced.getAsString()
1642 << UseEnvironment << CurrentEnvStr;
1643 } else {
1644 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
1645 << Range << D;
1646 }
1647
1648 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
1649 << D << PlatformName << Introduced.getAsString()
1650 << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
1651 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
1652}
1653
1654} // namespace
1655
1657 // Skip running the diagnostics scan if the diagnostic mode is
1658 // strict (-fhlsl-strict-availability) and the target shader stage is known
1659 // because all relevant diagnostics were already emitted in the
1660 // DiagnoseUnguardedAvailability scan (SemaAvailability.cpp).
1662 if (SemaRef.getLangOpts().HLSLStrictAvailability &&
1663 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
1664 return;
1665
1666 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
1667}
1668
1669// Helper function for CheckHLSLBuiltinFunctionCall
1670static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
1671 assert(TheCall->getNumArgs() > 1);
1672 ExprResult A = TheCall->getArg(0);
1673
1674 QualType ArgTyA = A.get()->getType();
1675
1676 auto *VecTyA = ArgTyA->getAs<VectorType>();
1677 SourceLocation BuiltinLoc = TheCall->getBeginLoc();
1678
1679 for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
1680 ExprResult B = TheCall->getArg(i);
1681 QualType ArgTyB = B.get()->getType();
1682 auto *VecTyB = ArgTyB->getAs<VectorType>();
1683 if (VecTyA == nullptr && VecTyB == nullptr)
1684 return false;
1685
1686 if (VecTyA && VecTyB) {
1687 bool retValue = false;
1688 if (VecTyA->getElementType() != VecTyB->getElementType()) {
1689 // Note: type promotion is intended to be handeled via the intrinsics
1690 // and not the builtin itself.
1691 S->Diag(TheCall->getBeginLoc(),
1692 diag::err_vec_builtin_incompatible_vector)
1693 << TheCall->getDirectCallee() << /*useAllTerminology*/ true
1694 << SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
1695 retValue = true;
1696 }
1697 if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
1698 // You should only be hitting this case if you are calling the builtin
1699 // directly. HLSL intrinsics should avoid this case via a
1700 // HLSLVectorTruncation.
1701 S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
1702 << TheCall->getDirectCallee() << /*useAllTerminology*/ true
1703 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
1704 TheCall->getArg(1)->getEndLoc());
1705 retValue = true;
1706 }
1707 return retValue;
1708 }
1709 }
1710
1711 // Note: if we get here one of the args is a scalar which
1712 // requires a VectorSplat on Arg0 or Arg1
1713 S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1714 << TheCall->getDirectCallee() << /*useAllTerminology*/ true
1715 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
1716 TheCall->getArg(1)->getEndLoc());
1717 return true;
1718}
1719
1721 QualType ArgType = Arg->getType();
1723 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
1724 << ArgType << ExpectedType << 1 << 0 << 0;
1725 return true;
1726 }
1727 return false;
1728}
1729
1731 Sema *S, Expr *Arg, QualType ExpectedType,
1732 llvm::function_ref<bool(clang::QualType PassedType)> Check) {
1733 QualType PassedType = Arg->getType();
1734 if (Check(PassedType)) {
1735 if (auto *VecTyA = PassedType->getAs<VectorType>())
1737 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
1738 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
1739 << PassedType << ExpectedType << 1 << 0 << 0;
1740 return true;
1741 }
1742 return false;
1743}
1744
1746 Sema *S, CallExpr *TheCall, QualType ExpectedType,
1747 llvm::function_ref<bool(clang::QualType PassedType)> Check) {
1748 for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
1749 Expr *Arg = TheCall->getArg(i);
1750 if (CheckArgTypeIsCorrect(S, Arg, ExpectedType, Check)) {
1751 return true;
1752 }
1753 }
1754 return false;
1755}
1756
1758 auto checkAllFloatTypes = [](clang::QualType PassedType) -> bool {
1759 return !PassedType->hasFloatingRepresentation();
1760 };
1761 return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.FloatTy,
1762 checkAllFloatTypes);
1763}
1764
1766 auto checkFloatorHalf = [](clang::QualType PassedType) -> bool {
1767 clang::QualType BaseType =
1768 PassedType->isVectorType()
1769 ? PassedType->getAs<clang::VectorType>()->getElementType()
1770 : PassedType;
1771 return !BaseType->isHalfType() && !BaseType->isFloat32Type();
1772 };
1773 return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.FloatTy,
1774 checkFloatorHalf);
1775}
1776
1777static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall,
1778 unsigned ArgIndex) {
1779 auto *Arg = TheCall->getArg(ArgIndex);
1780 SourceLocation OrigLoc = Arg->getExprLoc();
1781 if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==
1783 return false;
1784 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
1785 return true;
1786}
1787
1788static bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) {
1789 auto checkDoubleVector = [](clang::QualType PassedType) -> bool {
1790 if (const auto *VecTy = PassedType->getAs<VectorType>())
1791 return VecTy->getElementType()->isDoubleType();
1792 return false;
1793 };
1794 return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.FloatTy,
1795 checkDoubleVector);
1796}
1798 auto checkAllSignedTypes = [](clang::QualType PassedType) -> bool {
1799 return !PassedType->hasIntegerRepresentation() &&
1800 !PassedType->hasFloatingRepresentation();
1801 };
1802 return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.IntTy,
1803 checkAllSignedTypes);
1804}
1805
1807 auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool {
1808 return !PassedType->hasUnsignedIntegerRepresentation();
1809 };
1810 return CheckAllArgTypesAreCorrect(S, TheCall, S->Context.UnsignedIntTy,
1811 checkAllUnsignedTypes);
1812}
1813
1815 QualType ReturnType) {
1816 auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
1817 if (VecTyA)
1818 ReturnType = S->Context.getVectorType(ReturnType, VecTyA->getNumElements(),
1820 TheCall->setType(ReturnType);
1821}
1822
1823static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar,
1824 unsigned ArgIndex) {
1825 assert(TheCall->getNumArgs() >= ArgIndex);
1826 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
1827 auto *VTy = ArgType->getAs<VectorType>();
1828 // not the scalar or vector<scalar>
1829 if (!(S->Context.hasSameUnqualifiedType(ArgType, Scalar) ||
1830 (VTy &&
1831 S->Context.hasSameUnqualifiedType(VTy->getElementType(), Scalar)))) {
1832 S->Diag(TheCall->getArg(0)->getBeginLoc(),
1833 diag::err_typecheck_expect_scalar_or_vector)
1834 << ArgType << Scalar;
1835 return true;
1836 }
1837 return false;
1838}
1839
1840static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall,
1841 unsigned ArgIndex) {
1842 assert(TheCall->getNumArgs() >= ArgIndex);
1843 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
1844 auto *VTy = ArgType->getAs<VectorType>();
1845 // not the scalar or vector<scalar>
1846 if (!(ArgType->isScalarType() ||
1847 (VTy && VTy->getElementType()->isScalarType()))) {
1848 S->Diag(TheCall->getArg(0)->getBeginLoc(),
1849 diag::err_typecheck_expect_any_scalar_or_vector)
1850 << ArgType;
1851 return true;
1852 }
1853 return false;
1854}
1855
1856static bool CheckBoolSelect(Sema *S, CallExpr *TheCall) {
1857 assert(TheCall->getNumArgs() == 3);
1858 Expr *Arg1 = TheCall->getArg(1);
1859 Expr *Arg2 = TheCall->getArg(2);
1860 if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), Arg2->getType())) {
1861 S->Diag(TheCall->getBeginLoc(),
1862 diag::err_typecheck_call_different_arg_types)
1863 << Arg1->getType() << Arg2->getType() << Arg1->getSourceRange()
1864 << Arg2->getSourceRange();
1865 return true;
1866 }
1867
1868 TheCall->setType(Arg1->getType());
1869 return false;
1870}
1871
1872static bool CheckVectorSelect(Sema *S, CallExpr *TheCall) {
1873 assert(TheCall->getNumArgs() == 3);
1874 Expr *Arg1 = TheCall->getArg(1);
1875 Expr *Arg2 = TheCall->getArg(2);
1876 if (!Arg1->getType()->isVectorType()) {
1877 S->Diag(Arg1->getBeginLoc(), diag::err_builtin_non_vector_type)
1878 << "Second" << TheCall->getDirectCallee() << Arg1->getType()
1879 << Arg1->getSourceRange();
1880 return true;
1881 }
1882
1883 if (!Arg2->getType()->isVectorType()) {
1884 S->Diag(Arg2->getBeginLoc(), diag::err_builtin_non_vector_type)
1885 << "Third" << TheCall->getDirectCallee() << Arg2->getType()
1886 << Arg2->getSourceRange();
1887 return true;
1888 }
1889
1890 if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), Arg2->getType())) {
1891 S->Diag(TheCall->getBeginLoc(),
1892 diag::err_typecheck_call_different_arg_types)
1893 << Arg1->getType() << Arg2->getType() << Arg1->getSourceRange()
1894 << Arg2->getSourceRange();
1895 return true;
1896 }
1897
1898 // caller has checked that Arg0 is a vector.
1899 // check all three args have the same length.
1900 if (TheCall->getArg(0)->getType()->getAs<VectorType>()->getNumElements() !=
1901 Arg1->getType()->getAs<VectorType>()->getNumElements()) {
1902 S->Diag(TheCall->getBeginLoc(),
1903 diag::err_typecheck_vector_lengths_not_equal)
1904 << TheCall->getArg(0)->getType() << Arg1->getType()
1905 << TheCall->getArg(0)->getSourceRange() << Arg1->getSourceRange();
1906 return true;
1907 }
1908 TheCall->setType(Arg1->getType());
1909 return false;
1910}
1911
1913 Sema *S, CallExpr *TheCall, unsigned ArgIndex,
1914 llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =
1915 nullptr) {
1916 assert(TheCall->getNumArgs() >= ArgIndex);
1917 QualType ArgType = TheCall->getArg(ArgIndex)->getType();
1918 const HLSLAttributedResourceType *ResTy =
1920 if (!ResTy) {
1921 S->Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),
1922 diag::err_typecheck_expect_hlsl_resource)
1923 << ArgType;
1924 return true;
1925 }
1926 if (Check && Check(ResTy)) {
1927 S->Diag(TheCall->getArg(ArgIndex)->getExprLoc(),
1928 diag::err_invalid_hlsl_resource_type)
1929 << ArgType;
1930 return true;
1931 }
1932 return false;
1933}
1934
1935// Note: returning true in this case results in CheckBuiltinFunctionCall
1936// returning an ExprError
1937bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
1938 switch (BuiltinID) {
1939 case Builtin::BI__builtin_hlsl_resource_getpointer: {
1940 if (SemaRef.checkArgCount(TheCall, 2) ||
1941 CheckResourceHandle(&SemaRef, TheCall, 0) ||
1942 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
1944 return true;
1945
1946 auto *ResourceTy =
1948 QualType ContainedTy = ResourceTy->getContainedType();
1949 // TODO: Map to an hlsl_device address space.
1950 TheCall->setType(getASTContext().getPointerType(ContainedTy));
1951 TheCall->setValueKind(VK_LValue);
1952
1953 break;
1954 }
1955 case Builtin::BI__builtin_hlsl_all:
1956 case Builtin::BI__builtin_hlsl_any: {
1957 if (SemaRef.checkArgCount(TheCall, 1))
1958 return true;
1959 break;
1960 }
1961 case Builtin::BI__builtin_hlsl_asdouble: {
1962 if (SemaRef.checkArgCount(TheCall, 2))
1963 return true;
1965 return true;
1966
1967 SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().DoubleTy);
1968 break;
1969 }
1970 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
1971 if (SemaRef.checkArgCount(TheCall, 3))
1972 return true;
1973 if (CheckVectorElementCallArgs(&SemaRef, TheCall))
1974 return true;
1976 TheCall, /*CheckForFloatArgs*/
1977 TheCall->getArg(0)->getType()->hasFloatingRepresentation()))
1978 return true;
1979 break;
1980 }
1981 case Builtin::BI__builtin_hlsl_cross: {
1982 if (SemaRef.checkArgCount(TheCall, 2))
1983 return true;
1984 if (CheckVectorElementCallArgs(&SemaRef, TheCall))
1985 return true;
1987 return true;
1988 // ensure both args have 3 elements
1989 int NumElementsArg1 =
1990 TheCall->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
1991 int NumElementsArg2 =
1992 TheCall->getArg(1)->getType()->castAs<VectorType>()->getNumElements();
1993
1994 if (NumElementsArg1 != 3) {
1995 int LessOrMore = NumElementsArg1 > 3 ? 1 : 0;
1996 SemaRef.Diag(TheCall->getBeginLoc(),
1997 diag::err_vector_incorrect_num_elements)
1998 << LessOrMore << 3 << NumElementsArg1 << /*operand*/ 1;
1999 return true;
2000 }
2001 if (NumElementsArg2 != 3) {
2002 int LessOrMore = NumElementsArg2 > 3 ? 1 : 0;
2003
2004 SemaRef.Diag(TheCall->getBeginLoc(),
2005 diag::err_vector_incorrect_num_elements)
2006 << LessOrMore << 3 << NumElementsArg2 << /*operand*/ 1;
2007 return true;
2008 }
2009
2010 ExprResult A = TheCall->getArg(0);
2011 QualType ArgTyA = A.get()->getType();
2012 // return type is the same as the input type
2013 TheCall->setType(ArgTyA);
2014 break;
2015 }
2016 case Builtin::BI__builtin_hlsl_dot: {
2017 if (SemaRef.checkArgCount(TheCall, 2))
2018 return true;
2019 if (CheckVectorElementCallArgs(&SemaRef, TheCall))
2020 return true;
2022 return true;
2023 if (CheckNoDoubleVectors(&SemaRef, TheCall))
2024 return true;
2025 break;
2026 }
2027 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
2029 return true;
2030
2031 const Expr *Arg = TheCall->getArg(0);
2032 QualType ArgTy = Arg->getType();
2033 QualType EltTy = ArgTy;
2034
2036
2037 if (auto *VecTy = EltTy->getAs<VectorType>()) {
2038 EltTy = VecTy->getElementType();
2039 ResTy = SemaRef.Context.getVectorType(ResTy, VecTy->getNumElements(),
2040 VecTy->getVectorKind());
2041 }
2042
2043 if (!EltTy->isIntegerType()) {
2044 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2045 << 1 << /* integer ty */ 6 << ArgTy;
2046 return true;
2047 }
2048
2049 TheCall->setType(ResTy);
2050 break;
2051 }
2052 case Builtin::BI__builtin_hlsl_select: {
2053 if (SemaRef.checkArgCount(TheCall, 3))
2054 return true;
2055 if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
2056 return true;
2057 QualType ArgTy = TheCall->getArg(0)->getType();
2058 if (ArgTy->isBooleanType() && CheckBoolSelect(&SemaRef, TheCall))
2059 return true;
2060 auto *VTy = ArgTy->getAs<VectorType>();
2061 if (VTy && VTy->getElementType()->isBooleanType() &&
2062 CheckVectorSelect(&SemaRef, TheCall))
2063 return true;
2064 break;
2065 }
2066 case Builtin::BI__builtin_hlsl_elementwise_saturate:
2067 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
2069 return true;
2071 return true;
2072 break;
2073 }
2074 case Builtin::BI__builtin_hlsl_elementwise_degrees:
2075 case Builtin::BI__builtin_hlsl_elementwise_radians:
2076 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
2077 case Builtin::BI__builtin_hlsl_elementwise_frac: {
2079 return true;
2081 return true;
2082 break;
2083 }
2084 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
2086 return true;
2088 return true;
2090 break;
2091 }
2092 case Builtin::BI__builtin_hlsl_lerp: {
2093 if (SemaRef.checkArgCount(TheCall, 3))
2094 return true;
2095 if (CheckVectorElementCallArgs(&SemaRef, TheCall))
2096 return true;
2098 return true;
2100 return true;
2101 break;
2102 }
2103 case Builtin::BI__builtin_hlsl_length: {
2105 return true;
2106 if (SemaRef.checkArgCount(TheCall, 1))
2107 return true;
2108
2109 ExprResult A = TheCall->getArg(0);
2110 QualType ArgTyA = A.get()->getType();
2111 QualType RetTy;
2112
2113 if (auto *VTy = ArgTyA->getAs<VectorType>())
2114 RetTy = VTy->getElementType();
2115 else
2116 RetTy = TheCall->getArg(0)->getType();
2117
2118 TheCall->setType(RetTy);
2119 break;
2120 }
2121 case Builtin::BI__builtin_hlsl_mad: {
2122 if (SemaRef.checkArgCount(TheCall, 3))
2123 return true;
2124 if (CheckVectorElementCallArgs(&SemaRef, TheCall))
2125 return true;
2127 TheCall, /*CheckForFloatArgs*/
2128 TheCall->getArg(0)->getType()->hasFloatingRepresentation()))
2129 return true;
2130 break;
2131 }
2132 case Builtin::BI__builtin_hlsl_normalize: {
2134 return true;
2135 if (SemaRef.checkArgCount(TheCall, 1))
2136 return true;
2137
2138 ExprResult A = TheCall->getArg(0);
2139 QualType ArgTyA = A.get()->getType();
2140 // return type is the same as the input type
2141 TheCall->setType(ArgTyA);
2142 break;
2143 }
2144 case Builtin::BI__builtin_hlsl_elementwise_sign: {
2146 return true;
2148 return true;
2150 break;
2151 }
2152 case Builtin::BI__builtin_hlsl_step: {
2153 if (SemaRef.checkArgCount(TheCall, 2))
2154 return true;
2156 return true;
2157
2158 ExprResult A = TheCall->getArg(0);
2159 QualType ArgTyA = A.get()->getType();
2160 // return type is the same as the input type
2161 TheCall->setType(ArgTyA);
2162 break;
2163 }
2164 // Note these are llvm builtins that we want to catch invalid intrinsic
2165 // generation. Normal handling of these builitns will occur elsewhere.
2166 case Builtin::BI__builtin_elementwise_bitreverse: {
2168 return true;
2169 break;
2170 }
2171 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
2172 if (SemaRef.checkArgCount(TheCall, 2))
2173 return true;
2174
2175 // Ensure index parameter type can be interpreted as a uint
2176 ExprResult Index = TheCall->getArg(1);
2177 QualType ArgTyIndex = Index.get()->getType();
2178 if (!ArgTyIndex->isIntegerType()) {
2179 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
2180 diag::err_typecheck_convert_incompatible)
2181 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
2182 return true;
2183 }
2184
2185 // Ensure input expr type is a scalar/vector and the same as the return type
2186 if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))
2187 return true;
2188
2189 ExprResult Expr = TheCall->getArg(0);
2190 QualType ArgTyExpr = Expr.get()->getType();
2191 TheCall->setType(ArgTyExpr);
2192 break;
2193 }
2194 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
2195 if (SemaRef.checkArgCount(TheCall, 0))
2196 return true;
2197 break;
2198 }
2199 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
2200 if (SemaRef.checkArgCount(TheCall, 3))
2201 return true;
2202
2203 if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.DoubleTy, 0) ||
2205 1) ||
2207 2))
2208 return true;
2209
2210 if (CheckModifiableLValue(&SemaRef, TheCall, 1) ||
2211 CheckModifiableLValue(&SemaRef, TheCall, 2))
2212 return true;
2213 break;
2214 }
2215 case Builtin::BI__builtin_hlsl_elementwise_clip: {
2216 if (SemaRef.checkArgCount(TheCall, 1))
2217 return true;
2218
2220 return true;
2221 break;
2222 }
2223 case Builtin::BI__builtin_elementwise_acos:
2224 case Builtin::BI__builtin_elementwise_asin:
2225 case Builtin::BI__builtin_elementwise_atan:
2226 case Builtin::BI__builtin_elementwise_atan2:
2227 case Builtin::BI__builtin_elementwise_ceil:
2228 case Builtin::BI__builtin_elementwise_cos:
2229 case Builtin::BI__builtin_elementwise_cosh:
2230 case Builtin::BI__builtin_elementwise_exp:
2231 case Builtin::BI__builtin_elementwise_exp2:
2232 case Builtin::BI__builtin_elementwise_floor:
2233 case Builtin::BI__builtin_elementwise_fmod:
2234 case Builtin::BI__builtin_elementwise_log:
2235 case Builtin::BI__builtin_elementwise_log2:
2236 case Builtin::BI__builtin_elementwise_log10:
2237 case Builtin::BI__builtin_elementwise_pow:
2238 case Builtin::BI__builtin_elementwise_roundeven:
2239 case Builtin::BI__builtin_elementwise_sin:
2240 case Builtin::BI__builtin_elementwise_sinh:
2241 case Builtin::BI__builtin_elementwise_sqrt:
2242 case Builtin::BI__builtin_elementwise_tan:
2243 case Builtin::BI__builtin_elementwise_tanh:
2244 case Builtin::BI__builtin_elementwise_trunc: {
2246 return true;
2247 break;
2248 }
2249 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
2250 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
2251 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
2252 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
2253 };
2254 if (SemaRef.checkArgCount(TheCall, 2) ||
2255 CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy) ||
2256 CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
2258 return true;
2259 Expr *OffsetExpr = TheCall->getArg(1);
2260 std::optional<llvm::APSInt> Offset =
2262 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
2263 SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),
2264 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
2265 << 1;
2266 return true;
2267 }
2268 break;
2269 }
2270 }
2271 return false;
2272}
2273
2277 WorkList.push_back(BaseTy);
2278 while (!WorkList.empty()) {
2279 QualType T = WorkList.pop_back_val();
2280 T = T.getCanonicalType().getUnqualifiedType();
2281 assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
2282 if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
2283 llvm::SmallVector<QualType, 16> ElementFields;
2284 // Generally I've avoided recursion in this algorithm, but arrays of
2285 // structs could be time-consuming to flatten and churn through on the
2286 // work list. Hopefully nesting arrays of structs containing arrays
2287 // of structs too many levels deep is unlikely.
2288 BuildFlattenedTypeList(AT->getElementType(), ElementFields);
2289 // Repeat the element's field list n times.
2290 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
2291 List.insert(List.end(), ElementFields.begin(), ElementFields.end());
2292 continue;
2293 }
2294 // Vectors can only have element types that are builtin types, so this can
2295 // add directly to the list instead of to the WorkList.
2296 if (const auto *VT = dyn_cast<VectorType>(T)) {
2297 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
2298 continue;
2299 }
2300 if (const auto *RT = dyn_cast<RecordType>(T)) {
2301 const RecordDecl *RD = RT->getDecl();
2302 if (RD->isUnion()) {
2303 List.push_back(T);
2304 continue;
2305 }
2306 const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(RD);
2307
2309 if (CXXD && CXXD->isStandardLayout())
2311
2312 for (const auto *FD : RD->fields())
2313 FieldTypes.push_back(FD->getType());
2314 // Reverse the newly added sub-range.
2315 std::reverse(FieldTypes.begin(), FieldTypes.end());
2316 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2317
2318 // If this wasn't a standard layout type we may also have some base
2319 // classes to deal with.
2320 if (CXXD && !CXXD->isStandardLayout()) {
2321 FieldTypes.clear();
2322 for (const auto &Base : CXXD->bases())
2323 FieldTypes.push_back(Base.getType());
2324 std::reverse(FieldTypes.begin(), FieldTypes.end());
2325 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2326 }
2327 continue;
2328 }
2329 List.push_back(T);
2330 }
2331}
2332
2334 // null and array types are not allowed.
2335 if (QT.isNull() || QT->isArrayType())
2336 return false;
2337
2338 // UDT types are not allowed
2339 if (QT->isRecordType())
2340 return false;
2341
2342 if (QT->isBooleanType() || QT->isEnumeralType())
2343 return false;
2344
2345 // the only other valid builtin types are scalars or vectors
2346 if (QT->isArithmeticType()) {
2347 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
2348 return false;
2349 return true;
2350 }
2351
2352 if (const VectorType *VT = QT->getAs<VectorType>()) {
2353 int ArraySize = VT->getNumElements();
2354
2355 if (ArraySize > 4)
2356 return false;
2357
2358 QualType ElTy = VT->getElementType();
2359 if (ElTy->isBooleanType())
2360 return false;
2361
2362 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
2363 return false;
2364 return true;
2365 }
2366
2367 return false;
2368}
2369
2371 if (T1.isNull() || T2.isNull())
2372 return false;
2373
2376
2377 // If both types are the same canonical type, they're obviously compatible.
2378 if (SemaRef.getASTContext().hasSameType(T1, T2))
2379 return true;
2380
2382 BuildFlattenedTypeList(T1, T1Types);
2384 BuildFlattenedTypeList(T2, T2Types);
2385
2386 // Check the flattened type list
2387 return llvm::equal(T1Types, T2Types,
2388 [this](QualType LHS, QualType RHS) -> bool {
2389 return SemaRef.IsLayoutCompatible(LHS, RHS);
2390 });
2391}
2392
2394 FunctionDecl *Old) {
2395 if (New->getNumParams() != Old->getNumParams())
2396 return true;
2397
2398 bool HadError = false;
2399
2400 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
2401 ParmVarDecl *NewParam = New->getParamDecl(i);
2402 ParmVarDecl *OldParam = Old->getParamDecl(i);
2403
2404 // HLSL parameter declarations for inout and out must match between
2405 // declarations. In HLSL inout and out are ambiguous at the call site,
2406 // but have different calling behavior, so you cannot overload a
2407 // method based on a difference between inout and out annotations.
2408 const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>();
2409 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
2410 const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>();
2411 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
2412
2413 if (NSpellingIdx != OSpellingIdx) {
2414 SemaRef.Diag(NewParam->getLocation(),
2415 diag::err_hlsl_param_qualifier_mismatch)
2416 << NDAttr << NewParam;
2417 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
2418 << ODAttr;
2419 HadError = true;
2420 }
2421 }
2422 return HadError;
2423}
2424
2426 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
2427 "We should not get here without a parameter modifier expression");
2428 const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();
2429 if (Attr->getABI() == ParameterABI::Ordinary)
2430 return ExprResult(Arg);
2431
2432 bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut;
2433 if (!Arg->isLValue()) {
2434 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue)
2435 << Arg << (IsInOut ? 1 : 0);
2436 return ExprError();
2437 }
2438
2440
2441 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
2442
2443 // HLSL allows implicit conversions from scalars to vectors, but not the
2444 // inverse, so we need to disallow `inout` with scalar->vector or
2445 // scalar->matrix conversions.
2446 if (Arg->getType()->isScalarType() != Ty->isScalarType()) {
2447 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)
2448 << Arg << (IsInOut ? 1 : 0);
2449 return ExprError();
2450 }
2451
2452 auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), Arg->getType(),
2453 VK_LValue, OK_Ordinary, Arg);
2454
2455 // Parameters are initialized via copy initialization. This allows for
2456 // overload resolution of argument constructors.
2457 InitializedEntity Entity =
2459 ExprResult Res =
2460 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
2461 if (Res.isInvalid())
2462 return ExprError();
2463 Expr *Base = Res.get();
2464 // After the cast, drop the reference type when creating the exprs.
2465 Ty = Ty.getNonLValueExprType(Ctx);
2466 auto *OpV = new (Ctx)
2468
2469 // Writebacks are performed with `=` binary operator, which allows for
2470 // overload resolution on writeback result expressions.
2472 tok::equal, ArgOpV, OpV);
2473
2474 if (Res.isInvalid())
2475 return ExprError();
2476 Expr *Writeback = Res.get();
2477 auto *OutExpr =
2478 HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
2479
2480 return ExprResult(OutExpr);
2481}
2482
2484 // If HLSL gains support for references, all the cites that use this will need
2485 // to be updated with semantic checking to produce errors for
2486 // pointers/references.
2487 assert(!Ty->isReferenceType() &&
2488 "Pointer and reference types cannot be inout or out parameters");
2490 Ty.addRestrict();
2491 return Ty;
2492}
2493
2495 if (VD->hasGlobalStorage()) {
2496 // make sure the declaration has a complete type
2498 VD->getLocation(),
2500 diag::err_typecheck_decl_incomplete_type)) {
2501 VD->setInvalidDecl();
2502 return;
2503 }
2504
2505 // find all resources on decl
2506 if (VD->getType()->isHLSLIntangibleType())
2507 collectResourcesOnVarDecl(VD);
2508
2509 // process explicit bindings
2510 processExplicitBindingsOnDecl(VD);
2511 }
2512}
2513
2514// Walks though the global variable declaration, collects all resource binding
2515// requirements and adds them to Bindings
2516void SemaHLSL::collectResourcesOnVarDecl(VarDecl *VD) {
2517 assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() &&
2518 "expected global variable that contains HLSL resource");
2519
2520 // Cbuffers and Tbuffers are HLSLBufferDecl types
2521 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
2522 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
2523 ? ResourceClass::CBuffer
2524 : ResourceClass::SRV);
2525 return;
2526 }
2527
2528 // Unwrap arrays
2529 // FIXME: Calculate array size while unwrapping
2530 const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
2531 while (Ty->isConstantArrayType()) {
2532 const ConstantArrayType *CAT = cast<ConstantArrayType>(Ty);
2534 }
2535
2536 // Resource (or array of resources)
2537 if (const HLSLAttributedResourceType *AttrResType =
2539 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
2540 return;
2541 }
2542
2543 // User defined record type
2544 if (const RecordType *RT = dyn_cast<RecordType>(Ty))
2545 collectResourcesOnUserRecordDecl(VD, RT);
2546}
2547
2548// Walks though the explicit resource binding attributes on the declaration,
2549// and makes sure there is a resource that matched the binding and updates
2550// DeclBindingInfoLists
2551void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
2552 assert(VD->hasGlobalStorage() && "expected global variable");
2553
2554 for (Attr *A : VD->attrs()) {
2555 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
2556 if (!RBA)
2557 continue;
2558
2559 RegisterType RT = RBA->getRegisterType();
2560 assert(RT != RegisterType::I && "invalid or obsolete register type should "
2561 "never have an attribute created");
2562
2563 if (RT == RegisterType::C) {
2564 if (Bindings.hasBindingInfoForDecl(VD))
2565 SemaRef.Diag(VD->getLocation(),
2566 diag::warn_hlsl_user_defined_type_missing_member)
2567 << static_cast<int>(RT);
2568 continue;
2569 }
2570
2571 // Find DeclBindingInfo for this binding and update it, or report error
2572 // if it does not exist (user type does to contain resources with the
2573 // expected resource class).
2574 ResourceClass RC = getResourceClass(RT);
2575 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
2576 // update binding info
2577 BI->setBindingAttribute(RBA, BindingType::Explicit);
2578 } else {
2579 SemaRef.Diag(VD->getLocation(),
2580 diag::warn_hlsl_user_defined_type_missing_member)
2581 << static_cast<int>(RT);
2582 }
2583 }
2584}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
const Decl * D
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
StringRef Identifier
Definition: Format.cpp:3040
const Environment & Env
Definition: HTMLLogger.cpp:147
#define X(type, name)
Definition: Value.h:144
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
Definition: SemaHLSL.cpp:1720
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
Definition: SemaHLSL.cpp:2274
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition: SemaHLSL.cpp:500
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
Definition: SemaHLSL.cpp:61
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
Definition: SemaHLSL.cpp:463
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1856
static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1670
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
Definition: SemaHLSL.cpp:1207
static bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1806
static bool CheckFloatingOrIntRepresentation(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1797
static bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1788
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
Definition: SemaHLSL.cpp:1840
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
Definition: SemaHLSL.cpp:1814
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
Definition: SemaHLSL.cpp:169
static RegisterType getRegisterType(ResourceClass RC)
Definition: SemaHLSL.cpp:45
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
Definition: SemaHLSL.cpp:1777
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
Definition: SemaHLSL.cpp:471
static bool CheckArgTypeIsCorrect(Sema *S, Expr *Arg, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)
Definition: SemaHLSL.cpp:1730
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1872
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition: SemaHLSL.cpp:476
static ResourceClass getResourceClass(RegisterType RT)
Definition: SemaHLSL.cpp:93
static bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1765
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
Definition: SemaHLSL.cpp:1823
static bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1757
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
Definition: SemaHLSL.cpp:1912
HLSLResourceBindingAttr::RegisterType RegisterType
Definition: SemaHLSL.cpp:43
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
Definition: SemaHLSL.cpp:553
static bool isValidWaveSizeValue(unsigned Value)
Definition: SemaHLSL.cpp:701
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)
Definition: SemaHLSL.cpp:1745
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
Definition: SemaHLSL.cpp:1182
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
Definition: SemaHLSL.cpp:1108
This file declares semantic analysis for HLSL constructs.
SourceRange Range
Definition: SemaObjC.cpp:758
SourceLocation Loc
Definition: SemaObjC.cpp:759
Defines the clang::SourceLocation class and associated facilities.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
SourceLocation Begin
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:2915
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
CanQualType FloatTy
Definition: ASTContext.h:1172
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2732
CanQualType DoubleTy
Definition: ASTContext.h:1172
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified 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 IntTy
Definition: ASTContext.h:1169
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2763
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2482
CanQualType UnsignedIntTy
Definition: ASTContext.h:1170
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:799
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Definition: ASTContext.h:2513
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
QualType getElementType() const
Definition: Type.h:3589
Attr - This represents one attribute.
Definition: Attr.h:43
attr::Kind getKind() const
Definition: Attr.h:89
SourceLocation getLoc() const
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
Definition: DeclCXX.h:1237
base_class_range bases()
Definition: DeclCXX.h:620
const CXXRecordDecl * getStandardLayoutBaseWithFields() const
If this is a standard-layout class or union, any and all data members will be declared in the same ty...
Definition: DeclCXX.cpp:566
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2874
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3068
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3047
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3055
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3615
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2349
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
ValueDecl * getDecl()
Definition: Expr.h:1333
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:576
void addAttr(Attr *A)
Definition: DeclBase.cpp:1010
attr_iterator attr_end() const
Definition: DeclBase.h:545
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:596
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:151
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
Definition: DeclBase.cpp:1109
attr_iterator attr_begin() const
Definition: DeclBase.h:542
SourceLocation getLocation() const
Definition: DeclBase.h:442
DeclContext * getDeclContext()
Definition: DeclBase.h:451
attr_range attrs() const
Definition: DeclBase.h:538
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
void dropAttr()
Definition: DeclBase.h:559
bool hasAttr() const
Definition: DeclBase.h:580
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:786
Recursive AST visitor that supports extension via dynamic dispatch.
This represents one expression.
Definition: Expr.h:110
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, does not have an incomplet...
void setType(QualType t)
Definition: Expr.h:143
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3074
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
Definition: Expr.h:454
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
@ MLV_Valid
Definition: Expr.h:298
QualType getType() const
Definition: Expr.h:142
Represents a member of a struct/union/class.
Definition: Decl.h:3033
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:138
Represents a function declaration or definition.
Definition: Decl.h:1935
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2672
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3243
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition: Decl.h:2249
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2649
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3702
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3163
static const HLSLAttributedResourceType * findHandleTypeOnResource(const Type *RT)
Definition: Type.cpp:5433
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition: Decl.h:4927
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
Definition: Decl.cpp:5666
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
Definition: Expr.cpp:5413
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3236
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3319
This represents a decl that may have a name.
Definition: Decl.h:253
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:280
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1173
Represents a parameter to a function.
Definition: Decl.h:1725
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
Definition: ParsedAttr.cpp:260
unsigned getMinArgs() const
Definition: ParsedAttr.cpp:146
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:296
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:404
bool hasParsedType() const
Definition: ParsedAttr.h:352
const ParsedType & getTypeArg() const
Definition: ParsedAttr.h:474
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:386
bool isArgIdent(unsigned Arg) const
Definition: ParsedAttr.h:400
Expr * getArgAsExpr(unsigned Arg) const
Definition: ParsedAttr.h:398
AttributeCommonInfo::Kind getKind() const
Definition: ParsedAttr.h:625
A (possibly-)qualified type.
Definition: Type.h:929
void addRestrict()
Add the restrict qualifier to this QualType.
Definition: Type.h:1167
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3521
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:996
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7931
QualType getCanonicalType() const
Definition: Type.h:7983
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8025
Represents a struct/union/class.
Definition: Decl.h:4148
field_range fields() const
Definition: Decl.h:4354
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6072
RecordDecl * getDecl() const
Definition: Type.h:6082
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: Redeclarable.h:295
bool hasBindingInfoForDecl(const VarDecl *VD) const
Definition: SemaHLSL.cpp:138
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Definition: SemaHLSL.cpp:124
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Definition: SemaHLSL.cpp:111
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
Definition: SemaHLSL.cpp:2425
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
Definition: SemaHLSL.cpp:448
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:705
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
Definition: SemaHLSL.cpp:1053
QualType ProcessResourceTypeAttributes(QualType Wrapped)
Definition: SemaHLSL.cpp:1030
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:791
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:857
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:782
void CheckEntryPoint(FunctionDecl *FD)
Definition: SemaHLSL.cpp:353
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
Definition: SemaHLSL.cpp:632
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
Definition: SemaHLSL.cpp:253
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:808
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
Definition: SemaHLSL.cpp:427
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:769
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1306
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
Definition: SemaHLSL.cpp:2370
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
Definition: SemaHLSL.cpp:2393
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
Definition: SemaHLSL.cpp:565
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:1224
bool IsTypedResourceElementCompatible(QualType T1)
Definition: SemaHLSL.cpp:2333
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:650
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU)
Definition: SemaHLSL.cpp:1656
void ActOnTopLevelFunction(FunctionDecl *FD)
Definition: SemaHLSL.cpp:320
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:961
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
Definition: SemaHLSL.cpp:287
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
Definition: SemaHLSL.cpp:202
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
Definition: SemaHLSL.cpp:300
QualType getInoutParameterType(QualType Ty)
Definition: SemaHLSL.cpp:2483
SemaHLSL(Sema &S)
Definition: SemaHLSL.cpp:142
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
Definition: SemaHLSL.cpp:144
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
Definition: SemaHLSL.cpp:267
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaHLSL.cpp:800
void ActOnVariableDeclarator(VarDecl *VD)
Definition: SemaHLSL.cpp:2494
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaHLSL.cpp:1937
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:463
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:731
ASTContext & Context
Definition: Sema.h:908
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1497
ASTContext & getASTContext() const
Definition: Sema.h:531
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:690
bool BuiltinVectorToScalarMath(CallExpr *TheCall)
bool IsLayoutCompatible(QualType T1, QualType T2) const
const LangOptions & getLangOpts() const
Definition: Sema.h:524
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall)
DeclContext * getCurLexicalContext() const
Definition: Sema.h:735
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
Definition: Sema.h:4416
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall, bool CheckForFloatArgs=true)
ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)
Binary Operators. 'Tok' is the token for the operator.
Definition: SemaExpr.cpp:15271
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9068
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1308
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Definition: SemaInit.cpp:9718
void PopDeclContext()
Definition: SemaDecl.cpp:1315
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:2750
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:357
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:333
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:345
bool isUnion() const
Definition: Decl.h:3770
Exposes information about the current target.
Definition: TargetInfo.h:220
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:311
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1262
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
Definition: TargetInfo.h:1666
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
Definition: TargetInfo.h:1670
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
The top declaration context.
Definition: Decl.h:84
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7902
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
The base class of the type hierarchy.
Definition: Type.h:1828
bool isStructureType() const
Definition: Type.cpp:662
bool isBooleanType() const
Definition: Type.h:8638
bool isIncompleteArrayType() const
Definition: Type.h:8266
bool isConstantArrayType() const
Definition: Type.h:8262
bool isArrayType() const
Definition: Type.h:8258
bool isArithmeticType() const
Definition: Type.cpp:2315
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8550
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8800
bool isReferenceType() const
Definition: Type.h:8204
bool isHLSLIntangibleType() const
Definition: Type.cpp:5103
bool isEnumeralType() const
Definition: Type.h:8290
bool isScalarType() const
Definition: Type.h:8609
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2092
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:460
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2270
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition: Type.cpp:2372
bool isFloat32Type() const
Definition: Type.h:8523
bool isHalfType() const
Definition: Type.h:8514
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2220
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition: Type.cpp:2292
bool isVectorType() const
Definition: Type.h:8298
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2300
bool isFloatingType() const
Definition: Type.cpp:2283
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition: Type.cpp:638
bool isRecordType() const
Definition: Type.h:8286
QualType getType() const
Definition: Decl.h:682
Represents a variable declaration or definition.
Definition: Decl.h:882
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1177
Represents a GCC generic vector type.
Definition: Type.h:4034
unsigned getNumElements() const
Definition: Type.h:4049
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
The JSON file list parser is used to communicate input to InstallAPI.
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
BinaryOperatorKind
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1081
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
Definition: SemaHLSL.cpp:877
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
@ Generic
not a target-specific vector type
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:34
#define false
Definition: stdbool.h:26
TypeSourceInfo * ContainedTyInfo
Definition: TypeLoc.h:945
llvm::dxil::ResourceClass ResourceClass
Definition: Type.h:6255
Wraps an identifier and optional source location for the identifier.
Definition: ParsedAttr.h:103
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57