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

1

2

3

4

5

6

7

8

9

10

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

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

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

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

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

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

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

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

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

39#include

40#include

41

42using namespace clang;

43using RegisterType = HLSLResourceBindingAttr::RegisterType;

44

46 switch (RC) {

47 case ResourceClass::SRV:

48 return RegisterType::SRV;

49 case ResourceClass::UAV:

50 return RegisterType::UAV;

51 case ResourceClass::CBuffer:

52 return RegisterType::CBuffer;

53 case ResourceClass::Sampler:

54 return RegisterType::Sampler;

55 }

56 llvm_unreachable("unexpected ResourceClass value");

57}

58

59

60

62 assert(RT != nullptr);

63 switch (Slot[0]) {

64 case 't':

65 case 'T':

66 *RT = RegisterType::SRV;

67 return true;

68 case 'u':

69 case 'U':

70 *RT = RegisterType::UAV;

71 return true;

72 case 'b':

73 case 'B':

74 *RT = RegisterType::CBuffer;

75 return true;

76 case 's':

77 case 'S':

78 *RT = RegisterType::Sampler;

79 return true;

80 case 'c':

81 case 'C':

82 *RT = RegisterType::C;

83 return true;

84 case 'i':

85 case 'I':

86 *RT = RegisterType::I;

87 return true;

88 default:

89 return false;

90 }

91}

92

94 switch (RT) {

95 case RegisterType::SRV:

96 return ResourceClass::SRV;

97 case RegisterType::UAV:

98 return ResourceClass::UAV;

99 case RegisterType::CBuffer:

100 return ResourceClass::CBuffer;

101 case RegisterType::Sampler:

102 return ResourceClass::Sampler;

103 case RegisterType::C:

104 case RegisterType::I:

105

106 break;

107 }

108 llvm_unreachable("unexpected RegisterType value");

109}

110

112 ResourceClass ResClass) {

114 "DeclBindingInfo already added");

116

117

118

119

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

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

122}

123

125 ResourceClass ResClass) {

126 auto Entry = DeclToBindingListIndex.find(VD);

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

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

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

130 ++Index) {

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

132 return &BindingsList[Index];

133 }

134 }

135 return nullptr;

136}

137

139 return DeclToBindingListIndex.contains(VD);

140}

141

143

148

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

152

153

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

155 : llvm::hlsl::ResourceClass::SRV;

156 auto RK = CBuffer ? llvm::hlsl::ResourceKind::CBuffer

157 : llvm::hlsl::ResourceKind::TBuffer;

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

160

163

165}

166

167

168

171 unsigned Size = 0;

172 constexpr unsigned CBufferAlign = 16;

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

176 QualType Ty = Field->getType();

178

179

180 unsigned FieldAlign = 4;

182 FieldAlign = CBufferAlign;

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

184 Size += FieldSize;

185 }

187 if (unsigned ElementCount = AT->getSize().getZExtValue()) {

188 unsigned ElementSize =

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

191 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;

192 }

194 unsigned ElementCount = VT->getNumElements();

195 unsigned ElementSize =

197 Size = ElementSize * ElementCount;

198 } else {

200 }

201 return Size;

202}

203

204

205

206

209

210

211

212 bool HasPackOffset = false;

213 bool HasNonPackOffset = false;

214 for (auto *Field : BufDecl->decls()) {

215 VarDecl *Var = dyn_cast(Field);

216 if (!Var)

217 continue;

218 if (Field->hasAttr()) {

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

220 HasPackOffset = true;

221 } else {

222 HasNonPackOffset = true;

223 }

224 }

225

226 if (!HasPackOffset)

227 return;

228

229 if (HasNonPackOffset)

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

231

232

233

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

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

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

238 return LHS.second->getOffsetInBytes() <

239 RHS.second->getOffsetInBytes();

240 });

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

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

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

245 unsigned Begin = Attr->getOffsetInBytes();

246 unsigned End = Begin + Size;

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

248 if (End > NextBegin) {

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

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

251 << NextVar << Var;

252 }

253 }

254}

255

257 auto *BufDecl = cast(Dcl);

258 BufDecl->setRBraceLoc(RBrace);

259

261

263}

264

267 int X, int Y, int Z) {

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

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

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

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

272 }

273 return nullptr;

274 }

277}

278

281 int Min, int Max, int Preferred,

282 int SpelledArgsCount) {

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

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

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

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

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

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

289 }

290 return nullptr;

291 }

294 Result->setSpelledArgsCount(SpelledArgsCount);

296}

297

298HLSLShaderAttr *

300 llvm::Triple::EnvironmentType ShaderType) {

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

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

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

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

305 }

306 return nullptr;

307 }

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

309}

310

311HLSLParamModifierAttr *

313 HLSLParamModifierAttr::Spelling Spelling) {

314

315

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

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

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

319 D->dropAttr();

321 return HLSLParamModifierAttr::Create(

322 getASTContext(), true, AdjustedRange,

323 HLSLParamModifierAttr::Keyword_inout);

324 }

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

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

327 return nullptr;

328 }

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

330}

331

334

336 return;

337

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

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

341

342

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

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

345 << Shader;

347 }

348 } else {

349

350

353 }

354 } else {

355 switch (Env) {

356 case llvm::Triple::UnknownEnvironment:

357 case llvm::Triple::Library:

358 break;

359 default:

360 llvm_unreachable("Unhandled environment in triple");

361 }

362 }

363}

364

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

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

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

371 switch (ST) {

372 case llvm::Triple::Pixel:

373 case llvm::Triple::Vertex:

374 case llvm::Triple::Geometry:

375 case llvm::Triple::Hull:

376 case llvm::Triple::Domain:

377 case llvm::Triple::RayGeneration:

378 case llvm::Triple::Intersection:

379 case llvm::Triple::AnyHit:

380 case llvm::Triple::ClosestHit:

381 case llvm::Triple::Miss:

382 case llvm::Triple::Callable:

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

385 {llvm::Triple::Compute,

386 llvm::Triple::Amplification,

387 llvm::Triple::Mesh});

