clang: lib/Sema/SemaHLSL.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

15#include "clang/AST/Attrs.inc"

38#include "llvm/ADT/ArrayRef.h"

39#include "llvm/ADT/STLExtras.h"

40#include "llvm/ADT/SmallVector.h"

41#include "llvm/ADT/StringExtras.h"

42#include "llvm/ADT/StringRef.h"

43#include "llvm/ADT/Twine.h"

44#include "llvm/Frontend/HLSL/HLSLBinding.h"

45#include "llvm/Frontend/HLSL/RootSignatureValidations.h"

46#include "llvm/Support/Casting.h"

47#include "llvm/Support/DXILABI.h"

48#include "llvm/Support/ErrorHandling.h"

49#include "llvm/Support/FormatVariadic.h"

50#include "llvm/TargetParser/Triple.h"

51#include

52#include

53#include

54#include

55

56using namespace clang;

58using RegisterType = HLSLResourceBindingAttr::RegisterType;

59

62

64 switch (RC) {

65 case ResourceClass::SRV:

66 return RegisterType::SRV;

67 case ResourceClass::UAV:

68 return RegisterType::UAV;

69 case ResourceClass::CBuffer:

70 return RegisterType::CBuffer;

71 case ResourceClass::Sampler:

72 return RegisterType::Sampler;

73 }

74 llvm_unreachable("unexpected ResourceClass value");

75}

76

80

81

82

84 assert(RT != nullptr);

85 switch (Slot[0]) {

86 case 't':

87 case 'T':

88 *RT = RegisterType::SRV;

89 return true;

90 case 'u':

91 case 'U':

92 *RT = RegisterType::UAV;

93 return true;

94 case 'b':

95 case 'B':

96 *RT = RegisterType::CBuffer;

97 return true;

98 case 's':

99 case 'S':

100 *RT = RegisterType::Sampler;

101 return true;

102 case 'c':

103 case 'C':

104 *RT = RegisterType::C;

105 return true;

106 case 'i':

107 case 'I':

108 *RT = RegisterType::I;

109 return true;

110 default:

111 return false;

112 }

113}

114

116 switch (RT) {

117 case RegisterType::SRV:

118 return ResourceClass::SRV;

119 case RegisterType::UAV:

120 return ResourceClass::UAV;

121 case RegisterType::CBuffer:

122 return ResourceClass::CBuffer;

123 case RegisterType::Sampler:

124 return ResourceClass::Sampler;

125 case RegisterType::C:

126 case RegisterType::I:

127

128 break;

129 }

130 llvm_unreachable("unexpected RegisterType value");

131}

132

134 const auto *BT = dyn_cast(Type);

135 if (!BT) {

138 return Builtin::BI__builtin_get_spirv_spec_constant_int;

139 }

140

141 switch (BT->getKind()) {

142 case BuiltinType::Bool:

143 return Builtin::BI__builtin_get_spirv_spec_constant_bool;

144 case BuiltinType::Short:

145 return Builtin::BI__builtin_get_spirv_spec_constant_short;

146 case BuiltinType::Int:

147 return Builtin::BI__builtin_get_spirv_spec_constant_int;

148 case BuiltinType::LongLong:

149 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;

150 case BuiltinType::UShort:

151 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;

152 case BuiltinType::UInt:

153 return Builtin::BI__builtin_get_spirv_spec_constant_uint;

154 case BuiltinType::ULongLong:

155 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;

156 case BuiltinType::Half:

157 return Builtin::BI__builtin_get_spirv_spec_constant_half;

158 case BuiltinType::Float:

159 return Builtin::BI__builtin_get_spirv_spec_constant_float;

160 case BuiltinType::Double:

161 return Builtin::BI__builtin_get_spirv_spec_constant_double;

162 default:

164 }

165}

166

168 ResourceClass ResClass) {

170 "DeclBindingInfo already added");

172

173

174

175

176 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());

177 return &BindingsList.emplace_back(VD, ResClass);

178}

179

181 ResourceClass ResClass) {

182 auto Entry = DeclToBindingListIndex.find(VD);

183 if (Entry != DeclToBindingListIndex.end()) {

184 for (unsigned Index = Entry->getSecond();

185 Index < BindingsList.size() && BindingsList[Index].Decl == VD;

186 ++Index) {

187 if (BindingsList[Index].ResClass == ResClass)

188 return &BindingsList[Index];

189 }

190 }

191 return nullptr;

192}

193

195 return DeclToBindingListIndex.contains(VD);

196}

197

199

204

207 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);

208

209

210 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer

211 : llvm::hlsl::ResourceClass::SRV;

212 Result->addAttr(HLSLResourceClassAttr::CreateImplicit(getASTContext(), RC));

213

216

218}

219

222

223 if (T->isArrayType() || T->isStructureType())

224 return 16;

225

226

229

230 assert(Context.getTypeSize(T) <= 64 &&

231 "Scalar bit widths larger than 64 not supported");

232

233

234 return Context.getTypeSize(T) / 8;

235}

236

237

238

241 constexpr unsigned CBufferAlign = 16;

242 if (const auto *RD = T->getAsRecordDecl()) {

243 unsigned Size = 0;

244 for (const FieldDecl *Field : RD->fields()) {

245 QualType Ty = Field->getType();

248

249

250

251 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);

252 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {

253 FieldAlign = CBufferAlign;

254 }

255

256 Size = llvm::alignTo(Size, FieldAlign);

257 Size += FieldSize;

258 }

259 return Size;

260 }

261

262 if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {

263 unsigned ElementCount = AT->getSize().getZExtValue();

264 if (ElementCount == 0)

265 return 0;

266

267 unsigned ElementSize =

269 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);

270 return AlignedElementSize * (ElementCount - 1) + ElementSize;

271 }

272

274 unsigned ElementCount = VT->getNumElements();

275 unsigned ElementSize =

277 return ElementSize * ElementCount;

278 }

279

280 return Context.getTypeSize(T) / 8;

281}

282

283

284

285

288

289

290

291 bool HasPackOffset = false;

292 bool HasNonPackOffset = false;

293 for (auto *Field : BufDecl->buffer_decls()) {

294 VarDecl *Var = dyn_cast(Field);

295 if (!Var)

296 continue;

297 if (Field->hasAttr()) {

298 PackOffsetVec.emplace_back(Var, Field->getAttr());

299 HasPackOffset = true;

300 } else {

301 HasNonPackOffset = true;

302 }

303 }

304

305 if (!HasPackOffset)

306 return;

307

308 if (HasNonPackOffset)

309 S.Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);

310

311

312

313 bool IsValid = true;

315 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),

316 [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,

317 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {

318 return LHS.second->getOffsetInBytes() <

319 RHS.second->getOffsetInBytes();

320 });

321 for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {

322 VarDecl *Var = PackOffsetVec[i].first;

323 HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;

325 unsigned Begin = Attr->getOffsetInBytes();

326 unsigned End = Begin + Size;

327 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();

328 if (End > NextBegin) {

329 VarDecl *NextVar = PackOffsetVec[i + 1].first;

330 S.Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)

331 << NextVar << Var;

332 IsValid = false;

333 }

334 }

336}

337

338

341 CAT = dyn_cast(

343 return CAT != nullptr;

344}

345

350

351static const HLSLAttributedResourceType *

354 "expected array of resource records");

356 while (const ArrayType *AT = dyn_cast(Ty))

358 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);

359}

360

361

362

363

364

368 return true;

370 return RD->isEmpty();

373 return true;

375 return true;

376 return false;

377}

378

379

380

381

382

383

386 return true;

387

389 QualType Ty = Field->getType();

391 return true;

394 return true;

395 }

396

399 Base.getType()->castAsCXXRecordDecl()))

400 return true;

401 return false;

402}

403

410 assert(RD == nullptr &&

411 "there should be at most 1 record by a given name in a scope");

412 RD = FoundRD;

413 }

414 }

415 return RD;

416}

417

418

419

420

422 bool MustBeUnique) {

424

427 if (NameBaseII) {

428 Name.append(NameBaseII->getName());

429 } else {

430

431 Name.append("anon");

432 MustBeUnique = true;

433 }

434

435 size_t NameLength = Name.size();

437 if (!MustBeUnique)

438 return II;

439

440 unsigned suffix = 0;

441 while (true) {

442 if (suffix != 0) {

443 Name.append("_");

444 Name.append(llvm::Twine(suffix).str());

445 II = &AST.Idents.get(Name, tok::TokenKind::identifier);

446 }

448 return II;

449

450

451 suffix++;

452 Name.truncate(NameLength);

453 };

454}

455

456

457

462 return nullptr;

463

467 if (!RD)

468 return nullptr;

470 }

471 }

472

480 return Field;

481}

482

483

484

485

486

487

488

489

493 "struct is already HLSL buffer compatible");

494

498

499

501 return RD;

502

507 LS->addAttr(PackedAttr::CreateImplicit(AST));

509

510

511 if (unsigned NumBases = StructDecl->getNumBases()) {

512 assert(NumBases == 1 && "HLSL supports only one base type");

513 (void)NumBases;

518 if (BaseDecl) {

523 }

524 }

525 if (BaseDecl) {

528 }

529 }

530

531

537 }

539

541 return nullptr;

542

544 return LS;

545}

546

547

548

549

550

551

552

553

554

558

562 LS->addAttr(PackedAttr::CreateImplicit(AST));

565

567 VarDecl *VD = dyn_cast(D);

570 continue;

574

576

580 }

581 }

584}

585

587 uint32_t ImplicitBindingOrderID) {

589 HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {});

590 Attr->setBinding(RT, std::nullopt, 0);

591 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);

593}

594

595

598 BufDecl->setRBraceLoc(RBrace);

599

601

603

604

608

609

610 uint32_t OrderID = getNextImplicitBindingOrderID();

613 else

615 BufDecl->isCBuffer() ? RegisterType::CBuffer

616 : RegisterType::SRV,

617 OrderID);

618 }

619

620 SemaRef.PopDeclContext();

621}

622

625 int X, int Y, int Z) {

626 if (HLSLNumThreadsAttr *NT = D->getAttr()) {

627 if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) {

628 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;

629 Diag(AL.getLoc(), diag::note_conflicting_attribute);

630 }

631 return nullptr;

632 }

635}

636

639 int Min, int Max, int Preferred,

640 int SpelledArgsCount) {

641 if (HLSLWaveSizeAttr *WS = D->getAttr()) {

642 if (WS->getMin() != Min || WS->getMax() != Max ||

643 WS->getPreferred() != Preferred ||

644 WS->getSpelledArgsCount() != SpelledArgsCount) {

645 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;

646 Diag(AL.getLoc(), diag::note_conflicting_attribute);

647 }

648 return nullptr;

649 }

652 Result->setSpelledArgsCount(SpelledArgsCount);

654}

655

656HLSLVkConstantIdAttr *

658 int Id) {

659

662 Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;

663 return nullptr;

664 }

665

667

670 Diag(VD->getLocation(), diag::err_specialization_const);

671 return nullptr;

672 }

673

674 if (!VD->getType().isConstQualified()) {

675 Diag(VD->getLocation(), diag::err_specialization_const);

676 return nullptr;

677 }

678

679 if (HLSLVkConstantIdAttr *CI = D->getAttr()) {

680 if (CI->getId() != Id) {

681 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;

682 Diag(AL.getLoc(), diag::note_conflicting_attribute);

683 }

684 return nullptr;

685 }

686

687 HLSLVkConstantIdAttr *Result =

690}

691

692HLSLShaderAttr *

694 llvm::Triple::EnvironmentType ShaderType) {

695 if (HLSLShaderAttr *NT = D->getAttr()) {

696 if (NT->getType() != ShaderType) {

697 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;

698 Diag(AL.getLoc(), diag::note_conflicting_attribute);

699 }

700 return nullptr;

701 }

702 return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL);

703}

704

705HLSLParamModifierAttr *

707 HLSLParamModifierAttr::Spelling Spelling) {

708

709

710 if (HLSLParamModifierAttr *PA = D->getAttr()) {

711 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||

712 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {

713 D->dropAttr();

715 return HLSLParamModifierAttr::Create(

716 getASTContext(), true, AdjustedRange,

717 HLSLParamModifierAttr::Keyword_inout);

718 }

719 Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;

720 Diag(PA->getLocation(), diag::note_conflicting_attribute);

721 return nullptr;

722 }

723 return HLSLParamModifierAttr::Create(getASTContext(), AL);

724}

725

728

730 return;

731

732

733

736 if (SignatureDecl) {

737 FD->dropAttr();

738

740 SourceRange(), ParsedAttr::Form::Microsoft());

742 getASTContext(), AL, RootSigOverrideIdent, SignatureDecl));

743 }

744

745 llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment();

746 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {

747 if (const auto *Shader = FD->getAttr()) {

748

749

750 if (Shader->getType() != Env) {

751 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)

752 << Shader;

754 }

755 } else {

756

757

760 }

761 } else {

762 switch (Env) {

763 case llvm::Triple::UnknownEnvironment:

764 case llvm::Triple::Library:

765 break;

766 case llvm::Triple::RootSignature:

767 llvm_unreachable("rootsig environment has no functions");

768 default:

769 llvm_unreachable("Unhandled environment in triple");

770 }

771 }

772}

773

775 HLSLAppliedSemanticAttr *Semantic,

776 bool IsInput) {

778 return false;

779

780 const auto *ShaderAttr = FD->getAttr();

781 assert(ShaderAttr && "Entry point has no shader attribute");

782 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();

783 auto SemanticName = Semantic->getSemanticName().upper();

784

785

786

787

788 if (SemanticName == "SV_POSITION") {

789 return (ST == llvm::Triple::Vertex && !IsInput) ||

790 (ST == llvm::Triple::Pixel && IsInput);

791 }

792

793 return false;

794}

795

796bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,

799 SemanticInfo &ActiveSemantic,

800 SemaHLSL::SemanticContext &SC) {

801 if (ActiveSemantic.Semantic == nullptr) {

802 ActiveSemantic.Semantic = D->getAttr();

803 if (ActiveSemantic.Semantic)

804 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();

805 }

806

807 if (!ActiveSemantic.Semantic) {

808 Diag(D->getLocation(), diag::err_hlsl_missing_semantic_annotation);

809 return false;

810 }

811

813 HLSLAppliedSemanticAttr(getASTContext(), *ActiveSemantic.Semantic,

814 ActiveSemantic.Semantic->getAttrName()->getName(),

815 ActiveSemantic.Index.value_or(0));

816 if (!A)

818

819 checkSemanticAnnotation(FD, D, A, SC);

820 OutputDecl->addAttr(A);

821

822 unsigned Location = ActiveSemantic.Index.value_or(0);

823

825 SC.CurrentIOType & IOType::In)) {

826 bool HasVkLocation = false;

827 if (auto *A = D->getAttr()) {

828 HasVkLocation = true;

829 Location = A->getLocation();

830 }

831

832 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {

833 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);

834 return false;

835 }