389 }

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

392 {llvm::Triple::Compute,

393 llvm::Triple::Amplification,

394 llvm::Triple::Mesh});

396 }

397 break;

398

399 case llvm::Triple::Compute:

400 case llvm::Triple::Amplification:

401 case llvm::Triple::Mesh:

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

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

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

406 }

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

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

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

410 << WS << "6.6";

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

414 WS->getLocation(),

415 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)

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

418 }

419 }

420 break;

421 default:

422 llvm_unreachable("Unhandled environment in triple");

423 }

424

426 if (const auto *AnnotationAttr = Param->getAttr<HLSLAnnotationAttr>()) {

428 } else {

429

430

431 Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation);

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

434 }

435 }

436

437}

438

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

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

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

445

446 switch (AnnotationAttr->getKind()) {

447 case attr::HLSLSV_DispatchThreadID:

448 case attr::HLSLSV_GroupIndex:

449 case attr::HLSLSV_GroupThreadID:

450 case attr::HLSLSV_GroupID:

451 if (ST == llvm::Triple::Compute)

452 return;

454 break;

455 default:

456 llvm_unreachable("Unknown HLSLAnnotationAttr");

457 }

458}

459

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

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

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

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

466 return StringRef(

467 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));

468 });

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

470 << A << llvm::Triple::getEnvironmentTypeName(Stage)

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

472}

473

474template

477 Ty = VTy->getElementType();

480}

481

482template

485 return Ty;

486}

487

493

494 if (LHSFloat && RHSFloat) {

495 if (IsCompAssign ||

497 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);

498

499 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);

500 }

501

502 if (LHSFloat)

503 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);

504

505 assert(RHSFloat);

506 if (IsCompAssign)

507 return castElementclang::CK\_FloatingToIntegral(SemaRef, RHS, LHSType);

508

509 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);

510}

511

515

520

521

522 if (LHSSigned == RHSSigned) {

523 if (IsCompAssign || IntOrder >= 0)

524 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);

525

526 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);

527 }

528

529

530

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

532 if (IsCompAssign || RHSSigned)

533 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);

534 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);

535 }

536

537

538

539

541 if (IsCompAssign || LHSSigned)

542 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);

543 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);

544 }

545

546

547

548

549

550

551

552

553 if (IsCompAssign)

554 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);

555

556

560 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);

561

562 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);

563}

564

568 return CK_FloatingCast;

570 return CK_IntegralCast;

572 return CK_IntegralToFloating;

574 return CK_FloatingToIntegral;

575}

576

580 bool IsCompAssign) {

584

585

586

587 if (!LVecTy && IsCompAssign) {

592 return LHSType;

595 return LHSType;

596 }

597

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

599 unsigned LSz = 0;

600 if (LVecTy)

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

602 if (RVecTy)

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

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

606

607

608

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

611 diag::err_hlsl_vector_compound_assignment_truncation)

612 << LHSType << RHSType;

614 }

615

617 castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);

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

619 castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);

620

621 if (!RVecTy)

622 castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);

623 if (!IsCompAssign && !LVecTy)

624 castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);

625

626

629

632

633

636 LElTy, RElTy, IsCompAssign);

637

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

641 LElTy, RElTy, IsCompAssign);

642}

643

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

647 "Called with non-logical operator");

649 llvm::raw_svector_ostream OS(Buff);

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

652 OS << NewFnName << "(";

654 OS << ", ";

656 OS << ")";

660}

661

663 llvm::VersionTuple SMVersion =

665 uint32_t ZMax = 1024;

666 uint32_t ThreadMax = 1024;

667 if (SMVersion.getMajor() <= 4) {

668 ZMax = 1;

669 ThreadMax = 768;

670 } else if (SMVersion.getMajor() == 5) {

671 ZMax = 64;

672 ThreadMax = 1024;

673 }

674

675 uint32_t X;

677 return;

678 if (X > 1024) {

680 diag::err_hlsl_numthreads_argument_oor)

681 << 0 << 1024;

682 return;

683 }

684 uint32_t Y;

686 return;

687 if (Y > 1024) {

689 diag::err_hlsl_numthreads_argument_oor)

690 << 1 << 1024;

691 return;

692 }

693 uint32_t Z;

695 return;

696 if (Z > ZMax) {

698 diag::err_hlsl_numthreads_argument_oor)

699 << 2 << ZMax;

700 return;

701 }

702

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

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

705 return;

706 }

707

709 if (NewAttr)

711}

712

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

715}

716

718

719

720 unsigned SpelledArgsCount = AL.getNumArgs();

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

722 return;

723

724 uint32_t Min;

726 return;

727

728 uint32_t Max = 0;

729 if (SpelledArgsCount > 1 &&

731 return;

732

733 uint32_t Preferred = 0;

734 if (SpelledArgsCount > 2 &&

736 return;

737

738 if (SpelledArgsCount > 2) {

741 diag::err_attribute_power_of_two_in_range)

742 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize

743 << Preferred;

744 return;

745 }

746

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

749 diag::err_attribute_power_of_two_in_range)

750 << AL << Min << Max << Preferred;

751 return;

752 }

753 } else if (SpelledArgsCount > 1) {

756 diag::err_attribute_power_of_two_in_range)

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

758 return;

759 }

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

762 return;

763 } else if (Max == Min) {

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

765 }

766 } else {

769 diag::err_attribute_power_of_two_in_range)

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

771 return;

772 }

773 }

774

775 HLSLWaveSizeAttr *NewAttr =

777 if (NewAttr)

779}

780

783

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

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

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

788 return false;

789 }

790

791 return true;

792}

793

795 auto *VD = cast(D);

797 return;

798

800 HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));

801}

802

804 auto *VD = cast(D);

806 return;

807

810}

811

813 auto *VD = cast(D);

815 return;

816

818}

819

821 if (!isa(D) || !isa(D->getDeclContext())) {

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

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

824 return;

825 }

826

827 uint32_t SubComponent;

829 return;

830 uint32_t Component;

832 return;

833

834 QualType T = cast(D)->getType().getCanonicalType();

835

836

838

839

840 if (Component) {

842 if (IsAggregateTy || Size > 128) {

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

844 return;

845 } else {

846

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

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

849 return;

850 }

853 EltTy = VT->getElementType();

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

856

857

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

859 << Align << EltTy;

860 return;

861 }

862 }

863 }

864

867}

868

870 StringRef Str;

873 return;

874

875 llvm::Triple::EnvironmentType ShaderType;

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

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

878 << AL << Str << ArgLoc;

879 return;

880 }

881

882

883

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

885 if (NewAttr)

887}

888

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

893

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

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

898

900

901 bool HasResourceClass = false;

902 for (const Attr *A : AttrList) {

903 if (!A)

904 continue;

905 LocEnd = A->getRange().getEnd();

906 switch (A->getKind()) {

907 case attr::HLSLResourceClass: {

908 ResourceClass RC = cast(A)->getResourceClass();

909 if (HasResourceClass) {

911 ? diag::warn_duplicate_attribute_exact

912 : diag::warn_duplicate_attribute)

913 << A;

914 return false;

915 }

917 HasResourceClass = true;

918 break;

919 }

920 case attr::HLSLROV:

921 if (ResAttrs.IsROV) {

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

923 return false;

924 }

925 ResAttrs.IsROV = true;

926 break;

927 case attr::HLSLRawBuffer:

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

930 return false;

931 }

933 break;

934 case attr::HLSLContainedType: {

935 const HLSLContainedTypeAttr *CTAttr = cast(A);

936 QualType Ty = CTAttr->getType();

937 if (!ContainedTy.isNull()) {

938 S.Diag(A->getLocation(), ContainedTy == Ty

939 ? diag::warn_duplicate_attribute_exact

940 : diag::warn_duplicate_attribute)

941 << A;

942 return false;

943 }

944 ContainedTy = Ty;

945 ContainedTyInfo = CTAttr->getTypeLoc();

946 break;

947 }

948 default:

949 llvm_unreachable("unhandled resource attribute type");

950 }

951 }

952

953 if (!HasResourceClass) {

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

955 diag::err_hlsl_missing_resource_class);

956 return false;

957 }

958

960 Wrapped, ContainedTy, ResAttrs);

961

962 if (LocInfo && ContainedTyInfo) {

965 }

966 return true;

967}

968

969

970

971

972

974

975 if (T->isHLSLResourceType()) {

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

978 return false;

979 }

980

981

983 return false;

984

985 Attr *A = nullptr;

987 case ParsedAttr::AT_HLSLResourceClass: {

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

991 return false;

992 }

993

997

998

999 ResourceClass RC;

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

1001 Diag(ArgLoc, diag::warn_attribute_type_not_supported)

1003 return false;

1004 }

1006 break;

1007 }

1008

1009 case ParsedAttr::AT_HLSLROV:

1011 break;

1012

1013 case ParsedAttr::AT_HLSLRawBuffer:

1015 break;

1016

1017 case ParsedAttr::AT_HLSLContainedType: {

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

1020 return false;

1021 }

1022

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

1027 diag::err_incomplete_type))

1028 return false;

1030 break;

1031 }

1032

1033 default:

1034 llvm_unreachable("unhandled HLSL attribute");

1035 }

1036

1037 HLSLResourcesTypeAttrs.emplace_back(A);

1038 return true;

1039}

1040

1041

1043 if (!HLSLResourcesTypeAttrs.size())

1044 return CurrentType;

1045

1049 HLSLResourcesTypeAttrs, QT, &LocInfo)) {

1051 cast(QT.getTypePtr());

1052

1053

1054

1055

1056

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

1058 }

1059 HLSLResourcesTypeAttrs.clear();

1060 return QT;

1061}

1062

1063

1067 auto I = LocsForHLSLAttributedResources.find(RT);

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

1069 LocInfo = I->second;

1070 LocsForHLSLAttributedResources.erase(I);

1071 return LocInfo;

1072 }

1074 return LocInfo;

1075}

1076

1077

1078

1079void SemaHLSL::collectResourcesOnUserRecordDecl(const VarDecl *VD,

1084

1085

1086

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

1092 }

1093

1095 continue;

1096

1099

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

1102 if (!DBI)

1103 Bindings.addDeclBindingInfo(VD, RC);

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

1105

1106

1107

1108

1109

1110 collectResourcesOnUserRecordDecl(VD, RT);

1111 }

1112 }

1113}

1114

1115

1116

1117

1118

1119

1122 bool SpecifiedSpace) {

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

1124

1125

1126 if (D->hasAttr()) {

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

1128 return false;

1129 }

1130

1131

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

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

1134 : ResourceClass::SRV;

1136 return true;

1137

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

1139 << RegTypeNum;

1140 return false;

1141 }

1142

1143

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

1145 VarDecl *VD = cast(D);

1146

1147

1151 if (RegType == getRegisterType(AttrResType->getAttrs().ResourceClass))

1152 return true;

1153

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

1155 << RegTypeNum;

1156 return false;

1157 }

1158

1162

1163

1165 bool DeclaredInCOrTBuffer = isa(D->getDeclContext());

1166 if (SpecifiedSpace && !DeclaredInCOrTBuffer)

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

1168

1169 if (!DeclaredInCOrTBuffer &&

1171

1172 if (RegType == RegisterType::CBuffer)

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

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

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

1176 } else {

1177 if (RegType == RegisterType::C)

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

1179 else

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

1181 }

1182 return false;

1183 }

1185

1186

1187 return true;

1188

1189

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

1191 return false;

1192}

1193

1196

1197

1198 bool RegisterTypesDetected[5] = {false};

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

1200

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