836 SC.UsesExplicitVkLocations = HasVkLocation;

837 }

838

839 const ConstantArrayType *AT = dyn_cast(D->getType());

840 unsigned ElementCount = AT ? AT->getZExtSize() : 1;

841 ActiveSemantic.Index = Location + ElementCount;

842

843 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());

844 for (unsigned I = 0; I < ElementCount; ++I) {

845 Twine VariableName = BaseName.concat(Twine(Location + I));

846

847 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());

848 if (!Inserted) {

849 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)

850 << VariableName.str();

851 return false;

852 }

853 }

854

855 return true;

856}

857

858bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,

861 SemanticInfo &ActiveSemantic,

862 SemaHLSL::SemanticContext &SC) {

863 if (ActiveSemantic.Semantic == nullptr) {

864 ActiveSemantic.Semantic = D->getAttr();

865 if (ActiveSemantic.Semantic)

866 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();

867 }

868

871

872 const RecordType *RT = dyn_cast(T);

873 if (!RT)

874 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,

875 SC);

876

877 const RecordDecl *RD = RT->getDecl();

878 for (FieldDecl *Field : RD->fields()) {

879 SemanticInfo Info = ActiveSemantic;

880 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {

881 Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field;

882 return false;

883 }

884 if (ActiveSemantic.Semantic)

885 ActiveSemantic = Info;

886 }

887

888 return true;

889}

890

892 const auto *ShaderAttr = FD->getAttr();

893 assert(ShaderAttr && "Entry point has no shader attribute");

894 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();

897 switch (ST) {

898 case llvm::Triple::Pixel:

899 case llvm::Triple::Vertex:

900 case llvm::Triple::Geometry:

901 case llvm::Triple::Hull:

902 case llvm::Triple::Domain:

903 case llvm::Triple::RayGeneration:

904 case llvm::Triple::Intersection:

905 case llvm::Triple::AnyHit:

906 case llvm::Triple::ClosestHit:

907 case llvm::Triple::Miss:

908 case llvm::Triple::Callable:

909 if (const auto *NT = FD->getAttr()) {

910 diagnoseAttrStageMismatch(NT, ST,

911 {llvm::Triple::Compute,

912 llvm::Triple::Amplification,

913 llvm::Triple::Mesh});

915 }

916 if (const auto *WS = FD->getAttr()) {

917 diagnoseAttrStageMismatch(WS, ST,

918 {llvm::Triple::Compute,

919 llvm::Triple::Amplification,

920 llvm::Triple::Mesh});

922 }

923 break;

924

925 case llvm::Triple::Compute:

926 case llvm::Triple::Amplification:

927 case llvm::Triple::Mesh:

928 if (!FD->hasAttr()) {

929 Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)

930 << llvm::Triple::getEnvironmentTypeName(ST);

932 }

933 if (const auto *WS = FD->getAttr()) {

934 if (Ver < VersionTuple(6, 6)) {

935 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)

936 << WS << "6.6";

938 } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {

940 WS->getLocation(),

941 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)

942 << WS << WS->getSpelledArgsCount() << "6.8";

944 }

945 }

946 break;

947 case llvm::Triple::RootSignature:

948 llvm_unreachable("rootsig environment has no function entry point");

949 default:

950 llvm_unreachable("Unhandled environment in triple");

951 }

952

953 SemaHLSL::SemanticContext InputSC = {};

954 InputSC.CurrentIOType = IOType::In;

955

957 SemanticInfo ActiveSemantic;

958 ActiveSemantic.Semantic = Param->getAttr();

959 if (ActiveSemantic.Semantic)

960 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();

961

962

963 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, InputSC)) {

964 Diag(Param->getLocation(), diag::note_previous_decl) << Param;

966 }

967 }

968

969 SemanticInfo ActiveSemantic;

970 SemaHLSL::SemanticContext OutputSC = {};

971 OutputSC.CurrentIOType = IOType::Out;

972 ActiveSemantic.Semantic = FD->getAttr();

973 if (ActiveSemantic.Semantic)

974 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();

976 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);

977}

978

979void SemaHLSL::checkSemanticAnnotation(

981 const HLSLAppliedSemanticAttr *SemanticAttr, const SemanticContext &SC) {

982 auto *ShaderAttr = EntryPoint->getAttr();

983 assert(ShaderAttr && "Entry point has no shader attribute");

984 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();

985

986 auto SemanticName = SemanticAttr->getSemanticName().upper();

987 if (SemanticName == "SV_DISPATCHTHREADID" ||

988 SemanticName == "SV_GROUPINDEX" || SemanticName == "SV_GROUPTHREADID" ||

989 SemanticName == "SV_GROUPID") {

990

991 if (ST != llvm::Triple::Compute)

992 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,

993 {{llvm::Triple::Compute, IOType::In}});

994

995 if (SemanticAttr->getSemanticIndex() != 0) {

996 std::string PrettyName =

997 "'" + SemanticAttr->getSemanticName().str() + "'";

998 Diag(SemanticAttr->getLoc(),

999 diag::err_hlsl_semantic_indexing_not_supported)

1000 << PrettyName;

1001 }

1002 return;

1003 }

1004

1005 if (SemanticName == "SV_POSITION") {

1006

1007

1008 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,

1009 {{llvm::Triple::Vertex, IOType::InOut},

1010 {llvm::Triple::Pixel, IOType::In}});

1011 return;

1012 }

1013

1014 if (SemanticName == "SV_TARGET") {

1015 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,

1016 {{llvm::Triple::Pixel, IOType::Out}});

1017 return;

1018 }

1019

1020

1021

1022 if (SemanticAttr->getAttrName()->getName().starts_with_insensitive("SV_"))

1023 llvm_unreachable("Unknown SemanticAttr");

1024}

1025

1026void SemaHLSL::diagnoseAttrStageMismatch(

1027 const Attr *A, llvm::Triple::EnvironmentType Stage,

1028 std::initializer_listllvm::Triple::EnvironmentType AllowedStages) {

1029 SmallVector<StringRef, 8> StageStrings;

1030 llvm::transform(AllowedStages, std::back_inserter(StageStrings),

1031 [](llvm::Triple::EnvironmentType ST) {

1032 return StringRef(

1033 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));

1034 });

1035 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)

1036 << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)

1037 << (AllowedStages.size() != 1) << join(StageStrings, ", ");

1038}

1039

1040void SemaHLSL::diagnoseSemanticStageMismatch(

1041 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,

1042 std::initializer_list Allowed) {

1043

1044 for (auto &Case : Allowed) {

1045 if (Case.Stage != Stage)

1046 continue;

1047

1048 if (CurrentIOType & Case.AllowedIOTypesMask)

1049 return;

1050

1051 SmallVector<std::string, 8> ValidCases;

1052 llvm::transform(

1053 Allowed, std::back_inserter(ValidCases), [](SemanticStageInfo Case) {

1054 SmallVector<std::string, 2> ValidType;

1055 if (Case.AllowedIOTypesMask & IOType::In)

1056 ValidType.push_back("input");

1057 if (Case.AllowedIOTypesMask & IOType::Out)

1058 ValidType.push_back("output");

1059 return std::string(

1060 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +

1061 " " + join(ValidType, "/");

1062 });

1063 Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)

1064 << A->getAttrName() << (CurrentIOType & IOType::In ? "input" : "output")

1065 << llvm::Triple::getEnvironmentTypeName(Case.Stage)

1066 << join(ValidCases, ", ");

1067 return;

1068 }

1069

1070 SmallVector<StringRef, 8> StageStrings;

1071 llvm::transform(

1072 Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {

1073 return StringRef(

1074 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));

1075 });

1076

1077 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)

1078 << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)

1079 << (Allowed.size() != 1) << join(StageStrings, ", ");

1080}

1081

1082template

1085 Ty = VTy->getElementType();

1088}

1089

1090template

1095

1101

1102 if (LHSFloat && RHSFloat) {

1103 if (IsCompAssign ||

1106

1108 }

1109

1110 if (LHSFloat)

1112

1113 assert(RHSFloat);

1114 if (IsCompAssign)

1116

1118}

1119

1123

1128

1129

1130 if (LHSSigned == RHSSigned) {

1131 if (IsCompAssign || IntOrder >= 0)

1133

1135 }

1136

1137

1138

1139 if (IntOrder != (LHSSigned ? 1 : -1)) {

1140 if (IsCompAssign || RHSSigned)

1143 }

1144

1145

1146

1147

1148 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {

1149 if (IsCompAssign || LHSSigned)

1152 }

1153

1154

1155

1156

1157

1158

1159

1160

1161 if (IsCompAssign)

1163

1164

1165 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);

1166 QualType NewTy = Ctx.getExtVectorType(

1169

1171}

1172

1176 return CK_FloatingCast;

1178 return CK_IntegralCast;

1180 return CK_IntegralToFloating;

1182 return CK_FloatingToIntegral;

1183}

1184

1188 bool IsCompAssign) {

1192

1193

1194

1195 if (!LVecTy && IsCompAssign) {

1197 RHS = SemaRef.ImpCastExprToType(RHS.get(), RElTy, CK_HLSLVectorTruncation);

1199 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))

1200 return LHSType;

1201 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSType,

1203 return LHSType;

1204 }

1205

1206 unsigned EndSz = std::numeric_limits::max();

1207 unsigned LSz = 0;

1208 if (LVecTy)

1209 LSz = EndSz = LVecTy->getNumElements();

1210 if (RVecTy)

1212 assert(EndSz != std::numeric_limits::max() &&

1213 "one of the above should have had a value");

1214

1215

1216

1217 if (IsCompAssign && LSz != EndSz) {

1219 diag::err_hlsl_vector_compound_assignment_truncation)

1220 << LHSType << RHSType;

1222 }

1223

1226 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)

1228

1229 if (!RVecTy)

1231 if (!IsCompAssign && !LVecTy)

1233

1234

1235 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))

1236 return Ctx.getCommonSugaredType(LHSType, RHSType);

1237

1240

1241

1244 LElTy, RElTy, IsCompAssign);

1245

1247 "HLSL Vectors can only contain integer or floating point types");

1249 LElTy, RElTy, IsCompAssign);

1250}

1251

1254 assert((Opc == BO_LOr || Opc == BO_LAnd) &&

1255 "Called with non-logical operator");

1257 llvm::raw_svector_ostream OS(Buff);

1259 StringRef NewFnName = Opc == BO_LOr ? "or" : "and";

1260 OS << NewFnName << "(";

1262 OS << ", ";

1264 OS << ")";

1268}

1269

1270std::pair<IdentifierInfo *, bool>

1273 std::string IdStr = "__hlsl_rootsig_decl_" + std::to_string(Hash);

1275

1276

1280 return {DeclIdent, Found};

1281}

1282

1286

1288 return;

1289

1291 for (auto &RootSigElement : RootElements)

1292 Elements.push_back(RootSigElement.getElement());

1293

1295 SemaRef.getASTContext(), SemaRef.CurContext, Loc,

1296 DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements);

1297

1298 SignatureDecl->setImplicit();

1299 SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());

1300}

1301

1304 if (RootSigOverrideIdent) {

1307 if (SemaRef.LookupQualifiedName(R, DC))

1308 return dyn_cast(R.getFoundDecl());

1309 }

1310

1311 return nullptr;

1312}

1313

1314namespace {

1315

1316struct PerVisibilityBindingChecker {

1318

1319 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;

1320

1321 struct ElemInfo {

1323 llvm::dxbc::ShaderVisibility Vis;

1324 bool Diagnosed;

1325 };

1327

1328 PerVisibilityBindingChecker(SemaHLSL *S) : S(S) {}

1329

1330 void trackBinding(llvm::dxbc::ShaderVisibility Visibility,

1331 llvm::dxil::ResourceClass RC, uint32_t Space,

1332 uint32_t LowerBound, uint32_t UpperBound,

1333 const hlsl::RootSignatureElement *Elem) {

1335 assert(BuilderIndex < Builders.size() &&

1336 "Not enough builders for visibility type");

1337 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,

1338 static_cast<const void *>(Elem));

1339

1340 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,

1341 "'All' visibility must come first");

1342 if (Visibility == llvm::dxbc::ShaderVisibility::All)

1343 for (size_t I = 1, E = Builders.size(); I < E; ++I)

1344 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,

1345 static_cast<const void *>(Elem));

1346

1347 ElemInfoMap.push_back({Elem, Visibility, false});

1348 }

1349

1350 ElemInfo &getInfo(const hlsl::RootSignatureElement *Elem) {

1351 auto It = llvm::lower_bound(

1352 ElemInfoMap, Elem,

1353 [](const auto &LHS, const auto &RHS) { return LHS.Elem < RHS; });

1354 assert(It->Elem == Elem && "Element not in map");

1355 return *It;

1356 }

1357

1358 bool checkOverlap() {

1359 llvm::sort(ElemInfoMap, [](const auto &LHS, const auto &RHS) {

1360 return LHS.Elem < RHS.Elem;

1361 });

1362

1363 bool HadOverlap = false;

1364

1365 using llvm::hlsl::BindingInfoBuilder;

1366 auto ReportOverlap = [this,

1367 &HadOverlap](const BindingInfoBuilder &Builder,

1368 const llvm::hlsl::Binding &Reported) {

1369 HadOverlap = true;

1370

1371 const auto *Elem =

1372 static_cast<const hlsl::RootSignatureElement *>(Reported.Cookie);

1373 const llvm::hlsl::Binding &Previous = Builder.findOverlapping(Reported);

1374 const auto *PrevElem =

1375 static_cast<const hlsl::RootSignatureElement *>(Previous.Cookie);

1376

1377 ElemInfo &Info = getInfo(Elem);

1378

1379

1380 if (Info.Diagnosed)

1381 return;

1382 Info.Diagnosed = true;

1383

1384 ElemInfo &PrevInfo = getInfo(PrevElem);

1385 llvm::dxbc::ShaderVisibility CommonVis =

1386 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis

1387 : Info.Vis;

1388

1389 this->S->Diag(Elem->getLocation(), diag::err_hlsl_resource_range_overlap)

1390 << llvm::to_underlying(Reported.RC) << Reported.LowerBound

1391 << Reported.isUnbounded() << Reported.UpperBound

1393 << Previous.isUnbounded() << Previous.UpperBound << Reported.Space

1394 << CommonVis;

1395

1396 this->S->Diag(PrevElem->getLocation(),

1397 diag::note_hlsl_resource_range_here);

1398 };

1399

1400 for (BindingInfoBuilder &Builder : Builders)

1401 Builder.calculateBindingInfo(ReportOverlap);

1402

1403 return HadOverlap;

1404 }

1405};

1406

1412 return nullptr;

1414}

1415

1416}

1417

1420 return false;

1423 return false;

1424 const FieldDecl *SecondField = *It;

1425 if (const auto *ResTy =

1426 SecondField->getType()->getAs()) {

1427 return ResTy->getAttrs().IsCounter;

1428 }

1429 return false;

1430}

1431

1434

1435 bool HadError = false;

1436 auto ReportError = [this, &HadError](SourceLocation Loc, uint32_t LowerBound,

1437 uint32_t UpperBound) {

1438 HadError = true;

1439 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)

1440 << LowerBound << UpperBound;

1441 };

1442

1443 auto ReportFloatError = [this, &HadError](SourceLocation Loc,

1444 float LowerBound,

1445 float UpperBound) {

1446 HadError = true;

1447 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)

1448 << llvm::formatv("{0:f}", LowerBound).sstr<6>()

1449 << llvm::formatv("{0:f}", UpperBound).sstr<6>();

1450 };

1451

1452 auto VerifyRegister = [ReportError](SourceLocation Loc, uint32_t Register) {

1453 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))

1454 ReportError(Loc, 0, 0xfffffffe);

1455 };

1456

1457 auto VerifySpace = [ReportError](SourceLocation Loc, uint32_t Space) {

1458 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))

1459 ReportError(Loc, 0, 0xffffffef);

1460 };

1461

1462 const uint32_t Version =

1463 llvm::to_underlying(SemaRef.getLangOpts().HLSLRootSigVer);

1464 const uint32_t VersionEnum = Version - 1;

1465 auto ReportFlagError = [this, &HadError, VersionEnum](SourceLocation Loc) {

1466 HadError = true;

1467 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)

1468 << VersionEnum;

1469 };

1470

1471

1474 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();

1475 if (const auto *Descriptor =

1476 std::get_ifllvm::hlsl::rootsig::RootDescriptor(&Elem)) {

1477 VerifyRegister(Loc, Descriptor->Reg.Number);

1478 VerifySpace(Loc, Descriptor->Space);

1479

1480 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,

1481 Descriptor->Flags))

1482 ReportFlagError(Loc);

1483 } else if (const auto *Constants =

1484 std::get_ifllvm::hlsl::rootsig::RootConstants(&Elem)) {

1485 VerifyRegister(Loc, Constants->Reg.Number);

1486 VerifySpace(Loc, Constants->Space);

1487 } else if (const auto *Sampler =

1488 std::get_ifllvm::hlsl::rootsig::StaticSampler(&Elem)) {

1489 VerifyRegister(Loc, Sampler->Reg.Number);

1490 VerifySpace(Loc, Sampler->Space);

1491

1493 "By construction, parseFloatParam can't produce a NaN from a "

1494 "float_literal token");

1495

1496 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))

1497 ReportError(Loc, 0, 16);

1498 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))

1499 ReportFloatError(Loc, -16.f, 15.99f);

1500 } else if (const auto *Clause =

1501 std::get_ifllvm::hlsl::rootsig::DescriptorTableClause(

1502 &Elem)) {

1503 VerifyRegister(Loc, Clause->Reg.Number);

1504 VerifySpace(Loc, Clause->Space);

1505

1506 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {

1507

1508

1509

1510 ReportError(Loc, 1, 0xfffffffe);

1511 }

1512

1513 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,

1514 Clause->Flags))

1515 ReportFlagError(Loc);

1516 }

1517 }

1518

1519 PerVisibilityBindingChecker BindingChecker(this);

1520 SmallVector<std::pair<const llvm::hlsl::rootsig::DescriptorTableClause *,

1522 UnboundClauses;

1523

1525 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();

1526 if (const auto *Descriptor =

1527 std::get_ifllvm::hlsl::rootsig::RootDescriptor(&Elem)) {

1528 uint32_t LowerBound(Descriptor->Reg.Number);

1529 uint32_t UpperBound(LowerBound);

1530

1531 BindingChecker.trackBinding(

1532 Descriptor->Visibility,

1533 static_castllvm::dxil::ResourceClass\(Descriptor->Type),

1534 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);

1535 } else if (const auto *Constants =

1536 std::get_ifllvm::hlsl::rootsig::RootConstants(&Elem)) {

1537 uint32_t LowerBound(Constants->Reg.Number);

1538 uint32_t UpperBound(LowerBound);

1539

1540 BindingChecker.trackBinding(

1541 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,

1542 Constants->Space, LowerBound, UpperBound, &RootSigElem);

1543 } else if (const auto *Sampler =

1544 std::get_ifllvm::hlsl::rootsig::StaticSampler(&Elem)) {

1545 uint32_t LowerBound(Sampler->Reg.Number);

1546 uint32_t UpperBound(LowerBound);

1547

1548 BindingChecker.trackBinding(

1549 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,

1550 Sampler->Space, LowerBound, UpperBound, &RootSigElem);

1551 } else if (const auto *Clause =

1552 std::get_ifllvm::hlsl::rootsig::DescriptorTableClause(

1553 &Elem)) {

1554

1555 UnboundClauses.emplace_back(Clause, &RootSigElem);

1556 } else if (const auto *Table =

1557 std::get_ifllvm::hlsl::rootsig::DescriptorTable(&Elem)) {

1558 assert(UnboundClauses.size() == Table->NumClauses &&

1559 "Number of unbound elements must match the number of clauses");

1560 bool HasAnySampler = false;

1561 bool HasAnyNonSampler = false;

1562 uint64_t Offset = 0;

1563 bool IsPrevUnbound = false;

1564 for (const auto &[Clause, ClauseElem] : UnboundClauses) {

1566 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)

1567 HasAnySampler = true;

1568 else

1569 HasAnyNonSampler = true;

1570

1571 if (HasAnySampler && HasAnyNonSampler)

1572 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);

1573

1574

1575

1576

1577 if (Clause->NumDescriptors == 0)

1578 return true;

1579

1580 bool IsAppending =

1581 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;

1582 if (!IsAppending)

1583 Offset = Clause->Offset;

1584

1585 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(

1586 Offset, Clause->NumDescriptors);

1587

1588 if (IsPrevUnbound && IsAppending)

1589 Diag(Loc, diag::err_hlsl_appending_onto_unbound);

1590 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))

1591 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;

1592

1593

1594 Offset = RangeBound + 1;

1595 IsPrevUnbound = Clause->NumDescriptors ==

1596 llvm::hlsl::rootsig::NumDescriptorsUnbounded;

1597

1598

1599 uint32_t LowerBound(Clause->Reg.Number);

1600 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(

1601 LowerBound, Clause->NumDescriptors);

1602

1603 BindingChecker.trackBinding(

1604 Table->Visibility,

1605 static_castllvm::dxil::ResourceClass\(Clause->Type), Clause->Space,

1606 LowerBound, UpperBound, ClauseElem);

1607 }

1608 UnboundClauses.clear();

1609 }

1610 }

1611

1612 return BindingChecker.checkOverlap();

1613}

1614

1617 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;

1618 return;

1619 }

1620

1622 if (auto *RS = D->getAttr()) {

1623 if (RS->getSignatureIdent() != Ident) {

1624 Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS;

1625 return;

1626 }

1627

1628 Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << RS;

1629 return;

1630 }

1631

1634 if (auto *SignatureDecl =

1635 dyn_cast(R.getFoundDecl())) {

1638 }

1639}

1640

1642 llvm::VersionTuple SMVersion =

1645 llvm::Triple::dxil;

1646

1647 uint32_t ZMax = 1024;

1648 uint32_t ThreadMax = 1024;

1649 if (IsDXIL && SMVersion.getMajor() <= 4) {

1650 ZMax = 1;

1651 ThreadMax = 768;

1652 } else if (IsDXIL && SMVersion.getMajor() == 5) {

1653 ZMax = 64;

1654 ThreadMax = 1024;

1655 }

1656

1657 uint32_t X;

1659 return;

1660 if (X > 1024) {

1662 diag::err_hlsl_numthreads_argument_oor)

1663 << 0 << 1024;

1664 return;

1665 }

1666 uint32_t Y;

1668 return;

1669 if (Y > 1024) {

1671 diag::err_hlsl_numthreads_argument_oor)

1672 << 1 << 1024;

1673 return;

1674 }

1675 uint32_t Z;

1677 return;

1678 if (Z > ZMax) {

1680 diag::err_hlsl_numthreads_argument_oor)

1681 << 2 << ZMax;

1682 return;

1683 }

1684

1685 if (X * Y * Z > ThreadMax) {

1686 Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;

1687 return;

1688 }

1689

1691 if (NewAttr)

1693}

1694

1696 return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;

1697}

1698

1700

1701

1702 unsigned SpelledArgsCount = AL.getNumArgs();

1703 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)

1704 return;

1705

1706 uint32_t Min;

1708 return;

1709

1710 uint32_t Max = 0;

1711 if (SpelledArgsCount > 1 &&

1713 return;

1714

1715 uint32_t Preferred = 0;

1716 if (SpelledArgsCount > 2 &&

1718 return;

1719

1720 if (SpelledArgsCount > 2) {

1723 diag::err_attribute_power_of_two_in_range)

1724 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize

1725 << Preferred;

1726 return;

1727 }

1728

1729 if (Preferred < Min || Preferred > Max) {

1731 diag::err_attribute_power_of_two_in_range)

1732 << AL << Min << Max << Preferred;

1733 return;

1734 }

1735 } else if (SpelledArgsCount > 1) {

1738 diag::err_attribute_power_of_two_in_range)

1739 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;

1740 return;

1741 }

1743 Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;

1744 return;

1745 } else if (Max == Min) {

1746 Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;

1747 }

1748 } else {

1751 diag::err_attribute_power_of_two_in_range)

1752 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;

1753 return;

1754 }

1755 }

1756

1757 HLSLWaveSizeAttr *NewAttr =

1759 if (NewAttr)

1761}

1762

1764 uint32_t ID;

1766 return;

1768 HLSLVkExtBuiltinInputAttr(getASTContext(), AL, ID));

1769}

1770

1772 uint32_t Id;

1774 return;

1776 if (NewAttr)

1778}

1779

1781 uint32_t Binding = 0;

1783 return;

1784 uint32_t Set = 0;

1787 return;

1788

1791}

1792

1794 uint32_t Location;

1796 return;

1797

1799 HLSLVkLocationAttr(getASTContext(), AL, Location));

1800}

1801

1803 const auto *VT = T->getAs<VectorType>();

1804

1805 if (T->hasUnsignedIntegerRepresentation() ||

1806 (VT && VT->getNumElements() > 3)) {

1807 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)

1808 << AL << "uint/uint2/uint3";

1809 return false;

1810 }

1811

1812 return true;

1813}

1814

1816 const auto *VT = T->getAs<VectorType>();

1817 if (T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {

1818 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)

1819 << AL << "float/float1/float2/float3/float4";

1820 return false;

1821 }

1822

1823 return true;

1824}

1825

1827 std::optional Index) {

1829

1831 QualType ValueType = VD->getType();

1832 if (auto *FD = dyn_cast(D))

1834

1835 bool IsOutput = false;

1836 if (HLSLParamModifierAttr *MA = D->getAttr()) {

1837 if (MA->isOut()) {

1838 IsOutput = true;

1840 }

1841 }

1842

1843 if (SemanticName == "SV_DISPATCHTHREADID") {

1845 if (IsOutput)

1846 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;

1847 if (Index.has_value())

1848 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;

1850 return;

1851 }

1852

1853 if (SemanticName == "SV_GROUPINDEX") {

1854 if (IsOutput)

1855 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;

1856 if (Index.has_value())

1857 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;

1859 return;

1860 }

1861

1862 if (SemanticName == "SV_GROUPTHREADID") {

1864 if (IsOutput)

1865 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;

1866 if (Index.has_value())

1867 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;

1869 return;

1870 }

1871

1872 if (SemanticName == "SV_GROUPID") {

1874 if (IsOutput)

1875 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;

1876 if (Index.has_value())

1877 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;

1879 return;

1880 }

1881

1882 if (SemanticName == "SV_POSITION") {

1883 const auto *VT = ValueType->getAs<VectorType>();

1884 if (!ValueType->hasFloatingRepresentation() ||

1885 (VT && VT->getNumElements() > 4))

1886 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)

1887 << AL << "float/float1/float2/float3/float4";

1889 return;

1890 }

1891

1892 if (SemanticName == "SV_TARGET") {

1893 const auto *VT = ValueType->getAs<VectorType>();

1894 if (!ValueType->hasFloatingRepresentation() ||

1895 (VT && VT->getNumElements() > 4))

1896 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)

1897 << AL << "float/float1/float2/float3/float4";

1899 return;

1900 }

1901

1902 Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;

1903}

1904

1906 uint32_t IndexValue, ExplicitIndex;

1909 assert(IndexValue > 0 ? ExplicitIndex : true);

1910 std::optional Index =

1911 ExplicitIndex ? std::optional(IndexValue) : std::nullopt;

1912

1915 else

1917}

1918

1921 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)

1922 << AL << "shader constant in a constant buffer";

1923 return;

1924 }

1925

1926 uint32_t SubComponent;

1928 return;

1929 uint32_t Component;

1931 return;

1932

1934

1935

1936 bool IsAggregateTy = (T->isArrayType() || T->isStructureType());

1937

1938

1939 if (Component) {

1941 if (IsAggregateTy || Size > 128) {

1942 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);

1943 return;

1944 } else {

1945

1946 if ((Component * 32 + Size) > 128) {

1947 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);

1948 return;

1949 }

1951 if (const auto *VT = T->getAs<VectorType>())

1952 EltTy = VT->getElementType();

1954 if (Align > 32 && Component == 1) {

1955

1956

1957 Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)

1958 << Align << EltTy;

1959 return;

1960 }

1961 }

1962 }

1963

1966}

1967

1969 StringRef Str;

1971 if (SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))

1972 return;

1973

1974 llvm::Triple::EnvironmentType ShaderType;

1975 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {

1976 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)

1977 << AL << Str << ArgLoc;

1978 return;

1979 }

1980

1981

1982

1983 HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);

1984 if (NewAttr)

1986}