1202 if (HLSLResourceBindingAttr *attr =

1203 dyn_cast(*it)) {

1204

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

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

1209 diag::err_hlsl_duplicate_register_annotation)

1210 << otherRegTypeNum;

1211 return false;

1212 }

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

1214 }

1215 }

1216 return true;

1217}

1218

1221 bool SpecifiedSpace) {

1222

1223

1224 assert(((isa(D) && !isa(D)) ||

1225 (!isa(D) && isa(D))) &&

1226 "expecting VarDecl or HLSLBufferDecl");

1227

1228

1230 return false;

1231

1232

1234}

1235

1237 if (isa(TheDecl)) {

1239 cast(TheDecl)->getType(),

1240 diag::err_incomplete_type))

1241 return;

1242 }

1243 StringRef Space = "space0";

1244 StringRef Slot = "";

1245

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

1249 return;

1250 }

1251

1253 StringRef Str = Loc->Ident->getName();

1255

1257 bool SpecifiedSpace = false;

1259 SpecifiedSpace = true;

1260 Slot = Str;

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

1264 return;

1265 }

1266

1268 Space = Loc->Ident->getName();

1269 SpaceArgLoc = Loc->Loc;

1270 } else {

1271 Slot = Str;

1272 }

1273

1275 unsigned SlotNum = 0;

1276 unsigned SpaceNum = 0;

1277

1278

1279 if (!Slot.empty()) {

1281 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);

1282 return;

1283 }

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

1285 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);

1286 return;

1287 }

1288

1289 StringRef SlotNumStr = Slot.substr(1);

1290 if (SlotNumStr.getAsInteger(10, SlotNum)) {

1291 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);

1292 return;

1293 }

1294 }

1295

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

1297 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;

1298 return;

1299 }

1300 StringRef SpaceNumStr = Space.substr(5);

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

1302 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;

1303 return;

1304 }

1305

1307 SpecifiedSpace))

1308 return;

1309

1310 HLSLResourceBindingAttr *NewAttr =

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

1312 if (NewAttr) {

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

1314 TheDecl->addAttr(NewAttr);

1315 }

1316}

1317

1320 D, AL,

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

1322 if (NewAttr)

1324}

1325

1326namespace {

1327

1328

1329

1330

1331

1332

1333

1334

1335

1336

1337

1338

1339

1341 Sema &SemaRef;

1342

1343

1345

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

1357

1358

1359

1360

1361

1362

1363

1364

1365

1366

1367

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

1369

1370

1371

1372 llvm::Triple::EnvironmentType CurrentShaderEnvironment;

1373 unsigned CurrentShaderStageBit;

1374

1375

1376

1377

1378 bool ReportOnlyShaderStageIssues;

1379

1380

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

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

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

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

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

1386

1387

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

1389 CurrentShaderEnvironment = ShaderType;

1390 CurrentShaderStageBit = (1 << bitmapIndex);

1391 }

1392

1393 void SetUnknownShaderStageContext() {

1394 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;

1395 CurrentShaderStageBit = (1 << 31);

1396 }

1397

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

1399 return CurrentShaderEnvironment;

1400 }

1401

1402 bool InUnknownShaderStageContext() const {

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

1404 }

1405

1406

1407 void AddToScannedFunctions(const FunctionDecl *FD) {

1408 unsigned &ScannedStages = ScannedDecls[FD];

1409 ScannedStages |= CurrentShaderStageBit;

1410 }

1411

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

1413

1414 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {

1415 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));

1416 }

1417

1418 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {

1419 return ScannerStages & CurrentShaderStageBit;

1420 }

1421

1422 static bool NeverBeenScanned(unsigned ScannedStages) {

1423 return ScannedStages == 0;

1424 }

1425

1426

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

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

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

1431 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);

1432

1433public:

1434 DiagnoseHLSLAvailability(Sema &SemaRef)

1435 : SemaRef(SemaRef),

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

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

1438

1439

1442

1443 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {

1445 if (FD)

1446 HandleFunctionOrMethodRef(FD, DRE);

1447 return true;

1448 }

1449

1450 bool VisitMemberExpr(MemberExpr *ME) override {

1452 if (FD)

1453 HandleFunctionOrMethodRef(FD, ME);

1454 return true;

1455 }

1456};

1457

1458void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,

1459 Expr *RefExpr) {

1460 assert((isa(RefExpr) || isa(RefExpr)) &&

1461 "expected DeclRefExpr or MemberExpr");

1462

1463

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

1466 if (!WasAlreadyScannedInCurrentStage(FDWithBody))

1467 DeclsToScan.push_back(FDWithBody);

1468 return;

1469 }

1470

1471

1472 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);

1473 if (AA)

1474 CheckDeclAvailability(

1476}

1477

1478void DiagnoseHLSLAvailability::RunOnTranslationUnit(

1480

1481

1482

1483

1484

1485

1487 DeclContextsToScan.push_back(TU);

1488

1489 while (!DeclContextsToScan.empty()) {

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

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

1492

1494 continue;

1495

1496

1497

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

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

1500 continue;

1501 }

1502

1503

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

1506 continue;

1507

1508

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

1510 SetShaderStageContext(ShaderAttr->getType());

1511 RunOnFunction(FD);

1512 continue;

1513 }

1514

1515

1516

1518 if (!isExport) {

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

1520 if (Redecl->isInExportDeclContext()) {

1521 isExport = true;

1522 break;

1523 }

1524 }

1525 }

1526 if (isExport) {

1527 SetUnknownShaderStageContext();

1528 RunOnFunction(FD);

1529 continue;

1530 }

1531 }

1532 }

1533}

1534

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

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

1537 DeclsToScan.push_back(FD);

1538

1539 while (!DeclsToScan.empty()) {

1540

1541

1542

1543

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

1545

1546

1547 const unsigned ScannedStages = GetScannedStages(FD);

1548 if (WasAlreadyScannedInCurrentStage(ScannedStages))

1549 continue;

1550

1551 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);