1987

1991 assert(AttrList.size() && "expected list of resource attributes");

1992

1995 SourceLocation LocBegin = AttrList[0]->getRange().getBegin();

1996 SourceLocation LocEnd = AttrList[0]->getRange().getEnd();

1997

1998 HLSLAttributedResourceType::Attributes ResAttrs;

1999

2000 bool HasResourceClass = false;

2001 for (const Attr *A : AttrList) {

2002 if (!A)

2003 continue;

2006 case attr::HLSLResourceClass: {

2008 if (HasResourceClass) {

2010 ? diag::warn_duplicate_attribute_exact

2011 : diag::warn_duplicate_attribute)

2012 << A;

2013 return false;

2014 }

2015 ResAttrs.ResourceClass = RC;

2016 HasResourceClass = true;

2017 break;

2018 }

2019 case attr::HLSLROV:

2020 if (ResAttrs.IsROV) {

2021 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;

2022 return false;

2023 }

2024 ResAttrs.IsROV = true;

2025 break;

2026 case attr::HLSLRawBuffer:

2027 if (ResAttrs.RawBuffer) {

2028 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;

2029 return false;

2030 }

2031 ResAttrs.RawBuffer = true;

2032 break;

2033 case attr::HLSLIsCounter:

2034 if (ResAttrs.IsCounter) {

2035 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;

2036 return false;

2037 }

2038 ResAttrs.IsCounter = true;

2039 break;

2040 case attr::HLSLContainedType: {

2042 QualType Ty = CTAttr->getType();

2043 if (!ContainedTy.isNull()) {

2045 ? diag::warn_duplicate_attribute_exact

2046 : diag::warn_duplicate_attribute)

2047 << A;

2048 return false;

2049 }

2050 ContainedTy = Ty;

2051 ContainedTyInfo = CTAttr->getTypeLoc();

2052 break;

2053 }

2054 default:

2055 llvm_unreachable("unhandled resource attribute type");

2056 }

2057 }

2058

2059 if (!HasResourceClass) {

2060 S.Diag(AttrList.back()->getRange().getEnd(),

2061 diag::err_hlsl_missing_resource_class);

2062 return false;

2063 }

2064

2066 Wrapped, ContainedTy, ResAttrs);

2067

2068 if (LocInfo && ContainedTyInfo) {

2071 }

2072 return true;

2073}

2074

2075

2076

2077

2078

2080

2081 if (T->isHLSLResourceType()) {

2082 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)

2084 return false;

2085 }

2086

2087

2089 return false;

2090

2091 Attr *A = nullptr;

2092

2096 {

2097 AttributeCommonInfo::AS_CXX11, 0, false ,

2098 false

2099 });

2100

2102 case ParsedAttr::AT_HLSLResourceClass: {

2104 Diag(AL.getLoc(), diag::err_attribute_argument_type)

2106 return false;

2107 }

2108

2112

2113

2114 ResourceClass RC;

2115 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {

2116 Diag(ArgLoc, diag::warn_attribute_type_not_supported)

2117 << "ResourceClass" << Identifier;

2118 return false;

2119 }

2120 A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);

2121 break;

2122 }

2123

2124 case ParsedAttr::AT_HLSLROV:

2126 break;

2127

2128 case ParsedAttr::AT_HLSLRawBuffer:

2129 A = HLSLRawBufferAttr::Create(getASTContext(), ACI);

2130 break;

2131

2132 case ParsedAttr::AT_HLSLIsCounter:

2133 A = HLSLIsCounterAttr::Create(getASTContext(), ACI);

2134 break;

2135

2136 case ParsedAttr::AT_HLSLContainedType: {

2138 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;

2139 return false;

2140 }

2141

2144 assert(TSI && "no type source info for attribute argument");

2146 diag::err_incomplete_type))

2147 return false;

2148 A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);

2149 break;

2150 }

2151

2152 default:

2153 llvm_unreachable("unhandled HLSL attribute");

2154 }

2155

2156 HLSLResourcesTypeAttrs.emplace_back(A);

2157 return true;

2158}

2159

2160

2162 if (!HLSLResourcesTypeAttrs.size())

2163 return CurrentType;

2164

2168 HLSLResourcesTypeAttrs, QT, &LocInfo)) {

2169 const HLSLAttributedResourceType *RT =

2171

2172

2173

2174

2175

2176 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));

2177 }

2178 HLSLResourcesTypeAttrs.clear();

2179 return QT;

2180}

2181

2182

2186 auto I = LocsForHLSLAttributedResources.find(RT);

2187 if (I != LocsForHLSLAttributedResources.end()) {

2188 LocInfo = I->second;

2189 LocsForHLSLAttributedResources.erase(I);

2190 return LocInfo;

2191 }

2193 return LocInfo;

2194}

2195

2196

2197

2198void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,

2199 const RecordType *RT) {

2200 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();

2203

2204

2205

2207 "incomplete arrays inside user defined types are not supported");

2211 }

2212

2214 continue;

2215

2216 if (const HLSLAttributedResourceType *AttrResType =

2217 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {

2218

2219 ResourceClass RC = AttrResType->getAttrs().ResourceClass;

2221 if (!DBI)

2222 Bindings.addDeclBindingInfo(VD, RC);

2223 } else if (const RecordType *RT = dyn_cast(Ty)) {

2224

2225

2226

2227

2228

2229 collectResourceBindingsOnUserRecordDecl(VD, RT);

2230 }

2231 }

2232}

2233

2234

2235

2236

2237

2238

2241 bool SpecifiedSpace) {

2242 int RegTypeNum = static_cast<int>(RegType);

2243

2244

2245 if (D->hasAttr()) {

2246 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;

2247 return false;

2248 }

2249

2250

2251 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast(D)) {

2252 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer

2253 : ResourceClass::SRV;

2255 return true;

2256

2257 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)

2258 << RegTypeNum;

2259 return false;

2260 }

2261

2262

2263 assert(isa(D) && "D is expected to be VarDecl or HLSLBufferDecl");

2265

2266

2267 if (const HLSLAttributedResourceType *AttrResType =

2268 HLSLAttributedResourceType::findHandleTypeOnResource(

2271 return true;

2272

2273 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)

2274 << RegTypeNum;

2275 return false;

2276 }

2277

2281

2282

2285 if (SpecifiedSpace && !DeclaredInCOrTBuffer)

2286 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);

2287

2290

2291 if (RegType == RegisterType::CBuffer)

2292 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);

2293 else if (RegType != RegisterType::C)

2294 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;

2295 else

2296 return true;

2297 } else {

2298 if (RegType == RegisterType::C)

2299 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);

2300 else

2301 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;

2302 }

2303 return false;

2304 }

2306

2307

2308 return true;

2309

2310

2311 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;

2312 return false;

2313}

2314

2317

2318

2319 bool RegisterTypesDetected[5] = {false};

2320 RegisterTypesDetected[static_cast<int>(regType)] = true;

2321

2322 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {

2323 if (HLSLResourceBindingAttr *attr =

2324 dyn_cast(*it)) {

2325

2327 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {

2328 int otherRegTypeNum = static_cast<int>(otherRegType);

2330 diag::err_hlsl_duplicate_register_annotation)

2331 << otherRegTypeNum;

2332 return false;

2333 }

2334 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;

2335 }

2336 }

2337 return true;

2338}

2339

2342 bool SpecifiedSpace) {

2343

2344

2347 "expecting VarDecl or HLSLBufferDecl");

2348

2349

2351 return false;

2352

2353

2355}

2356

2358 if (VarDecl *VD = dyn_cast(TheDecl)) {

2360 if (const auto *IAT = dyn_cast(Ty))

2361 Ty = IAT->getElementType();

2363 diag::err_incomplete_type))

2364 return;

2365 }

2366

2367 StringRef Slot = "";

2368 StringRef Space = "";

2370

2372 Diag(AL.getLoc(), diag::err_attribute_argument_type)

2374 return;

2375 }

2377

2380 SlotLoc = Loc->getLoc();

2382 Diag(AL.getLoc(), diag::err_attribute_argument_type)

2384 return;

2385 }

2388 SpaceLoc = Loc->getLoc();

2389 } else {

2391 if (Str.starts_with("space")) {

2392 Space = Str;

2393 SpaceLoc = Loc->getLoc();

2394 } else {

2395 Slot = Str;

2396 SlotLoc = Loc->getLoc();

2397 Space = "space0";

2398 }

2399 }

2400

2402 std::optional SlotNum;

2403 unsigned SpaceNum = 0;

2404

2405

2406 if (!Slot.empty()) {

2408 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);

2409 return;

2410 }

2411 if (RegType == RegisterType::I) {

2412 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);

2413 return;

2414 }

2415 StringRef SlotNumStr = Slot.substr(1);

2416 unsigned N;

2417 if (SlotNumStr.getAsInteger(10, N)) {

2418 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);

2419 return;

2420 }

2421 SlotNum = N;

2422 }

2423

2424

2425 if (!Space.starts_with("space")) {

2426 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;

2427 return;

2428 }

2429 StringRef SpaceNumStr = Space.substr(5);

2430 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {

2431 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;

2432 return;

2433 }

2434

2435

2436 if (SlotNum.has_value())

2439 return;

2440

2441 HLSLResourceBindingAttr *NewAttr =

2442 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);

2443 if (NewAttr) {

2444 NewAttr->setBinding(RegType, SlotNum, SpaceNum);

2445 TheDecl->addAttr(NewAttr);

2446 }

2447}

2448

2451 D, AL,

2452 static_castHLSLParamModifierAttr::Spelling\(AL.getSemanticSpelling()));

2453 if (NewAttr)

2455}

2456

2457namespace {

2458

2459

2460

2461

2462

2463

2464

2465

2466

2467

2468

2469

2470

2472 Sema &SemaRef;

2473

2474

2476

2477

2478

2479

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490

2491

2492

2493

2494

2495

2496

2497

2498

2499 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;

2500

2501

2502

2503 llvm::Triple::EnvironmentType CurrentShaderEnvironment;

2504 unsigned CurrentShaderStageBit;

2505

2506

2507

2508

2509 bool ReportOnlyShaderStageIssues;

2510

2511

2512 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {

2513 static_assert(sizeof(unsigned) >= 4);

2514 assert(HLSLShaderAttr::isValidShaderType(ShaderType));

2515 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&

2516 "ShaderType is too big for this bitmap");

2517

2518

2519 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;

2520 CurrentShaderEnvironment = ShaderType;

2521 CurrentShaderStageBit = (1 << bitmapIndex);

2522 }

2523

2524 void SetUnknownShaderStageContext() {

2525 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;

2526 CurrentShaderStageBit = (1 << 31);

2527 }

2528

2529 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {

2530 return CurrentShaderEnvironment;

2531 }

2532

2533 bool InUnknownShaderStageContext() const {

2534 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;

2535 }

2536

2537

2538 void AddToScannedFunctions(const FunctionDecl *FD) {

2539 unsigned &ScannedStages = ScannedDecls[FD];

2540 ScannedStages |= CurrentShaderStageBit;

2541 }

2542

2543 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }

2544

2545 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {

2546 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));

2547 }

2548

2549 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {

2550 return ScannerStages & CurrentShaderStageBit;

2551 }

2552

2553 static bool NeverBeenScanned(unsigned ScannedStages) {

2554 return ScannedStages == 0;

2555 }

2556

2557

2558 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);

2559 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,

2560 SourceRange Range);

2561 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);

2562 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);

2563

2564public:

2565 DiagnoseHLSLAvailability(Sema &SemaRef)

2566 : SemaRef(SemaRef),

2567 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),

2568 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}

2569

2570

2571 void RunOnTranslationUnit(const TranslationUnitDecl *TU);

2572 void RunOnFunction(const FunctionDecl *FD);

2573

2574 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {

2575 FunctionDecl *FD = llvm::dyn_cast(DRE->getDecl());

2576 if (FD)

2577 HandleFunctionOrMethodRef(FD, DRE);

2578 return true;

2579 }

2580

2581 bool VisitMemberExpr(MemberExpr *ME) override {

2582 FunctionDecl *FD = llvm::dyn_cast(ME->getMemberDecl());

2583 if (FD)

2584 HandleFunctionOrMethodRef(FD, ME);

2585 return true;

2586 }

2587};

2588

2589void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,

2590 Expr *RefExpr) {

2592 "expected DeclRefExpr or MemberExpr");

2593

2594

2596 if (FD->hasBody(FDWithBody)) {

2597 if (!WasAlreadyScannedInCurrentStage(FDWithBody))

2598 DeclsToScan.push_back(FDWithBody);

2599 return;

2600 }

2601

2602

2603 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);

2604 if (AA)

2605 CheckDeclAvailability(

2607}

2608

2609void DiagnoseHLSLAvailability::RunOnTranslationUnit(

2611

2612

2613

2614

2615

2616

2618 DeclContextsToScan.push_back(TU);

2619

2620 while (!DeclContextsToScan.empty()) {

2621 const DeclContext *DC = DeclContextsToScan.pop_back_val();

2622 for (auto &D : DC->decls()) {

2623

2625 continue;

2626

2627

2628

2629 if (llvm::dyn_cast(D) || llvm::dyn_cast(D)) {

2630 DeclContextsToScan.push_back(llvm::dyn_cast(D));

2631 continue;

2632 }

2633

2634

2635 const FunctionDecl *FD = llvm::dyn_cast(D);

2637 continue;

2638

2639

2640 if (HLSLShaderAttr *ShaderAttr = FD->getAttr()) {

2641 SetShaderStageContext(ShaderAttr->getType());

2642 RunOnFunction(FD);

2643 continue;

2644 }

2645

2646

2647

2649 if (!isExport) {

2650 for (const auto *Redecl : FD->redecls()) {

2651 if (Redecl->isInExportDeclContext()) {

2652 isExport = true;

2653 break;

2654 }

2655 }

2656 }

2657 if (isExport) {

2658 SetUnknownShaderStageContext();

2659 RunOnFunction(FD);

2660 continue;

2661 }

2662 }

2663 }

2664}

2665

2666void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {

2667 assert(DeclsToScan.empty() && "DeclsToScan should be empty");

2668 DeclsToScan.push_back(FD);

2669

2670 while (!DeclsToScan.empty()) {

2671

2672

2673

2674

2675 const FunctionDecl *FD = DeclsToScan.pop_back_val();

2676

2677

2678 const unsigned ScannedStages = GetScannedStages(FD);

2679 if (WasAlreadyScannedInCurrentStage(ScannedStages))

2680 continue;

2681

2682 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);

2683

2684 AddToScannedFunctions(FD);

2685 TraverseStmt(FD->getBody());

2686 }

2687}

2688

2689bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(

2690 const AvailabilityAttr *AA) {

2691 IdentifierInfo *IIEnvironment = AA->getEnvironment();

2692 if (!IIEnvironment)

2693 return true;

2694

2695 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();

2696 if (CurrentEnv == llvm::Triple::UnknownEnvironment)

2697 return false;

2698

2699 llvm::Triple::EnvironmentType AttrEnv =

2700 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());

2701

2702 return CurrentEnv == AttrEnv;

2703}

2704

2705const AvailabilityAttr *

2706DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {

2707 AvailabilityAttr const *PartialMatch = nullptr;

2708

2709

2710

2711 for (const auto *A : D->attrs()) {

2712 if (const auto *Avail = dyn_cast(A)) {

2713 StringRef AttrPlatform = Avail->getPlatform()->getName();

2714 StringRef TargetPlatform =

2716

2717

2718 if (AttrPlatform == TargetPlatform) {

2719

2720 if (HasMatchingEnvironmentOrNone(Avail))

2721 return Avail;

2722 PartialMatch = Avail;

2723 }

2724 }

2725 }

2726 return PartialMatch;

2727}

2728

2729

2730

2731void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,

2732 const AvailabilityAttr *AA,

2734

2736

2737 if (!IIEnv) {

2738

2739

2740

2741

2742

2743

2744

2745 if (SemaRef.getLangOpts().HLSLStrictAvailability)

2746 return;

2747

2748

2749

2750

2751 if (ReportOnlyShaderStageIssues)

2752 return;

2753

2754 } else {

2755

2756

2757 if (InUnknownShaderStageContext())

2758 return;

2759 }

2760

2761

2762 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);

2763 VersionTuple Introduced = AA->getIntroduced();

2766

2767 if (TargetVersion >= Introduced && EnvironmentMatches)

2768 return;

2769

2770

2772 llvm::StringRef PlatformName(

2773 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));

2774

2775 llvm::StringRef CurrentEnvStr =

2776 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());

2777

2778 llvm::StringRef AttrEnvStr =

2779 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";

2780 bool UseEnvironment = !AttrEnvStr.empty();

2781

2782 if (EnvironmentMatches) {

2783 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)

2784 << Range << D << PlatformName << Introduced.getAsString()

2785 << UseEnvironment << CurrentEnvStr;

2786 } else {

2787 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)

2789 }

2790

2791 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)

2792 << D << PlatformName << Introduced.getAsString()

2794 << UseEnvironment << AttrEnvStr << CurrentEnvStr;

2795}

2796

2797}

2798

2800

2801 if (!DefaultCBufferDecls.empty()) {

2803 SemaRef.getASTContext(), SemaRef.getCurLexicalContext(),

2804 DefaultCBufferDecls);

2806 getNextImplicitBindingOrderID());

2807 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);

2809

2810

2811 for (const Decl *VD : DefaultCBufferDecls) {

2812 const HLSLResourceBindingAttr *RBA =

2813 VD->getAttr();

2814 if (RBA && RBA->hasRegisterSlot() &&

2815 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {

2817 break;

2818 }

2819 }

2820

2822 SemaRef.Consumer.HandleTopLevelDecl(DG);

2823 }

2824 diagnoseAvailabilityViolations(TU);

2825}

2826

2828

2829

2830

2831

2834 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)

2835 return;

2836

2837 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);

2838}

2839

2843

2844 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {

2847 S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)

2848 << TheCall->getDirectCallee() << true

2851 return true;

2852 }

2853 }

2854 return false;

2855}

2856

2860 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)

2862 return true;

2863 }

2864 return false;

2865}

2866

2869 llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,

2871 Check) {

2872 for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {

2875 return true;

2876 }

2877 return false;

2878}

2879

2881 int ArgOrdinal,

2886 : PassedType;

2887 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())

2888 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)

2889 << ArgOrdinal << 5 << 0

2890 << 2 << PassedType;

2891 return false;

2892}

2893

2895 unsigned ArgIndex) {

2896 auto *Arg = TheCall->getArg(ArgIndex);

2898 if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==

2900 return false;

2901 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;

2902 return true;

2903}

2904

2908 if (!VecTy)

2909 return false;

2910

2911 if (VecTy->getElementType()->isDoubleType())

2912 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)

2913 << ArgOrdinal << 1 << 0 << 1

2914 << PassedType;

2915 return false;

2916}

2917

2919 int ArgOrdinal,

2923 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)

2924 << ArgOrdinal << 5 << 1

2925 << 1 << PassedType;

2926 return false;

2927}

2928

2930 int ArgOrdinal,

2933 if (VecTy->getElementType()->isUnsignedIntegerType())

2934 return false;

2935

2936 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)

2937 << ArgOrdinal << 4 << 3 << 0

2938 << PassedType;

2939}

2940

2941

2943 int ArgOrdinal,

2946 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)

2947 << ArgOrdinal << 5 << 3

2948 << 0 << PassedType;

2949 return false;

2950}

2951

2953 unsigned ArgOrdinal, unsigned Width) {

2956 ArgTy = VTy->getElementType();

2957

2958 uint64_t ElementBitCount =

2960 if (ElementBitCount != Width) {

2962 diag::err_integer_incorrect_bit_count)

2963 << Width << ElementBitCount;

2964 return true;

2965 }

2966 return false;

2967}

2968

2972 if (VecTyA)

2973 ReturnType =

2975

2976 TheCall->setType(ReturnType);

2977}

2978

2980 unsigned ArgIndex) {

2981 assert(TheCall->getNumArgs() >= ArgIndex);

2984

2986 (VTy &&

2989 diag::err_typecheck_expect_scalar_or_vector)

2990 << ArgType << Scalar;

2991 return true;

2992 }

2993 return false;

2994}

2995

2997 unsigned ArgIndex) {

2998 assert(TheCall->getNumArgs() >= ArgIndex);

3001

3002 if (!(ArgType->isScalarType() ||

3003 (VTy && VTy->getElementType()->isScalarType()))) {

3005 diag::err_typecheck_expect_any_scalar_or_vector)

3006 << ArgType << 1;

3007 return true;

3008 }

3009 return false;

3010}

3011

3017

3019 (VTy &&

3022 diag::err_typecheck_expect_any_scalar_or_vector)

3023 << ArgType << 0;

3024 return true;

3025 }

3026 return false;

3027}

3028

3035 diag::err_typecheck_call_different_arg_types)

3038 return true;

3039 }

3040

3042 return false;

3043}

3044

3051

3052 QualType Arg1ScalarTy = Arg1Ty;

3054 Arg1ScalarTy = VTy->getElementType();

3055

3056 QualType Arg2ScalarTy = Arg2Ty;

3058 Arg2ScalarTy = VTy->getElementType();

3059

3061 S->Diag(Arg1->getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)

3062 << 1 << TheCall->getCallee() << Arg1Ty << Arg2Ty;

3063

3065 unsigned Arg0Length = Arg0Ty->getAs<VectorType>()->getNumElements();

3066 unsigned Arg1Length = Arg1Ty->isVectorType()

3068 : 0;

3069 unsigned Arg2Length = Arg2Ty->isVectorType()

3071 : 0;

3072 if (Arg1Length > 0 && Arg0Length != Arg1Length) {

3074 diag::err_typecheck_vector_lengths_not_equal)

3077 return true;

3078 }

3079

3080 if (Arg2Length > 0 && Arg0Length != Arg2Length) {

3082 diag::err_typecheck_vector_lengths_not_equal)

3085 return true;

3086 }

3087

3090 return false;

3091}

3092

3094 Sema *S, CallExpr *TheCall, unsigned ArgIndex,

3095 llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =

3096 nullptr) {

3097 assert(TheCall->getNumArgs() >= ArgIndex);

3099 const HLSLAttributedResourceType *ResTy =

3100 ArgType.getTypePtr()->getAs();

3101 if (!ResTy) {

3103 diag::err_typecheck_expect_hlsl_resource)

3104 << ArgType;

3105 return true;

3106 }

3107 if (Check && Check(ResTy)) {

3109 diag::err_invalid_hlsl_resource_type)

3110 << ArgType;

3111 return true;

3112 }

3113 return false;

3114}

3115

3116

3117

3119 switch (BuiltinID) {

3120 case Builtin::BI__builtin_hlsl_adduint64: {

3121 if (SemaRef.checkArgCount(TheCall, 2))

3122 return true;

3123

3126 return true;

3127

3128

3130 return true;

3131

3132

3135 if (NumElementsArg != 2 && NumElementsArg != 4) {

3136 SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count)

3137 << 1 << 64 << NumElementsArg * 32;

3138 return true;

3139 }

3140

3141

3143 return true;

3144

3147

3148 TheCall->setType(ArgTyA);

3149 break;

3150 }

3151 case Builtin::BI__builtin_hlsl_resource_getpointer: {

3152 if (SemaRef.checkArgCount(TheCall, 2) ||

3155 SemaRef.getASTContext().UnsignedIntTy))

3156 return true;

3157

3158 auto *ResourceTy =

3160 QualType ContainedTy = ResourceTy->getContainedType();

3161 auto ReturnType =

3163 ReturnType = SemaRef.Context.getPointerType(ReturnType);

3164 TheCall->setType(ReturnType);

3166

3167 break;

3168 }

3169 case Builtin::BI__builtin_hlsl_resource_load_with_status: {

3170 if (SemaRef.checkArgCount(TheCall, 3) ||

3173 SemaRef.getASTContext().UnsignedIntTy) ||

3175 SemaRef.getASTContext().UnsignedIntTy) ||

3177 return true;

3178

3179 auto *ResourceTy =

3181 QualType ReturnType = ResourceTy->getContainedType();

3182 TheCall->setType(ReturnType);

3183

3184 break;

3185 }

3186

3187 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {

3188 assert(TheCall->getNumArgs() == 1 && "expected 1 arg");

3189

3191 TheCall->setType(ResourceTy);

3192 break;

3193 }

3194 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {

3195 assert(TheCall->getNumArgs() == 6 && "expected 6 args");

3196

3198 TheCall->setType(ResourceTy);

3199 break;

3200 }

3201 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {

3202 assert(TheCall->getNumArgs() == 6 && "expected 6 args");

3203

3205 TheCall->setType(ResourceTy);

3206 break;

3207 }

3208 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {

3209 assert(TheCall->getNumArgs() == 3 && "expected 3 args");

3212 auto *MainResType = MainHandleTy->getAs();

3213 auto MainAttrs = MainResType->getAttrs();

3214 assert(!MainAttrs.IsCounter && "cannot create a counter from a counter");

3215 MainAttrs.IsCounter = true;

3217 MainResType->getWrappedType(), MainResType->getContainedType(),

3218 MainAttrs);

3219

3220

3221 TheCall->setType(CounterHandleTy);

3222 break;

3223 }

3224 case Builtin::BI__builtin_hlsl_and:

3225 case Builtin::BI__builtin_hlsl_or: {

3226 if (SemaRef.checkArgCount(TheCall, 2))

3227 return true;

3229 return true;

3231 return true;

3232

3235

3236 TheCall->setType(ArgTyA);

3237 break;

3238 }

3239 case Builtin::BI__builtin_hlsl_all:

3240 case Builtin::BI__builtin_hlsl_any: {

3241 if (SemaRef.checkArgCount(TheCall, 1))

3242 return true;

3244 return true;

3245 break;

3246 }

3247 case Builtin::BI__builtin_hlsl_asdouble: {

3248 if (SemaRef.checkArgCount(TheCall, 2))

3249 return true;

3252 SemaRef.Context.UnsignedIntTy,

3253 0))

3254 return true;

3257 SemaRef.Context.UnsignedIntTy,

3258 1))

3259 return true;

3261 return true;

3262

3264 break;

3265 }

3266 case Builtin::BI__builtin_hlsl_elementwise_clamp: {

3267 if (SemaRef.BuiltinElementwiseTernaryMath(

3268 TheCall,

3270 return true;

3271 break;

3272 }

3273 case Builtin::BI__builtin_hlsl_dot: {

3274

3275 if (SemaRef.BuiltinVectorToScalarMath(TheCall))

3276 return true;

3278 return true;

3279 break;

3280 }

3281 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:

3282 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {

3283 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))

3284 return true;

3285

3286 const Expr *Arg = TheCall->getArg(0);

3289

3291

3293 EltTy = VecTy->getElementType();

3294 ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());

3295 }

3296

3298 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)

3299 << 1 << 5 << 1

3300 << 0 << ArgTy;

3301 return true;

3302 }

3303

3304 TheCall->setType(ResTy);

3305 break;

3306 }

3307 case Builtin::BI__builtin_hlsl_select: {

3308 if (SemaRef.checkArgCount(TheCall, 3))

3309 return true;

3311 return true;

3314 return true;

3316 if (VTy && VTy->getElementType()->isBooleanType() &&

3318 return true;

3319 break;

3320 }

3321 case Builtin::BI__builtin_hlsl_elementwise_saturate:

3322 case Builtin::BI__builtin_hlsl_elementwise_rcp: {

3323 if (SemaRef.checkArgCount(TheCall, 1))

3324 return true;

3325 if (!TheCall->getArg(0)

3329 diag::err_builtin_invalid_arg_type)

3330 << 1 << 5 << 0

3332 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))

3333 return true;

3334 break;

3335 }

3336 case Builtin::BI__builtin_hlsl_elementwise_degrees:

3337 case Builtin::BI__builtin_hlsl_elementwise_radians:

3338 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:

3339 case Builtin::BI__builtin_hlsl_elementwise_frac:

3340 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:

3341 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {

3342 if (SemaRef.checkArgCount(TheCall, 1))

3343 return true;

3346 return true;

3347 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))

3348 return true;

3349 break;

3350 }

3351 case Builtin::BI__builtin_hlsl_elementwise_isinf:

3352 case Builtin::BI__builtin_hlsl_elementwise_isnan: {

3353 if (SemaRef.checkArgCount(TheCall, 1))

3354 return true;

3357 return true;

3358 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))

3359 return true;

3361 break;

3362 }

3363 case Builtin::BI__builtin_hlsl_lerp: {

3364 if (SemaRef.checkArgCount(TheCall, 3))

3365 return true;

3368 return true;

3370 return true;

3371 if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))

3372 return true;

3373 break;

3374 }