1552

1553 AddToScannedFunctions(FD);

1554 TraverseStmt(FD->getBody());

1555 }

1556}

1557

1558bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(

1559 const AvailabilityAttr *AA) {

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

1561 if (!IIEnvironment)

1562 return true;

1563

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

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

1566 return false;

1567

1568 llvm::Triple::EnvironmentType AttrEnv =

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

1570

1571 return CurrentEnv == AttrEnv;

1572}

1573

1574const AvailabilityAttr *

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

1576 AvailabilityAttr const *PartialMatch = nullptr;

1577

1578

1579

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

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

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

1583 StringRef TargetPlatform =

1585

1586

1587 if (AttrPlatform == TargetPlatform) {

1588

1589 if (HasMatchingEnvironmentOrNone(Avail))

1590 return Avail;

1591 PartialMatch = Avail;

1592 }

1593 }

1594 }

1595 return PartialMatch;

1596}

1597

1598

1599

1600void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,

1601 const AvailabilityAttr *AA,

1603

1605

1606 if (!IIEnv) {

1607

1608

1609

1610

1611

1612

1613

1614 if (SemaRef.getLangOpts().HLSLStrictAvailability)

1615 return;

1616

1617

1618

1619

1620 if (ReportOnlyShaderStageIssues)

1621 return;

1622

1623 } else {

1624

1625

1626 if (InUnknownShaderStageContext())

1627 return;

1628 }

1629

1630

1631 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);

1632 VersionTuple Introduced = AA->getIntroduced();

1635

1636 if (TargetVersion >= Introduced && EnvironmentMatches)

1637 return;

1638

1639

1641 llvm::StringRef PlatformName(

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

1643

1644 llvm::StringRef CurrentEnvStr =

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

1646

1647 llvm::StringRef AttrEnvStr =

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

1649 bool UseEnvironment = !AttrEnvStr.empty();

1650

1651 if (EnvironmentMatches) {

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

1654 << UseEnvironment << CurrentEnvStr;

1655 } else {

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

1658 }

1659

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

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

1663 << UseEnvironment << AttrEnvStr << CurrentEnvStr;

1664}

1665

1666}

1667

1669

1670

1671

1672

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

1676 return;

1677

1678 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);

1679}

1680

1681

1685

1687

1690

1691 bool AllBArgAreVectors = true;

1692 for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {

1696 if (VecTyB == nullptr)

1697 AllBArgAreVectors &= false;

1698 if (VecTyA && VecTyB == nullptr) {

1699

1700

1701 S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)

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

1704 return true;

1705 }

1706 if (VecTyA && VecTyB) {

1707 bool retValue = false;

1708 if (VecTyA->getElementType() != VecTyB->getElementType()) {

1709

1710

1712 diag::err_vec_builtin_incompatible_vector)

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

1715 retValue = true;

1716 }

1717 if (VecTyA->getNumElements() != VecTyB->getNumElements()) {

1718

1719

1720

1721 S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)

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

1724 retValue = true;

1725 }

1726 if (retValue)

1727 return retValue;

1728 }

1729 }

1730

1731 if (VecTyA == nullptr && AllBArgAreVectors) {

1732

1733

1734 S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)

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

1737 return true;

1738 }

1739 return false;

1740}

1741

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

1747 return true;

1748 }

1749 return false;

1750}

1751

1754 llvm::function_ref<bool(clang::QualType PassedType)> Check) {

1756 if (Check(PassedType)) {

1759 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());

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

1761 << PassedType << ExpectedType << 1 << 0 << 0;

1762 return true;

1763 }

1764 return false;

1765}

1766

1769 llvm::function_ref<bool(clang::QualType PassedType)> Check) {

1770 for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {

1773 return true;

1774 }

1775 }

1776 return false;

1777}

1778

1780 auto checkAllFloatTypes = [](clang::QualType PassedType) -> bool {

1781 return !PassedType->hasFloatingRepresentation();

1782 };

1784 checkAllFloatTypes);

1785}

1786

1788 auto checkFloatorHalf = [](clang::QualType PassedType) -> bool {

1792 : PassedType;

1794 };

1796 checkFloatorHalf);

1797}

1798

1800 unsigned ArgIndex) {

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

1805 return false;

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

1807 return true;

1808}

1809

1811 auto checkDoubleVector = [](clang::QualType PassedType) -> bool {

1812 if (const auto *VecTy = PassedType->getAs<VectorType>())

1813 return VecTy->getElementType()->isDoubleType();

1814 return false;

1815 };

1817 checkDoubleVector);

1818}

1820 auto checkAllSignedTypes = [](clang::QualType PassedType) -> bool {

1821 return !PassedType->hasIntegerRepresentation() &&

1822 !PassedType->hasFloatingRepresentation();

1823 };

1825 checkAllSignedTypes);

1826}

1827

1829 auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool {

1830 return !PassedType->hasUnsignedIntegerRepresentation();

1831 };

1833 checkAllUnsignedTypes);

1834}

1835

1839 if (VecTyA)

1842 TheCall->setType(ReturnType);

1843}

1844

1846 unsigned ArgIndex) {

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

1850

1852 (VTy &&

1855 diag::err_typecheck_expect_scalar_or_vector)

1856 << ArgType << Scalar;

1857 return true;

1858 }

1859 return false;

1860}

1861

1863 unsigned ArgIndex) {

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

1867

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

1871 diag::err_typecheck_expect_any_scalar_or_vector)

1872 << ArgType << 1;

1873 return true;

1874 }

1875 return false;

1876}

1877

1883

1885 (VTy &&

1888 diag::err_typecheck_expect_any_scalar_or_vector)

1889 << ArgType << 0;

1890 return true;

1891 }

1892 return false;

1893}

1894

1901 diag::err_typecheck_call_different_arg_types)

1904 return true;

1905 }

1906

1908 return false;

1909}

1910