3375 case Builtin::BI__builtin_hlsl_mad: {

3376 if (SemaRef.BuiltinElementwiseTernaryMath(

3377 TheCall,

3379 return true;

3380 break;

3381 }

3382 case Builtin::BI__builtin_hlsl_normalize: {

3383 if (SemaRef.checkArgCount(TheCall, 1))

3384 return true;

3387 return true;

3390

3391 TheCall->setType(ArgTyA);

3392 break;

3393 }

3394 case Builtin::BI__builtin_hlsl_elementwise_sign: {

3395 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))

3396 return true;

3399 return true;

3401 break;

3402 }

3403 case Builtin::BI__builtin_hlsl_step: {

3404 if (SemaRef.checkArgCount(TheCall, 2))

3405 return true;

3408 return true;

3409

3412

3413 TheCall->setType(ArgTyA);

3414 break;

3415 }

3416 case Builtin::BI__builtin_hlsl_wave_active_max:

3417 case Builtin::BI__builtin_hlsl_wave_active_min:

3418 case Builtin::BI__builtin_hlsl_wave_active_sum: {

3419 if (SemaRef.checkArgCount(TheCall, 1))

3420 return true;

3421

3422

3424 return true;

3426 return true;

3429 TheCall->setType(ArgTyExpr);

3430 break;

3431 }

3432

3433

3434 case Builtin::BI__builtin_elementwise_bitreverse: {

3435

3436

3439 return true;

3440 break;

3441 }

3442 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {

3443 if (SemaRef.checkArgCount(TheCall, 2))

3444 return true;

3445

3446

3451 diag::err_typecheck_convert_incompatible)

3452 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;

3453 return true;

3454 }

3455

3456

3458 return true;

3459

3462 TheCall->setType(ArgTyExpr);

3463 break;

3464 }

3465 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {

3466 if (SemaRef.checkArgCount(TheCall, 0))

3467 return true;

3468 break;

3469 }

3470 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {

3471 if (SemaRef.checkArgCount(TheCall, 3))

3472 return true;

3473

3476 1) ||

3478 2))

3479 return true;

3480

3483 return true;

3484 break;

3485 }

3486 case Builtin::BI__builtin_hlsl_elementwise_clip: {

3487 if (SemaRef.checkArgCount(TheCall, 1))

3488 return true;

3489

3491 return true;

3492 break;

3493 }

3494 case Builtin::BI__builtin_elementwise_acos:

3495 case Builtin::BI__builtin_elementwise_asin:

3496 case Builtin::BI__builtin_elementwise_atan:

3497 case Builtin::BI__builtin_elementwise_atan2:

3498 case Builtin::BI__builtin_elementwise_ceil:

3499 case Builtin::BI__builtin_elementwise_cos:

3500 case Builtin::BI__builtin_elementwise_cosh:

3501 case Builtin::BI__builtin_elementwise_exp:

3502 case Builtin::BI__builtin_elementwise_exp2:

3503 case Builtin::BI__builtin_elementwise_exp10:

3504 case Builtin::BI__builtin_elementwise_floor:

3505 case Builtin::BI__builtin_elementwise_fmod:

3506 case Builtin::BI__builtin_elementwise_log:

3507 case Builtin::BI__builtin_elementwise_log2:

3508 case Builtin::BI__builtin_elementwise_log10:

3509 case Builtin::BI__builtin_elementwise_pow:

3510 case Builtin::BI__builtin_elementwise_roundeven:

3511 case Builtin::BI__builtin_elementwise_sin:

3512 case Builtin::BI__builtin_elementwise_sinh:

3513 case Builtin::BI__builtin_elementwise_sqrt:

3514 case Builtin::BI__builtin_elementwise_tan:

3515 case Builtin::BI__builtin_elementwise_tanh:

3516 case Builtin::BI__builtin_elementwise_trunc: {

3519 return true;

3520 break;

3521 }

3522 case Builtin::BI__builtin_hlsl_buffer_update_counter: {

3523 assert(TheCall->getNumArgs() == 2 && "expected 2 args");

3524 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {

3525 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&

3526 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());

3527 };

3529 return true;

3530 Expr *OffsetExpr = TheCall->getArg(1);

3531 std::optionalllvm::APSInt Offset =

3533 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {

3535 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)

3536 << 1;

3537 return true;

3538 }

3539 break;

3540 }

3541 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {

3542 if (SemaRef.checkArgCount(TheCall, 1))

3543 return true;

3546 return true;

3547

3549 return true;

3550

3553 ArgTy = VTy->getElementType();

3556 diag::err_builtin_invalid_arg_type)

3557 << 1 << 5 << 3

3558 << 0 << TheCall->getArg(0)->getType();

3559 return true;

3560 }

3561

3563 break;

3564 }

3565 }

3566 return false;

3567}

3568

3572 WorkList.push_back(BaseTy);

3573 while (!WorkList.empty()) {

3574 QualType T = WorkList.pop_back_val();

3575 T = T.getCanonicalType().getUnqualifiedType();

3576 if (const auto *AT = dyn_cast(T)) {

3578

3579

3580

3581

3583

3584 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)

3585 llvm::append_range(List, ElementFields);

3586 continue;

3587 }

3588

3589

3590 if (const auto *VT = dyn_cast(T)) {

3591 List.insert(List.end(), VT->getNumElements(), VT->getElementType());

3592 continue;

3593 }

3594 if (const auto *MT = dyn_cast(T)) {

3595 List.insert(List.end(), MT->getNumElementsFlattened(),

3596 MT->getElementType());

3597 continue;

3598 }

3599 if (const auto *RD = T->getAsCXXRecordDecl()) {

3600 if (RD->isStandardLayout())

3601 RD = RD->getStandardLayoutBaseWithFields();

3602

3603

3604

3605 if (RD->isUnion() || !RD->isAggregate()) {

3606 List.push_back(T);

3607 continue;

3608 }

3609

3611 for (const auto *FD : RD->fields())

3612 if (!FD->isUnnamedBitField())

3613 FieldTypes.push_back(FD->getType());

3614

3615 std::reverse(FieldTypes.begin(), FieldTypes.end());

3616 llvm::append_range(WorkList, FieldTypes);

3617

3618

3619

3620 if (!RD->isStandardLayout()) {

3621 FieldTypes.clear();

3622 for (const auto &Base : RD->bases())

3623 FieldTypes.push_back(Base.getType());

3624 std::reverse(FieldTypes.begin(), FieldTypes.end());

3625 llvm::append_range(WorkList, FieldTypes);

3626 }

3627 continue;

3628 }

3629 List.push_back(T);

3630 }

3631}

3632

3634

3636 return false;

3637

3638

3640 return false;

3641

3643 return false;

3644

3645

3647 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)

3648 return false;

3649 return true;

3650 }

3651

3653 int ArraySize = VT->getNumElements();

3654

3655 if (ArraySize > 4)

3656 return false;

3657

3658 QualType ElTy = VT->getElementType();

3660 return false;

3661

3662 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)

3663 return false;

3664 return true;

3665 }

3666

3667 return false;

3668}

3669

3672 return false;

3673

3676

3677

3678 if (SemaRef.getASTContext().hasSameType(T1, T2))

3679 return true;

3680

3685

3686

3687 return llvm::equal(T1Types, T2Types,

3689 return SemaRef.IsLayoutCompatible(LHS, RHS);

3690 });

3691}

3692

3696 return true;

3697

3698 bool HadError = false;

3699

3700 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {

3703

3704

3705

3706

3707

3708 const auto *NDAttr = NewParam->getAttr();

3709 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);

3710 const auto *ODAttr = OldParam->getAttr();

3711 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);

3712

3713 if (NSpellingIdx != OSpellingIdx) {

3715 diag::err_hlsl_param_qualifier_mismatch)

3716 << NDAttr << NewParam;

3717 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)

3718 << ODAttr;

3719 HadError = true;

3720 }

3721 }

3722 return HadError;

3723}

3724

3725

3726

3728

3730 return false;

3731

3732 if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))

3733 return true;

3734

3736 case Type::STK_Bool:

3742 return true;

3747 llvm_unreachable("HLSL doesn't support pointers.");

3750 llvm_unreachable("HLSL doesn't support complex types.");

3752 llvm_unreachable("HLSL doesn't support fixed point types.");

3753 }

3754 llvm_unreachable("Should have returned before this");

3755

3761 return true;

3764 llvm_unreachable("HLSL doesn't support complex types.");

3766 llvm_unreachable("HLSL doesn't support fixed point types.");

3771 llvm_unreachable("HLSL doesn't support pointers.");

3772 }

3773 llvm_unreachable("Should have returned before this");

3774

3779 llvm_unreachable("HLSL doesn't support pointers.");

3780

3782 llvm_unreachable("HLSL doesn't support fixed point types.");

3783

3786 llvm_unreachable("HLSL doesn't support complex types.");

3787 }

3788

3789 llvm_unreachable("Unhandled scalar cast");

3790}

3791

3792

3793

3794

3796

3798

3799

3802 return false;

3803

3805

3806

3808 return false;

3809

3810 if (SrcVecTy)

3812

3815

3816 for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {

3817 if (DestTypes[I]->isUnionType())

3818 return false;

3820 return false;

3821 }

3822 return true;

3823}

3824

3825

3827

3828

3829

3831 if (SrcTy->isScalarType())

3832 return false;

3833

3836 return false;

3837

3840 return false;

3841

3846

3847

3848

3849 if (SrcTypes.size() < DestTypes.size())

3850 return false;

3851

3852 unsigned SrcSize = SrcTypes.size();

3853 unsigned DstSize = DestTypes.size();

3854 unsigned I;

3855 for (I = 0; I < DstSize && I < SrcSize; I++) {

3856 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())

3857 return false;

3859 return false;

3860 }

3861 }

3862

3863

3864 for (; I < SrcSize; I++) {

3865 if (SrcTypes[I]->isUnionType())

3866 return false;

3867 }

3868 return true;

3869}

3870

3872 assert(Param->hasAttr() &&

3873 "We should not get here without a parameter modifier expression");

3874 const auto *Attr = Param->getAttr();

3877

3881 << Arg << (IsInOut ? 1 : 0);

3883 }

3884

3886

3887 QualType Ty = Param->getType().getNonLValueExprType(Ctx);

3888

3889

3890

3891

3893 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)

3894 << Arg << (IsInOut ? 1 : 0);

3896 }

3897

3900

3901

3902

3906 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);

3910

3912 auto *OpV = new (Ctx)

3914

3915

3916

3917 Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Param->getBeginLoc(),

3918 tok::equal, ArgOpV, OpV);

3919

3922 Expr *Writeback = Res.get();

3923 auto *OutExpr =

3925

3927}

3928

3930

3931

3932

3934 "Pointer and reference types cannot be inout or out parameters");

3935 Ty = SemaRef.getASTContext().getLValueReferenceType(Ty);

3937 return Ty;

3938}

3939

3945 !VD->hasAttr() &&

3947}

3948

3950

3951 if (Decl->getType().hasAddressSpace())

3952 return;

3953

3954 if (Decl->getType()->isDependentType())

3955 return;

3956

3958

3959 if (Decl->hasAttr()) {

3961 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);

3963 return;

3964 }

3965

3967 return;

3968

3969

3971 return;

3972

3973

3974

3975 if (Decl->getStorageClass() != SC_Static && Decl->isStaticDataMember())

3976 return;

3977

3979 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);

3981}

3982

3985

3986 if (SemaRef.RequireCompleteType(

3988 SemaRef.getASTContext().getBaseElementType(VD->getType()),

3989 diag::err_typecheck_decl_incomplete_type)) {

3992 return;

3993 }

3994

3995

3996

3997

3999

4003 DefaultCBufferDecls.push_back(VD);

4004 }

4005

4006

4008 collectResourceBindingsOnVarDecl(VD);

4009

4010 if (VD->hasAttr())

4012

4015

4016

4017

4019 }

4020

4021

4022 processExplicitBindingsOnDecl(VD);

4023

4024

4027

4028

4029

4032 uint32_t OrderID = getNextImplicitBindingOrderID();

4035 else {

4038 OrderID);

4039

4041 }

4042 }

4043

4044

4046

4050 uint32_t OrderID = getNextImplicitBindingOrderID();

4052 }

4053 }

4054 }

4055 }

4056

4058}

4059

4060bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {

4062 "expected resource record type");

4063

4067

4068

4070

4071

4076

4078 const char *CreateMethodName;

4079 if (Binding.isExplicit())

4080 CreateMethodName = HasCounter ? "__createFromBindingWithImplicitCounter"

4081 : "__createFromBinding";

4082 else

4083 CreateMethodName = HasCounter

4084 ? "__createFromImplicitBindingWithImplicitCounter"

4085 : "__createFromImplicitBinding";

4086

4087 CreateMethod =

4088 lookupMethod(SemaRef, ResourceDecl, CreateMethodName, VD->getLocation());

4089

4090 if (!CreateMethod)

4091

4092

4093

4094 return false;

4095

4096 if (Binding.isExplicit()) {

4100 Args.push_back(RegSlot);

4101 } else {

4102 uint32_t OrderID = (Binding.hasImplicitOrderID())

4103 ? Binding.getImplicitOrderID()

4104 : getNextImplicitBindingOrderID();

4108 Args.push_back(OrderId);

4109 }

4110

4111 IntegerLiteral *Space =

4114 Args.push_back(Space);

4115

4117 AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());

4118 Args.push_back(RangeSize);

4119

4121 AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());

4122 Args.push_back(Index);

4123

4124 StringRef VarName = VD->getName();

4128 SourceLocation());

4131 Name, nullptr, VK_PRValue, FPOptionsOverride());

4132 Args.push_back(NameCast);

4133

4134 if (HasCounter) {

4135

4136 uint32_t CounterOrderID = getNextImplicitBindingOrderID();

4137 IntegerLiteral *CounterId =

4140 Args.push_back(CounterId);

4141 }

4142

4143

4145 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,

4146 true);

4147

4148

4149

4151 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,

4153

4156 CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());

4157

4158 CallExpr *InitExpr =

4160 SourceLocation(), FPOptionsOverride());

4163 SemaRef.CheckCompleteVariableDeclaration(VD);

4164 return true;

4165}

4166

4167bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {

4169 "expected array of resource records");

4170

4171

4172

4173

4174

4175

4176

4177

4178

4179

4180 ASTContext &AST = SemaRef.getASTContext();

4183 CXXMethodDecl *CreateMethod = nullptr;

4184

4186 ResourceBindingAttrs ResourceAttrs(VD);

4187 if (ResourceAttrs.isExplicit())

4188

4189 CreateMethod =