1916 S->Diag(Arg1->getBeginLoc(), diag::err_builtin_non_vector_type)

1919 return true;

1920 }

1921

1923 S->Diag(Arg2->getBeginLoc(), diag::err_builtin_non_vector_type)

1926 return true;

1927 }

1928

1931 diag::err_typecheck_call_different_arg_types)

1934 return true;

1935 }

1936

1937

1938

1942 diag::err_typecheck_vector_lengths_not_equal)

1945 return true;

1946 }

1948 return false;

1949}

1950

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

1954 nullptr) {

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

1959 if (!ResTy) {

1961 diag::err_typecheck_expect_hlsl_resource)

1962 << ArgType;

1963 return true;

1964 }

1965 if (Check && Check(ResTy)) {

1967 diag::err_invalid_hlsl_resource_type)

1968 << ArgType;

1969 return true;

1970 }

1971 return false;

1972}

1973

1974

1975

1977 switch (BuiltinID) {

1978 case Builtin::BI__builtin_hlsl_resource_getpointer: {

1983 return true;

1984

1985 auto *ResourceTy =

1987 QualType ContainedTy = ResourceTy->getContainedType();

1988

1991

1992 break;

1993 }

1994 case Builtin::BI__builtin_hlsl_all:

1995 case Builtin::BI__builtin_hlsl_any: {

1997 return true;

1998 break;

1999 }

2000 case Builtin::BI__builtin_hlsl_asdouble: {

2002 return true;

2004 return true;

2005

2007 break;

2008 }

2009 case Builtin::BI__builtin_hlsl_elementwise_clamp: {

2011 return true;

2013 return true;

2015 TheCall,

2017 return true;

2018 break;

2019 }

2020 case Builtin::BI__builtin_hlsl_cross: {

2022 return true;

2024 return true;

2026 return true;

2027

2028 int NumElementsArg1 =

2030 int NumElementsArg2 =

2032

2033 if (NumElementsArg1 != 3) {

2034 int LessOrMore = NumElementsArg1 > 3 ? 1 : 0;

2036 diag::err_vector_incorrect_num_elements)

2037 << LessOrMore << 3 << NumElementsArg1 << 1;

2038 return true;

2039 }

2040 if (NumElementsArg2 != 3) {

2041 int LessOrMore = NumElementsArg2 > 3 ? 1 : 0;

2042

2044 diag::err_vector_incorrect_num_elements)

2045 << LessOrMore << 3 << NumElementsArg2 << 1;

2046 return true;

2047 }

2048

2051

2052 TheCall->setType(ArgTyA);

2053 break;

2054 }

2055 case Builtin::BI__builtin_hlsl_dot: {

2057 return true;

2059 return true;

2061 return true;

2063 return true;

2064 break;

2065 }

2066 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:

2067 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {

2069 return true;

2070

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

2074

2076

2078 EltTy = VecTy->getElementType();

2080 VecTy->getVectorKind());

2081 }

2082

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

2085 << 1 << 6 << ArgTy;

2086 return true;

2087 }

2088

2089 TheCall->setType(ResTy);

2090 break;

2091 }

2092 case Builtin::BI__builtin_hlsl_select: {

2094 return true;

2096 return true;

2099 return true;

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

2103 return true;

2104 break;

2105 }

2106 case Builtin::BI__builtin_hlsl_elementwise_saturate:

2107 case Builtin::BI__builtin_hlsl_elementwise_rcp: {

2109 return true;

2111 return true;

2112 break;

2113 }

2114 case Builtin::BI__builtin_hlsl_elementwise_degrees:

2115 case Builtin::BI__builtin_hlsl_elementwise_radians:

2116 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:

2117 case Builtin::BI__builtin_hlsl_elementwise_frac: {

2119 return true;

2121 return true;

2122 break;

2123 }

2124 case Builtin::BI__builtin_hlsl_elementwise_isinf: {

2126 return true;

2128 return true;

2130 break;

2131 }

2132 case Builtin::BI__builtin_hlsl_lerp: {

2134 return true;

2136 return true;

2138 return true;

2140 return true;

2141 break;

2142 }

2143 case Builtin::BI__builtin_hlsl_mad: {

2145 return true;

2147 return true;

2149 TheCall,

2151 return true;

2152 break;

2153 }

2154 case Builtin::BI__builtin_hlsl_normalize: {

2156 return true;

2158 return true;

2159

2162

2163 TheCall->setType(ArgTyA);

2164 break;

2165 }

2166 case Builtin::BI__builtin_hlsl_elementwise_sign: {

2168 return true;

2170 return true;

2172 break;

2173 }

2174 case Builtin::BI__builtin_hlsl_step: {

2176 return true;

2178 return true;

2179

2182

2183 TheCall->setType(ArgTyA);

2184 break;

2185 }

2186 case Builtin::BI__builtin_hlsl_wave_active_sum: {

2188 return true;

2189

2190

2192 return true;

2194 return true;

2197 TheCall->setType(ArgTyExpr);

2198 break;

2199 }

2200

2201

2202 case Builtin::BI__builtin_elementwise_bitreverse: {

2204 return true;

2205 break;

2206 }

2207 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {

2209 return true;

2210

2211

2213 QualType ArgTyIndex = Index.get()->getType();

2216 diag::err_typecheck_convert_incompatible)

2218 return true;

2219 }

2220

2221

2223 return true;

2224

2227 TheCall->setType(ArgTyExpr);

2228 break;

2229 }

2230 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {

2232 return true;

2233 break;

2234 }

2235 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {

2237 return true;

2238

2241 1) ||

2243 2))

2244 return true;

2245

2248 return true;

2249 break;

2250 }

2251 case Builtin::BI__builtin_hlsl_elementwise_clip: {

2253 return true;

2254

2256 return true;

2257 break;

2258 }

2259 case Builtin::BI__builtin_elementwise_acos:

2260 case Builtin::BI__builtin_elementwise_asin:

2261 case Builtin::BI__builtin_elementwise_atan:

2262 case Builtin::BI__builtin_elementwise_atan2:

2263 case Builtin::BI__builtin_elementwise_ceil:

2264 case Builtin::BI__builtin_elementwise_cos:

2265 case Builtin::BI__builtin_elementwise_cosh:

2266 case Builtin::BI__builtin_elementwise_exp:

2267 case Builtin::BI__builtin_elementwise_exp2:

2268 case Builtin::BI__builtin_elementwise_floor:

2269 case Builtin::BI__builtin_elementwise_fmod:

2270 case Builtin::BI__builtin_elementwise_log:

2271 case Builtin::BI__builtin_elementwise_log2:

2272 case Builtin::BI__builtin_elementwise_log10:

2273 case Builtin::BI__builtin_elementwise_pow:

2274 case Builtin::BI__builtin_elementwise_roundeven:

2275 case Builtin::BI__builtin_elementwise_sin:

2276 case Builtin::BI__builtin_elementwise_sinh:

2277 case Builtin::BI__builtin_elementwise_sqrt:

2278 case Builtin::BI__builtin_elementwise_tan:

2279 case Builtin::BI__builtin_elementwise_tanh:

2280 case Builtin::BI__builtin_elementwise_trunc: {

2282 return true;

2283 break;

2284 }

2285 case Builtin::BI__builtin_hlsl_buffer_update_counter: {

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

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

2289 };

2294 return true;

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

2296 std::optionalllvm::APSInt Offset =

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

2300 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)

2301 << 1;

2302 return true;

2303 }

2304 break;

2305 }

2306 }

2307 return false;

2308}

2309

2313 WorkList.push_back(BaseTy);

2314 while (!WorkList.empty()) {

2315 QualType T = WorkList.pop_back_val();

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

2317 assert(!isa(T) && "Matrix types not yet supported in HLSL");

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

2320

2321

2322

2323

2325

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

2327 List.insert(List.end(), ElementFields.begin(), ElementFields.end());

2328 continue;

2329 }

2330

2331

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

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

2334 continue;

2335 }

2336 if (const auto *RT = dyn_cast(T)) {

2339 List.push_back(T);

2340 continue;

2341 }

2342 const CXXRecordDecl *CXXD = dyn_cast(RD);

2343

2347

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

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

2350

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

2352 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());

2353

2354

2355

2357 FieldTypes.clear();

2358 for (const auto &Base : CXXD->bases())

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

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

2361 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());

2362 }

2363 continue;

2364 }

2365 List.push_back(T);

2366 }

2367}

2368

2370

2372 return false;

2373

2374

2376 return false;

2377

2379 return false;

2380

2381

2384 return false;

2385 return true;

2386 }

2387

2389 int ArraySize = VT->getNumElements();

2390

2391 if (ArraySize > 4)

2392 return false;

2393

2394 QualType ElTy = VT->getElementType();

2396 return false;

2397

2399 return false;

2400 return true;

2401 }

2402

2403 return false;

2404}

2405

2408 return false;

2409

2412

2413

2415 return true;

2416

2421

2422

2423 return llvm::equal(T1Types, T2Types,

2426 });

2427}

2428

2432 return true;

2433

2434 bool HadError = false;

2435

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

2439

2440

2441

2442

2443

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

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

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

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

2448

2449 if (NSpellingIdx != OSpellingIdx) {

2451 diag::err_hlsl_param_qualifier_mismatch)

2452 << NDAttr << NewParam;

2454 << ODAttr;

2455 HadError = true;

2456 }

2457 }

2458 return HadError;

2459}

2460

2462 assert(Param->hasAttr() &&

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

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

2467

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

2473 }

2474

2476

2478

2479

2480

2481

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

2486 }

2487

2490

2491

2492

2500

2502 auto *OpV = new (Ctx)

2504

2505

2506

2508 tok::equal, ArgOpV, OpV);

2509

2512 Expr *Writeback = Res.get();

2513 auto *OutExpr =

2515

2517}

2518

2520

2521

2522

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

2527 return Ty;

2528}

2529

2532

2536 diag::err_typecheck_decl_incomplete_type)) {

2538 return;

2539 }

2540

2541

2543 collectResourcesOnVarDecl(VD);

2544

2545

2546 processExplicitBindingsOnDecl(VD);

2547 }

2548}

2549

2550

2551

2552void SemaHLSL::collectResourcesOnVarDecl(VarDecl *VD) {

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

2555

2556

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

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

2559 ? ResourceClass::CBuffer

2560 : ResourceClass::SRV);

2561 return;

2562 }

2563

2564

2565

2570 }

2571

2572

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

2576 return;

2577 }

2578

2579

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

2581 collectResourcesOnUserRecordDecl(VD, RT);

2582}

2583

2584

2585

2586

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

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

2589

2591 HLSLResourceBindingAttr *RBA = dyn_cast(A);

2592 if (!RBA)

2593 continue;

2594

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

2597 "never have an attribute created");

2598

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

2600 if (Bindings.hasBindingInfoForDecl(VD))

2602 diag::warn_hlsl_user_defined_type_missing_member)

2603 << static_cast<int>(RT);

2604 continue;

2605 }

2606

2607

2608

2609

2612

2614 } else {

2616 diag::warn_hlsl_user_defined_type_missing_member)

2617 << static_cast<int>(RT);

2618 }

2619 }

2620}

Defines the clang::ASTContext interface.

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

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

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

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

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

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

static bool convertToRegisterType(StringRef Slot, RegisterType *RT)

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

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

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

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

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

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

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

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

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

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

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

static RegisterType getRegisterType(ResourceClass RC)

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

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

static bool CheckArgTypeIsCorrect(Sema *S, Expr *Arg, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)

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

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

static ResourceClass getResourceClass(RegisterType RT)

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

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

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

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

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

HLSLResourceBindingAttr::RegisterType RegisterType

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

static bool isValidWaveSizeValue(unsigned Value)