4190 lookupMethod(SemaRef, ResourceDecl,

4191 HasCounter ? "__createFromBindingWithImplicitCounter"

4192 : "__createFromBinding",

4194 else

4195

4196 CreateMethod = lookupMethod(

4198 HasCounter ? "__createFromImplicitBindingWithImplicitCounter"

4199 : "__createFromImplicitBinding",

4201

4202 if (!CreateMethod)

4203 return false;

4204

4205

4207 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,

4208 true);

4209 return true;

4210}

4211

4212

4213

4215

4216

4218 return true;

4219

4220

4224 return initGlobalResourceDecl(VD);

4226 return initGlobalResourceArrayDecl(VD);

4227 }

4228 return false;

4229}

4230

4231

4236 "expected LHS to be a resource record or array of resource records");

4237 if (Opc != BO_Assign)

4238 return true;

4239

4240

4241 Expr *E = LHSExpr;

4242 while (auto *ASE = dyn_cast(E))

4244

4245

4247 if (VarDecl *VD = dyn_cast(DRE->getDecl())) {

4249

4250 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;

4251 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;

4252 return false;

4253 }

4254 }

4255 }

4256 return true;

4257}

4258

4259

4260

4261void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {

4263 "expected global variable that contains HLSL resource");

4264

4265

4266 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast(VD)) {

4267 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()

4268 ? ResourceClass::CBuffer

4269 : ResourceClass::SRV);

4270 return;

4271 }

4272

4273

4274

4279 }

4280

4281

4282 if (const HLSLAttributedResourceType *AttrResType =

4283 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {

4284 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);

4285 return;

4286 }

4287

4288

4289 if (const RecordType *RT = dyn_cast(Ty))

4290 collectResourceBindingsOnUserRecordDecl(VD, RT);

4291}

4292

4293

4294

4295

4296void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {

4297 assert(VD->hasGlobalStorage() && "expected global variable");

4298

4299 bool HasBinding = false;

4300 for (Attr *A : VD->attrs()) {

4302 HasBinding = true;

4303

4304 HLSLResourceBindingAttr *RBA = dyn_cast(A);

4305 if (!RBA || !RBA->hasRegisterSlot())

4306 continue;

4307 HasBinding = true;

4308

4310 assert(RT != RegisterType::I && "invalid or obsolete register type should "

4311 "never have an attribute created");

4312

4313 if (RT == RegisterType::C) {

4314 if (Bindings.hasBindingInfoForDecl(VD))

4316 diag::warn_hlsl_user_defined_type_missing_member)

4317 << static_cast<int>(RT);

4318 continue;

4319 }

4320

4321

4322

4323

4325 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {

4326

4328 } else {

4330 diag::warn_hlsl_user_defined_type_missing_member)

4331 << static_cast<int>(RT);

4332 }

4333 }

4334

4337}

4338namespace {

4339class InitListTransformer {

4340 Sema &S;

4341 ASTContext &Ctx;

4342 QualType InitTy;

4343 QualType *DstIt = nullptr;

4344 Expr **ArgIt = nullptr;

4345

4346

4347

4348 bool Wrap;

4349

4350 bool castInitializer(Expr *E) {

4351 assert(DstIt && "This should always be something!");

4352 if (DstIt == DestTypes.end()) {

4353 if (!Wrap) {

4354 ArgExprs.push_back(E);

4355

4356

4357 return true;

4358 }

4359 DstIt = DestTypes.begin();

4360 }

4362 Ctx, *DstIt, false);

4365 return false;

4367 ArgExprs.push_back(Init);

4368 DstIt++;

4369 return true;

4370 }

4371

4372 bool buildInitializerListImpl(Expr *E) {

4373

4374 if (auto *Init = dyn_cast(E)) {

4375 for (auto *SubInit : Init->inits())

4376 if (!buildInitializerListImpl(SubInit))

4377 return false;

4378 return true;

4379 }

4380

4381

4382 QualType Ty = E->getType();

4383

4385 return castInitializer(E);

4386

4387 if (auto *VecTy = Ty->getAs()) {

4389

4392 for (uint64_t I = 0; I < Size; ++I) {

4394 SizeTy, SourceLocation());

4395

4399 return false;

4400 if (!castInitializer(ElExpr.get()))

4401 return false;

4402 }

4403 return true;

4404 }

4405 if (auto *MTy = Ty->getAs()) {

4406 unsigned Rows = MTy->getNumRows();

4407 unsigned Cols = MTy->getNumColumns();

4408 QualType ElemTy = MTy->getElementType();

4409

4410 for (unsigned C = 0; C < Cols; ++C) {

4411 for (unsigned R = 0; R < Rows; ++R) {

4412

4416

4421 E, RowIdx, ColIdx, E->getEndLoc());

4423 return false;

4424 if (!castInitializer(ElExpr.get()))

4425 return false;

4427 }

4428 }

4429 return true;

4430 }

4431

4432 if (auto *ArrTy = dyn_cast(Ty.getTypePtr())) {

4436 for (uint64_t I = 0; I < Size; ++I) {

4438 SizeTy, SourceLocation());

4442 return false;

4443 if (!buildInitializerListImpl(ElExpr.get()))

4444 return false;

4445 }

4446 return true;

4447 }

4448

4450 llvm::SmallVector<CXXRecordDecl *> RecordDecls;

4451 RecordDecls.push_back(RD);

4452 while (RecordDecls.back()->getNumBases()) {

4453 CXXRecordDecl *D = RecordDecls.back();

4455 "HLSL doesn't support multiple inheritance");

4456 RecordDecls.push_back(

4458 }

4459 while (!RecordDecls.empty()) {

4460 CXXRecordDecl *RD = RecordDecls.pop_back_val();

4461 for (auto *FD : RD->fields()) {

4462 if (FD->isUnnamedBitField())

4463 continue;

4467 E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);

4469 return false;

4470 if (!buildInitializerListImpl(Res.get()))

4471 return false;

4472 }

4473 }

4474 }

4475 return true;

4476 }

4477

4478 Expr *generateInitListsImpl(QualType Ty) {

4479 assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");

4481 return *(ArgIt++);

4482

4483 llvm::SmallVector<Expr *> Inits;

4487 QualType ElTy;

4489 if (auto *ATy = Ty->getAs()) {

4490 ElTy = ATy->getElementType();

4491 Size = ATy->getNumElements();

4492 } else if (auto *CMTy = Ty->getAs()) {

4493 ElTy = CMTy->getElementType();

4494 Size = CMTy->getNumElementsFlattened();

4495 } else {

4497 ElTy = VTy->getElementType();

4498 Size = VTy->getZExtSize();

4499 }

4500 for (uint64_t I = 0; I < Size; ++I)

4501 Inits.push_back(generateInitListsImpl(ElTy));

4502 }

4504 llvm::SmallVector<CXXRecordDecl *> RecordDecls;

4505 RecordDecls.push_back(RD);

4506 while (RecordDecls.back()->getNumBases()) {

4507 CXXRecordDecl *D = RecordDecls.back();

4509 "HLSL doesn't support multiple inheritance");

4510 RecordDecls.push_back(

4512 }

4513 while (!RecordDecls.empty()) {

4514 CXXRecordDecl *RD = RecordDecls.pop_back_val();

4515 for (auto *FD : RD->fields())

4516 if (!FD->isUnnamedBitField())

4517 Inits.push_back(generateInitListsImpl(FD->getType()));

4518 }

4519 }

4520 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),

4521 Inits, Inits.back()->getEndLoc());

4522 NewInit->setType(Ty);

4523 return NewInit;

4524 }

4525

4526public:

4527 llvm::SmallVector<QualType, 16> DestTypes;

4528 llvm::SmallVector<Expr *, 16> ArgExprs;

4529 InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)

4530 : S(SemaRef), Ctx(SemaRef.getASTContext()),

4531 Wrap(Entity.getType()->isIncompleteArrayType()) {

4532 InitTy = Entity.getType().getNonReferenceType();

4533

4534

4535

4536 if (Wrap) {

4540 }

4542 DstIt = DestTypes.begin();

4543 }

4544

4545 bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }

4546

4547 Expr *generateInitLists() {

4548 assert(!ArgExprs.empty() &&

4549 "Call buildInitializerList to generate argument expressions.");

4550 ArgIt = ArgExprs.begin();

4551 if (!Wrap)

4552 return generateInitListsImpl(InitTy);

4553 llvm::SmallVector<Expr *> Inits;

4554 while (ArgIt != ArgExprs.end())

4555 Inits.push_back(generateInitListsImpl(InitTy));

4556

4557 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),

4558 Inits, Inits.back()->getEndLoc());

4559 llvm::APInt ArySize(64, Inits.size());

4561 ArraySizeModifier::Normal, 0));

4562 return NewInit;

4563 }

4564};

4565}

4566

4569

4570 if (Init->getType()->isScalarType())

4571 return true;

4573 InitListTransformer ILT(SemaRef, Entity);

4574

4575 for (unsigned I = 0; I < Init->getNumInits(); ++I) {

4583 Init->setInit(I, E);

4584 }

4585 if (!ILT.buildInitializerList(E))

4586 return false;

4587 }

4588 size_t ExpectedSize = ILT.DestTypes.size();

4589 size_t ActualSize = ILT.ArgExprs.size();

4590 if (ExpectedSize == 0 && ActualSize == 0)

4591 return true;

4592

4593

4594

4595

4596

4598 ExpectedSize =

4599 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;

4600

4601

4602

4603

4606 InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);

4607 if (ExpectedSize != ActualSize) {

4608 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;

4609 SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)

4610 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;

4611 return false;

4612 }

4613

4614

4615

4617 Init->resizeInits(Ctx, NewInit->getNumInits());

4618 for (unsigned I = 0; I < NewInit->getNumInits(); ++I)

4619 Init->updateInit(Ctx, I, NewInit->getInit(I));

4620 return true;

4621}

4622

4624 const HLSLVkConstantIdAttr *ConstIdAttr =

4625 VDecl->getAttr();

4626 if (!ConstIdAttr)

4627 return true;

4628

4630

4632 if (Init->isCXX11ConstantExpr(Context, &InitValue)) {

4633 Diag(VDecl->getLocation(), diag::err_specialization_const);

4635 return false;

4636 }

4637

4640

4641

4642 int ConstantID = ConstIdAttr->getId();

4643 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);

4645 ConstIdAttr->getLocation());

4646

4648 Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);

4649 if (C->getType()->getCanonicalTypeUnqualified() !=

4653 Context.getTrivialTypeSourceInfo(

4654 Init->getType(), Init->getExprLoc()),

4656 .get();

4657 }

4659 return true;

4660}

Defines the clang::ASTContext interface.

Defines enum values for all the target-independent builtin functions.

llvm::dxil::ResourceClass ResourceClass

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

TokenType getType() const

Returns the token's type, e.g.

FormatToken * Previous

The previous token in the unwrapped line.

Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings

static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)

Definition SemaHLSL.cpp:2857

static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)

Definition SemaHLSL.cpp:3569

static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)

Definition SemaHLSL.cpp:2942

static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)

Definition SemaHLSL.cpp:1120

static bool convertToRegisterType(StringRef Slot, RegisterType *RT)

Definition SemaHLSL.cpp:83

static bool CheckWaveActive(Sema *S, CallExpr *TheCall)

Definition SemaHLSL.cpp:3012

static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)

Definition SemaHLSL.cpp:1083

static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)

Definition SemaHLSL.cpp:3029

static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)

Definition SemaHLSL.cpp:220

static bool isZeroSizedArray(const ConstantArrayType *CAT)

Definition SemaHLSL.cpp:339

static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)

Definition SemaHLSL.cpp:2340

static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)

Definition SemaHLSL.cpp:458

static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)

Definition SemaHLSL.cpp:2929

static bool isInvalidConstantBufferLeafElementType(const Type *Ty)

Definition SemaHLSL.cpp:365

static Builtin::ID getSpecConstBuiltinId(const Type *Type)

Definition SemaHLSL.cpp:133

static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)

Definition SemaHLSL.cpp:2918

static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)

Definition SemaHLSL.cpp:2996

static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)

Definition SemaHLSL.cpp:421

static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)

Definition SemaHLSL.cpp:586

static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)

Definition SemaHLSL.cpp:2969

static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)

Definition SemaHLSL.cpp:346

static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)

Definition SemaHLSL.cpp:239

static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)

Definition SemaHLSL.cpp:352

static RegisterType getRegisterType(ResourceClass RC)

Definition SemaHLSL.cpp:63

static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)

Definition SemaHLSL.cpp:774

static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)

Definition SemaHLSL.cpp:2894

static QualType castElement(Sema &S, ExprResult &E, QualType Ty)

Definition SemaHLSL.cpp:1091

static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)

Definition SemaHLSL.cpp:404

static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)

Definition SemaHLSL.cpp:2952

static bool hasCounterHandle(const CXXRecordDecl *RD)

Definition SemaHLSL.cpp:1418

static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)

Definition SemaHLSL.cpp:3045

static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)

Definition SemaHLSL.cpp:1096

static ResourceClass getResourceClass(RegisterType RT)

Definition SemaHLSL.cpp:115

static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)

Definition SemaHLSL.cpp:490

static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)

Definition SemaHLSL.cpp:2979

void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)

Definition SemaHLSL.cpp:555

static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)

Definition SemaHLSL.cpp:384

static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)

Definition SemaHLSL.cpp:3093

static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)

Definition SemaHLSL.cpp:286

HLSLResourceBindingAttr::RegisterType RegisterType

Definition SemaHLSL.cpp:58

static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)

Definition SemaHLSL.cpp:1173

static bool isValidWaveSizeValue(unsigned Value)

Definition SemaHLSL.cpp:1695

static bool IsDefaultBufferConstantDecl(VarDecl *VD)

Definition SemaHLSL.cpp:3940

static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)

Definition SemaHLSL.cpp:2905

static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)

Definition SemaHLSL.cpp:2315

static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)

Definition SemaHLSL.cpp:2239

This file declares semantic analysis for HLSL constructs.

Defines the clang::SourceLocation class and associated facilities.

Defines various enumerations that describe declaration and type specifiers.

C Language Family Type Representation.

Defines the clang::TypeLoc interface and its subclasses.

C Language Family Type Representation.

static const TypeInfo & getInfo(unsigned id)

return(__x > > __y)|(__x<<(32 - __y))

APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

unsigned getIntWidth(QualType T) const

int getIntegerTypeOrder(QualType LHS, QualType RHS) const

Return the highest ranked integer type, see C99 6.3.1.8p1.

QualType getPointerType(QualType T) const

Return the uniqued reference to the type for a pointer to the specified type.

const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const

QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const

Return the unique reference to the type for a constant array of the specified element type.

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

int getFloatingTypeOrder(QualType LHS, QualType RHS) const

Compare the rank of the two specified floating point types, ignoring the domain of the type (i....

TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const

Allocate a TypeSourceInfo where all locations have been initialized to a given location,...

QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const

Return a type for a constant array for a string literal of the specified element type and length.

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

CanQualType UnsignedIntTy

QualType getSizeType() const

Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.

QualType getExtVectorType(QualType VectorType, unsigned NumElts) const

Return the unique reference to an extended vector type of the specified element type and size.

const TargetInfo & getTargetInfo() const

QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)

QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const

Return the uniqued reference to the type for an address space qualified type with the specified type ...

CanQualType getCanonicalTagType(const TagDecl *TD) const

static bool hasSameUnqualifiedType(QualType T1, QualType T2)

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

unsigned getTypeAlign(QualType T) const

Return the ABI-specified alignment of a (complete) type T, in bits.

Represents an array type, per C99 6.7.5.2 - Array Declarators.

QualType getElementType() const

Attr - This represents one attribute.

attr::Kind getKind() const

SourceLocation getLocation() const

SourceLocation getScopeLoc() const

SourceRange getRange() const

const IdentifierInfo * getScopeName() const

SourceLocation getLoc() const

const IdentifierInfo * getAttrName() const

Represents a base class of a C++ class.

QualType getType() const

Retrieves the type of the base class.

Represents a static or instance method of a struct/union/class.

Represents a C++ struct/union/class.

bool isHLSLIntangible() const

Returns true if the class contains HLSL intangible type, either as a field or in base class.

static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)

void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)

Sets the base classes of this struct or class.

void completeDefinition() override

Indicates that the definition of this class is now complete.

unsigned getNumBases() const

Retrieves the number of base classes of this class.

base_class_iterator bases_begin()

bool isEmpty() const

Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

SourceLocation getBeginLoc() const

static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)

Create a call expression.

FunctionDecl * getDirectCallee()

If the callee is a FunctionDecl, return it. Otherwise return null.

unsigned getNumArgs() const

getNumArgs - Return the number of actual arguments to this call.

QualType withConst() const

Retrieves a version of this type with const applied.

const T * getTypePtr() const

Retrieve the underlying type pointer, which refers to a canonical type.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

Represents the canonical version of C arrays with a specified constant size.

bool isZeroSize() const

Return true if the size is zero.

uint64_t getZExtSize() const

Return the size zero-extended as a uint64_t.

static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

lookup_result lookup(DeclarationName Name) const

lookup - Find the declarations (if any) with the given Name in this context.

bool isTranslationUnit() const

void addDecl(Decl *D)

Add the declaration D into this context.

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

DeclContext * getNonTransparentContext()

A reference to a declared variable, function, enum, etc.

static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)

Decl - This represents one declaration (or definition), e.g.

attr_iterator attr_end() const

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

void setInvalidDecl(bool Invalid=true)

setInvalidDecl - Indicates the Decl had a semantic error.

bool isInExportDeclContext() const

Whether this declaration was exported in a lexical context.

attr_iterator attr_begin() const

SourceLocation getLocation() const

void setImplicit(bool I=true)

DeclContext * getDeclContext()

AccessSpecifier getAccess() const

SourceLocation getBeginLoc() const LLVM_READONLY

The name of a declaration.

Represents a ValueDecl that came out of a declarator.

SourceLocation getBeginLoc() const LLVM_READONLY

This represents one expression.

ExprValueKind getValueKind() const

getValueKind - The value kind that this expression produces.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const

isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.

bool isLValue() const

isLValue - True if this expression is an "l-value" according to the rules of the current language.

ExprObjectKind getObjectKind() const

getObjectKind - The object kind that this expression produces.

bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const

HasSideEffects - This routine returns true for all those expressions which have any effect other than...

void setValueKind(ExprValueKind Cat)

setValueKind - Set the value kind produced by this expression.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

Represents a member of a struct/union/class.

static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)

static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)

Create a code modification hint that replaces the given source range with the given code string.

Represents a function declaration or definition.

const ParmVarDecl * getParamDecl(unsigned i) const

Stmt * getBody(const FunctionDecl *&Definition) const

Retrieve the body (definition) of the function.

bool isThisDeclarationADefinition() const

Returns whether this specific declaration of the function is also a definition that does not contain ...

QualType getReturnType() const

ArrayRef< ParmVarDecl * > parameters() const

bool isTemplateInstantiation() const

Determines if the given function was instantiated from a function template.

redecl_range redecls() const

Returns an iterator range for all the redeclarations of the same decl.

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

DeclarationNameInfo getNameInfo() const

bool hasBody(const FunctionDecl *&Definition) const

Returns true if the function has a body.

bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const

Returns true if the function has a definition that does not need to be instantiated.

HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.

static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)

void addLayoutStruct(CXXRecordDecl *LS)

void setHasValidPackoffset(bool PO)

static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)

buffer_decl_range buffer_decls() const

static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)

static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

A simple pair of identifier info and location.

SourceLocation getLoc() const

IdentifierInfo * getIdentifierInfo() const

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)

Describes an C or C++ initializer list.

Describes an entity that is being initialized.

QualType getType() const

Retrieve type being initialized.

static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)

Create the initialization entity for a parameter.

static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)

Returns a new integer literal with value 'V' and type 'type'.

Represents the results of name lookup.

NamedDecl * getFoundDecl() const

Fetch the unique decl found by this lookup.

Represents a prvalue temporary that is written into memory so that a reference can bind to it.

ValueDecl * getMemberDecl() const

Retrieve the member declaration to which this expression refers.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.

Represents a parameter to a function.

ParsedAttr - Represents a syntactic attribute.

unsigned getSemanticSpelling() const

If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...

unsigned getMinArgs() const

bool checkExactlyNumArgs(class Sema &S, unsigned Num) const

Check if the attribute has exactly as many args as Num.

IdentifierLoc * getArgAsIdent(unsigned Arg) const

bool hasParsedType() const

const ParsedType & getTypeArg() const

unsigned getNumArgs() const

getNumArgs - Return the number of actual arguments to this attribute.

bool isArgIdent(unsigned Arg) const

Expr * getArgAsExpr(unsigned Arg) const

AttributeCommonInfo::Kind getKind() const

A (possibly-)qualified type.

void addRestrict()

Add the restrict qualifier to this QualType.

QualType getNonLValueExprType(const ASTContext &Context) const

Determine the type of a (typically non-lvalue) expression with the specified result type.

QualType getDesugaredType(const ASTContext &Context) const

Return the specified type with any "sugar" removed from the type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

LangAS getAddressSpace() const

Return the address space of this type.

QualType getNonReferenceType() const

If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...

QualType getCanonicalType() const

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

bool hasAddressSpace() const

Check if this type has any address space qualifier.

Represents a struct/union/class.

field_iterator field_end() const

field_range fields() const

field_iterator field_begin() const

bool hasBindingInfoForDecl(const VarDecl *VD) const

Definition SemaHLSL.cpp:194

DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)

Definition SemaHLSL.cpp:180

DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)

Definition SemaHLSL.cpp:167

Scope - A scope is a transient data structure that is used while parsing the program.

ASTContext & getASTContext() const

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)

Definition SemaHLSL.cpp:3871

HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const

Definition SemaHLSL.cpp:1303

bool CanPerformElementwiseCast(Expr *Src, QualType DestType)

Definition SemaHLSL.cpp:3826

void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1699

void handleVkLocationAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1793

HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)

Definition SemaHLSL.cpp:2184

void handleSemanticAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1905

bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)

Definition SemaHLSL.cpp:3727

QualType ProcessResourceTypeAttributes(QualType Wrapped)

Definition SemaHLSL.cpp:2161

void handleShaderAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1968

void CheckEntryPoint(FunctionDecl *FD)

Definition SemaHLSL.cpp:891

void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)

Definition SemaHLSL.cpp:1252

T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)

void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)

Definition SemaHLSL.cpp:2799

HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)

Definition SemaHLSL.cpp:657

HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)

Definition SemaHLSL.cpp:623

void deduceAddressSpace(VarDecl *Decl)

Definition SemaHLSL.cpp:3949

std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)

Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...

Definition SemaHLSL.cpp:1271

void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1919

bool diagnosePositionType(QualType T, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1815

bool handleInitialization(VarDecl *VDecl, Expr *&Init)

Definition SemaHLSL.cpp:4623

bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1802

void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:2449

bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)

Definition SemaHLSL.cpp:4232

bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)

Definition SemaHLSL.cpp:3795

bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const

Definition SemaHLSL.cpp:3670

void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)

Definition SemaHLSL.cpp:1826

void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1615

bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)

Definition SemaHLSL.cpp:3693

QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)

Definition SemaHLSL.cpp:1185

void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:2357

bool IsTypedResourceElementCompatible(QualType T1)

Definition SemaHLSL.cpp:3633

bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)

Definition SemaHLSL.cpp:4567

void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1641

bool ActOnUninitializedVarDecl(VarDecl *D)

Definition SemaHLSL.cpp:4214

void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1763

void ActOnTopLevelFunction(FunctionDecl *FD)

Definition SemaHLSL.cpp:726

bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)

Definition SemaHLSL.cpp:2079

HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)

Definition SemaHLSL.cpp:693

void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)

Definition SemaHLSL.cpp:596

void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1780

HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)

Definition SemaHLSL.cpp:706

QualType getInoutParameterType(QualType Ty)

Definition SemaHLSL.cpp:3929

SemaHLSL(Sema &S)

Definition SemaHLSL.cpp:198

void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)

Definition SemaHLSL.cpp:1771

Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)

Definition SemaHLSL.cpp:200

HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)

Definition SemaHLSL.cpp:637

bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)

Definition SemaHLSL.cpp:1432

void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)

Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...

Definition SemaHLSL.cpp:1283

void ActOnVariableDeclarator(VarDecl *VD)

Definition SemaHLSL.cpp:3983

bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)

Definition SemaHLSL.cpp:3118

Sema - This implements semantic analysis and AST building for C.

@ LookupOrdinaryName

Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....

@ LookupMemberName

Member name lookup, which finds the names of class/struct/union members.

ASTContext & getASTContext() const

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.

const LangOptions & getLangOpts() const

ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)

ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)

bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)

Perform qualified name lookup into a given context.

ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)

ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)

Encodes a location in the source.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getEndLoc() const LLVM_READONLY

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...

SourceLocation getBeginLoc() const LLVM_READONLY

static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)

This is the "fully general" constructor that allows representation of strings formed from one or more...

void startDefinition()

Starts the definition of this tag declaration.

Exposes information about the current target.

TargetOptions & getTargetOpts() const

Retrieve the target options.

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

StringRef getPlatformName() const

Retrieve the name of the platform as it is used in the availability attribute.

VersionTuple getPlatformMinVersion() const

Retrieve the minimum desired version of the platform, to which the program should be compiled.

std::string HLSLEntry

The entry point name for HLSL shader being compiled as specified by -E.

The top declaration context.

SourceLocation getBeginLoc() const

Get the begin source location.

A container of type source information.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

The base class of the type hierarchy.

bool isBooleanType() const

bool isIncompleteArrayType() const

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isConstantArrayType() const

bool hasIntegerRepresentation() const

Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...

CXXRecordDecl * castAsCXXRecordDecl() const

bool isArithmeticType() const

bool isConstantMatrixType() const

bool isHLSLBuiltinIntangibleType() const

CanQualType getCanonicalTypeUnqualified() const

bool isIntegerType() const

isIntegerType() does not include complex integers (a GCC extension).

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isHLSLIntangibleType() const

bool isEnumeralType() const

bool isScalarType() const

bool isIntegralType(const ASTContext &Ctx) const

Determine whether this type is an integral type.

const Type * getArrayElementTypeNoTypeQual() const

If this is an array type, return the element type of the array, potentially with type qualifiers miss...

bool hasUnsignedIntegerRepresentation() const

Determine whether this type has an unsigned integer representation of some sort, e....

bool isAggregateType() const

Determines whether the type is a C++ aggregate type or C aggregate or union type.

ScalarTypeKind getScalarTypeKind() const

Given that this is a scalar type, classify it.

bool hasSignedIntegerRepresentation() const

Determine whether this type has an signed integer representation of some sort, e.g....

bool isHLSLResourceRecord() const

bool hasFloatingRepresentation() const

Determine whether this type has a floating-point representation of some sort, e.g....

bool isVectorType() const

bool isRealFloatingType() const

Floating point categories.

bool isHLSLAttributedResourceType() const

bool isFloatingType() const

const T * getAs() const

Member-template getAs'.

const Type * getUnqualifiedDesugaredType() const

Return the specified type with any "sugar" removed from the type, removing any typedefs,...

bool isRecordType() const

bool isHLSLResourceRecordArray() const

void setType(QualType newType)

Represents a variable declaration or definition.

void setInitStyle(InitializationStyle Style)

@ CallInit

Call-style initialization (C++98)

void setStorageClass(StorageClass SC)

bool hasGlobalStorage() const

Returns true for all variables that do not have local storage.

StorageClass getStorageClass() const

Returns the storage class as written in the source.

Represents a GCC generic vector type.

unsigned getNumElements() const

QualType getElementType() const

Defines the clang::TargetInfo interface.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)

@ ICIS_NoInit

No in-class initializer.

@ OK_Ordinary

An ordinary object is located at an address in memory.

static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)

@ AANT_ArgumentIdentifier

@ Result

The result type of a method or function.

@ Ordinary

This parameter uses ordinary ABI rules for its type.

const FunctionProtoType * T

llvm::Expected< QualType > ExpectedType

static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)

@ Type

The name was classified as a type.

LangAS

Defines the address space values used by the address space qualifier of QualType.

bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)

Definition SemaHLSL.cpp:1988

CastKind

CastKind - The kind of operation required for a conversion.

@ VK_PRValue

A pr-value expression (in the C++11 taxonomy) produces a temporary value.

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor

U cast(CodeGen::Address addr)

ActionResult< Expr * > ExprResult

Visibility

Describes the different kinds of visibility that a declaration may have.

hash_code hash_value(const clang::dependencies::ModuleID &ID)

__DEVICE__ bool isnan(float __x)

__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)

TypeSourceInfo * ContainedTyInfo

Describes how types, statements, expressions, and declarations should be printed.

void setCounterImplicitOrderID(unsigned Value) const

bool hasCounterImplicitOrderID() const

void setImplicitOrderID(unsigned Value) const

const SourceLocation & getLocation() const

const llvm::hlsl::rootsig::RootElement & getElement() const