static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)

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

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

This file declares semantic analysis for HLSL constructs.

Defines the clang::SourceLocation class and associated facilities.

Defines the clang::TypeLoc interface and its subclasses.

C Language Family Type Representation.

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

unsigned getIntWidth(QualType T) const

int getIntegerTypeOrder(QualType LHS, QualType RHS) const

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

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const

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

QualType getPointerType(QualType T) const

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

QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const

Return the uniqued reference to the type for an lvalue reference to the specified type.

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

int getFloatingTypeOrder(QualType LHS, QualType RHS) const

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

bool hasSameUnqualifiedType(QualType T1, QualType T2) const

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

uint64_t getTypeSize(QualType T) const

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

CanQualType UnsignedIntTy

QualType getCommonSugaredType(QualType X, QualType Y, bool Unqualified=false)

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 getCorrespondingUnsignedType(QualType T) const

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

unsigned getTypeAlign(QualType T) const

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

QualType getElementType() const

Attr - This represents one attribute.

attr::Kind getKind() const

SourceRange getRange() const

SourceLocation getLoc() const

Represents a C++ struct/union/class.

bool isStandardLayout() const

Determine whether this class is standard-layout per C++ [class]p7.

const CXXRecordDecl * getStandardLayoutBaseWithFields() const

If this is a standard-layout class or union, any and all data members will be declared in the same ty...

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 LLVM_READONLY

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.

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

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

decl_range decls() const

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

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

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

DeclContext * getDeclContext()

SourceLocation getBeginLoc() const LLVM_READONLY

SourceLocation getBeginLoc() const LLVM_READONLY

Recursive AST visitor that supports extension via dynamic dispatch.

This represents one expression.

isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const

isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, does not have an incomplet...

bool isLValue() const

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

Expr * IgnoreCasts() LLVM_READONLY

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

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...

std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const

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

Represents a member of a struct/union/class.

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 ...

ArrayRef< ParmVarDecl * > parameters() const

unsigned getNumParams() const

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

bool hasBody(const FunctionDecl *&Definition) const

Returns true if the function has a body.

static const HLSLAttributedResourceType * findHandleTypeOnResource(const Type *RT)

HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.

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

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

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

StringRef getName() const

Return the actual identifier string.

Describes an entity that is being initialized.

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

Create the initialization entity for a parameter.

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

ValueDecl * getMemberDecl() const

Retrieve the member declaration to which this expression refers.

This represents a decl that may have a name.

StringRef getName() const

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

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.

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.

QualType getCanonicalType() const

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

Represents a struct/union/class.

field_range fields() const

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

RecordDecl * getDecl() const

redecl_range redecls() const

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

bool hasBindingInfoForDecl(const VarDecl *VD) const

DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)

DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)

Scope - A scope is a transient data structure that is used while parsing the program.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

ASTContext & getASTContext() const

ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)

void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)

void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)

HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)

QualType ProcessResourceTypeAttributes(QualType Wrapped)

void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL)

void handleShaderAttr(Decl *D, const ParsedAttr &AL)

void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL)

void CheckEntryPoint(FunctionDecl *FD)

void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)

HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)

void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)

void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)

bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)

void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)

bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const

bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)

QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)

void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)

bool IsTypedResourceElementCompatible(QualType T1)

void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)

void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU)

void ActOnTopLevelFunction(FunctionDecl *FD)

bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)

HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)

void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)

HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)

QualType getInoutParameterType(QualType Ty)

Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)

HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)

void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL)

void ActOnVariableDeclarator(VarDecl *VD)

bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)

Sema - This implements semantic analysis and AST building for C.

Scope * getCurScope() const

Retrieve the parser's current scope.

void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)

Add this decl to the scope shadowed decl chains.

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.

bool BuiltinVectorToScalarMath(CallExpr *TheCall)

bool IsLayoutCompatible(QualType T1, QualType T2) const

const LangOptions & getLangOpts() const

bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall)

DeclContext * getCurLexicalContext() const

bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)

If Expr is a valid integer constant, get the value of the integer expression and return success or fa...

bool BuiltinElementwiseTernaryMath(CallExpr *TheCall, bool CheckForFloatArgs=true)

ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)

Binary Operators. 'Tok' is the token for the operator.

bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)

Checks that a call expression's argument count is the desired number.

bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)

Ensure that the type T is a complete type.

void PushDeclContext(Scope *S, DeclContext *DC)

Set the current declaration context until it gets popped.

ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)

static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)

bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)

Check if the argument E is a ASCII string literal.

Encodes a location in the source.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

SourceLocation getEndLoc() const LLVM_READONLY

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

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 isStructureType() const

bool isBooleanType() const

bool isIncompleteArrayType() const

bool isConstantArrayType() const

bool isArithmeticType() 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.

bool isFloat32Type() const

bool hasSignedIntegerRepresentation() const

Determine whether this type has an signed integer representation of some sort, e.g....

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 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

Represents a variable declaration or definition.

bool hasGlobalStorage() const

Returns true for all variables that do not have local storage.

Represents a GCC generic vector type.

unsigned getNumElements() const

Defines the clang::TargetInfo interface.

const internal::VariadicAllOfMatcher< Attr > attr

Matches attributes.

The JSON file list parser is used to communicate input to InstallAPI.

@ OK_Ordinary

An ordinary object is located at an address in memory.

@ AANT_ArgumentIdentifier

@ Result

The result type of a method or function.

@ Ordinary

This parameter uses ordinary ABI rules for its type.

ActionResult< Expr * > ExprResult

bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)

CastKind

CastKind - The kind of operation required for a conversion.

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

const FunctionProtoType * T

@ Generic

not a target-specific vector type

Diagnostic wrappers for TextAPI types for error reporting.

__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)

TypeSourceInfo * ContainedTyInfo

llvm::dxil::ResourceClass ResourceClass

Wraps an identifier and optional source location for the identifier.

Describes how types, statements, expressions, and declarations should be printed.