;
55 caseResourceClass::SRV:
56 returnRegisterType::SRV;
57 caseResourceClass::UAV:
58 returnRegisterType::UAV;
59 caseResourceClass::CBuffer:
60 returnRegisterType::CBuffer;
61 caseResourceClass::Sampler:
62 returnRegisterType::Sampler;
64llvm_unreachable(
"unexpected ResourceClass value");
70assert(RT !=
nullptr);
74*RT = RegisterType::SRV;
78*RT = RegisterType::UAV;
82*RT = RegisterType::CBuffer;
86*RT = RegisterType::Sampler;
90*RT = RegisterType::C;
94*RT = RegisterType::I;
103 caseRegisterType::SRV:
104 returnResourceClass::SRV;
105 caseRegisterType::UAV:
106 returnResourceClass::UAV;
107 caseRegisterType::CBuffer:
108 returnResourceClass::CBuffer;
109 caseRegisterType::Sampler:
110 returnResourceClass::Sampler;
111 caseRegisterType::C:
112 caseRegisterType::I:
116llvm_unreachable(
"unexpected RegisterType value");
120ResourceClass ResClass) {
122 "DeclBindingInfo already added");
128DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
129 return&BindingsList.emplace_back(VD, ResClass);
133ResourceClass ResClass) {
134 autoEntry = DeclToBindingListIndex.find(VD);
135 if(Entry != DeclToBindingListIndex.end()) {
136 for(
unsignedIndex = Entry->getSecond();
137Index < BindingsList.size() && BindingsList[Index].Decl == VD;
139 if(BindingsList[Index].ResClass == ResClass)
140 return&BindingsList[Index];
147 returnDeclToBindingListIndex.contains(VD);
159 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
162 autoRC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
163: llvm::hlsl::ResourceClass::SRV;
164 autoRK = CBuffer ? llvm::hlsl::ResourceKind::CBuffer
165: llvm::hlsl::ResourceKind::TBuffer;
180 constexpr unsignedCBufferAlign = 16;
188 unsignedFieldAlign = 4;
190FieldAlign = CBufferAlign;
191Size = llvm::alignTo(Size, FieldAlign);
195 if(
unsignedElementCount = AT->getSize().getZExtValue()) {
196 unsignedElementSize =
198 unsignedAlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
199Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
202 unsignedElementCount = VT->getNumElements();
203 unsignedElementSize =
205Size = ElementSize * ElementCount;
220 boolHasPackOffset =
false;
221 boolHasNonPackOffset =
false;
222 for(
auto*Field : BufDecl->
decls()) {
223 VarDecl*Var = dyn_cast<VarDecl>(Field);
226 if(Field->hasAttr<HLSLPackOffsetAttr>()) {
227PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
228HasPackOffset =
true;
230HasNonPackOffset =
true;
237 if(HasNonPackOffset)
243std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
244[](
conststd::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
245 conststd::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
246return LHS.second->getOffsetInBytes() <
247RHS.second->getOffsetInBytes();
249 for(
unsignedi = 0; i < PackOffsetVec.size() - 1; i++) {
250 VarDecl*Var = PackOffsetVec[i].first;
251HLSLPackOffsetAttr *
Attr= PackOffsetVec[i].second;
253 unsigned Begin=
Attr->getOffsetInBytes();
254 unsignedEnd =
Begin+ Size;
255 unsignedNextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
256 if(End > NextBegin) {
257 VarDecl*NextVar = PackOffsetVec[i + 1].first;
267CAT = dyn_cast<ConstantArrayType>(
269 returnCAT !=
nullptr;
315 Base.getType()->getAsCXXRecordDecl()))
326assert(RD ==
nullptr&&
327 "there should be at most 1 record by a given name in a scope");
344Name.append(NameBaseII->
getName());
347Name.append(
"anon");
348MustBeUnique =
true;
351 size_tNameLength = Name.size();
360Name.append(llvm::Twine(suffix).str());
361II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
368Name.truncate(NameLength);
410 "struct is already HLSL buffer compatible");
426 if(
unsignedNumBases = StructDecl->
getNumBases()) {
427assert(NumBases == 1 &&
"HLSL supports only one base type");
481 VarDecl*VD = dyn_cast<VarDecl>(
D);
501 auto*BufDecl = cast<HLSLBufferDecl>(Dcl);
502BufDecl->setRBraceLoc(RBrace);
514 int X,
intY,
intZ) {
515 if(HLSLNumThreadsAttr *NT =
D->
getAttr<HLSLNumThreadsAttr>()) {
516 if(NT->getX() !=
X|| NT->getY() != Y || NT->getZ() != Z) {
517 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
518 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
528 int Min,
int Max,
intPreferred,
529 intSpelledArgsCount) {
530 if(HLSLWaveSizeAttr *WS =
D->
getAttr<HLSLWaveSizeAttr>()) {
531 if(WS->getMin() !=
Min|| WS->getMax() !=
Max||
532WS->getPreferred() != Preferred ||
533WS->getSpelledArgsCount() != SpelledArgsCount) {
534 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
535 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
541 Result->setSpelledArgsCount(SpelledArgsCount);
547llvm::Triple::EnvironmentType ShaderType) {
548 if(HLSLShaderAttr *NT =
D->
getAttr<HLSLShaderAttr>()) {
549 if(NT->getType() != ShaderType) {
550 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
551 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
555 returnHLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
558HLSLParamModifierAttr *
560HLSLParamModifierAttr::Spelling Spelling) {
563 if(HLSLParamModifierAttr *PA =
D->
getAttr<HLSLParamModifierAttr>()) {
564 if((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
565(PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
568 returnHLSLParamModifierAttr::Create(
570HLSLParamModifierAttr::Keyword_inout);
572 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
573 Diag(PA->getLocation(), diag::note_conflicting_attribute);
586 if(HLSLShaderAttr::isValidShaderType(
Env) &&
Env!= llvm::Triple::Library) {
587 if(
const auto*Shader = FD->
getAttr<HLSLShaderAttr>()) {
590 if(Shader->getType() !=
Env) {
591 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
603 casellvm::Triple::UnknownEnvironment:
604 casellvm::Triple::Library:
607llvm_unreachable(
"Unhandled environment in triple");
613 const auto*ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
614assert(ShaderAttr &&
"Entry point has no shader attribute");
615llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
619 casellvm::Triple::Pixel:
620 casellvm::Triple::Vertex:
621 casellvm::Triple::Geometry:
622 casellvm::Triple::Hull:
623 casellvm::Triple::Domain:
624 casellvm::Triple::RayGeneration:
625 casellvm::Triple::Intersection:
626 casellvm::Triple::AnyHit:
627 casellvm::Triple::ClosestHit:
628 casellvm::Triple::Miss:
629 casellvm::Triple::Callable:
630 if(
const auto*NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
632{llvm::Triple::Compute,
633llvm::Triple::Amplification,
634llvm::Triple::Mesh});
637 if(
const auto*WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
639{llvm::Triple::Compute,
640llvm::Triple::Amplification,
641llvm::Triple::Mesh});
646 casellvm::Triple::Compute:
647 casellvm::Triple::Amplification:
648 casellvm::Triple::Mesh:
649 if(!FD->
hasAttr<HLSLNumThreadsAttr>()) {
651<< llvm::Triple::getEnvironmentTypeName(ST);
654 if(
const auto*WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
655 if(Ver < VersionTuple(6, 6)) {
656 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
659}
else if(WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
662diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
663<< WS << WS->getSpelledArgsCount() <<
"6.8";
669llvm_unreachable(
"Unhandled environment in triple");
678 Diag(FD->
getLocation(), diag::err_hlsl_missing_semantic_annotation);
679 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
689 auto*ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
690assert(ShaderAttr &&
"Entry point has no shader attribute");
691llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
693 switch(AnnotationAttr->
getKind()) {
694 caseattr::HLSLSV_DispatchThreadID:
695 caseattr::HLSLSV_GroupIndex:
696 caseattr::HLSLSV_GroupThreadID:
697 caseattr::HLSLSV_GroupID:
698 if(ST == llvm::Triple::Compute)
703llvm_unreachable(
"Unknown HLSLAnnotationAttr");
708 const Attr*A, llvm::Triple::EnvironmentType Stage,
709std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
711llvm::transform(AllowedStages, std::back_inserter(StageStrings),
712[](llvm::Triple::EnvironmentType ST) {
714HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
716 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
717<< A << llvm::Triple::getEnvironmentTypeName(Stage)
718<< (AllowedStages.size() != 1) << join(StageStrings,
", ");
721template<CastKind Kind>
724Ty = VTy->getElementType();
729template<CastKind Kind>
741 if(LHSFloat && RHSFloat) {
744 returncastElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
746 returncastElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
750 returncastElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
754 returncastElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
756 returncastElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
769 if(LHSSigned == RHSSigned) {
770 if(IsCompAssign || IntOrder >= 0)
771 returncastElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
773 returncastElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
778 if(IntOrder != (LHSSigned ? 1 : -1)) {
779 if(IsCompAssign || RHSSigned)
780 returncastElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
781 returncastElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
788 if(IsCompAssign || LHSSigned)
789 returncastElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
790 returncastElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
801 returncastElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
807(void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
809 returncastElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
815 returnCK_FloatingCast;
817 returnCK_IntegralCast;
819 returnCK_IntegralToFloating;
821 returnCK_FloatingToIntegral;
834 if(!LVecTy && IsCompAssign) {
845 unsignedEndSz = std::numeric_limits<unsigned>::max();
848LSz = EndSz = LVecTy->getNumElements();
851assert(EndSz != std::numeric_limits<unsigned>::max() &&
852 "one of the above should have had a value");
856 if(IsCompAssign && LSz != EndSz) {
858diag::err_hlsl_vector_compound_assignment_truncation)
859<< LHSType << RHSType;
864castVector<CK_HLSLVectorTruncation>(
SemaRef, RHS, RHSType, EndSz);
865 if(!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
866castVector<CK_HLSLVectorTruncation>(
SemaRef, LHS, LHSType, EndSz);
869castVector<CK_VectorSplat>(
SemaRef, RHS, RHSType, EndSz);
870 if(!IsCompAssign && !LVecTy)
871castVector<CK_VectorSplat>(
SemaRef, LHS, LHSType, EndSz);
883LElTy, RElTy, IsCompAssign);
886 "HLSL Vectors can only contain integer or floating point types");
888LElTy, RElTy, IsCompAssign);
893assert((Opc == BO_LOr || Opc == BO_LAnd) &&
894 "Called with non-logical operator");
896llvm::raw_svector_ostream OS(Buff);
898StringRef NewFnName = Opc == BO_LOr ?
"or":
"and";
899OS << NewFnName <<
"(";
910llvm::VersionTuple SMVersion =
912uint32_t ZMax = 1024;
913uint32_t ThreadMax = 1024;
914 if(SMVersion.getMajor() <= 4) {
917}
else if(SMVersion.getMajor() == 5) {
927diag::err_hlsl_numthreads_argument_oor)
936diag::err_hlsl_numthreads_argument_oor)
945diag::err_hlsl_numthreads_argument_oor)
950 if(
X* Y * Z > ThreadMax) {
951 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
967 unsignedSpelledArgsCount = AL.
getNumArgs();
968 if(SpelledArgsCount == 0 || SpelledArgsCount > 3)
976 if(SpelledArgsCount > 1 &&
980uint32_t Preferred = 0;
981 if(SpelledArgsCount > 2 &&
985 if(SpelledArgsCount > 2) {
988diag::err_attribute_power_of_two_in_range)
989<< AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
994 if(Preferred < Min || Preferred >
Max) {
996diag::err_attribute_power_of_two_in_range)
997<< AL <<
Min<<
Max<< Preferred;
1000}
else if(SpelledArgsCount > 1) {
1003diag::err_attribute_power_of_two_in_range)
1004<< AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1008 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1010}
else if(
Max==
Min) {
1011 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1016diag::err_attribute_power_of_two_in_range)
1017<< AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1022HLSLWaveSizeAttr *NewAttr =
1032(VT && VT->getNumElements() > 3)) {
1033 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1034<< AL <<
"uint/uint2/uint3";
1042 auto*VD = cast<ValueDecl>(
D);
1051 auto*VD = cast<ValueDecl>(
D);
1060 auto*VD = cast<ValueDecl>(
D);
1069 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1070<< AL <<
"shader constant in a constant buffer";
1074uint32_t SubComponent;
1081 QualType T= cast<VarDecl>(
D)->getType().getCanonicalType();
1089 if(IsAggregateTy || Size > 128) {
1090 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1094 if((Component * 32 + Size) > 128) {
1095 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1100EltTy = VT->getElementType();
1102 if(Align > 32 && Component == 1) {
1105 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1122llvm::Triple::EnvironmentType ShaderType;
1123 if(!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1124 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1125<< AL << Str << ArgLoc;
1139assert(AttrList.size() &&
"expected list of resource attributes");
1148 boolHasResourceClass =
false;
1149 for(
const Attr*A : AttrList) {
1152LocEnd = A->getRange().getEnd();
1153 switch(A->getKind()) {
1154 caseattr::HLSLResourceClass: {
1155ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
1156 if(HasResourceClass) {
1158? diag::warn_duplicate_attribute_exact
1159: diag::warn_duplicate_attribute)
1164HasResourceClass =
true;
1168 if(ResAttrs.
IsROV) {
1169S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1172ResAttrs.
IsROV=
true;
1174 caseattr::HLSLRawBuffer:
1176S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1181 caseattr::HLSLContainedType: {
1182 constHLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
1184 if(!ContainedTy.
isNull()) {
1185S.
Diag(A->getLocation(), ContainedTy == Ty
1186? diag::warn_duplicate_attribute_exact
1187: diag::warn_duplicate_attribute)
1196llvm_unreachable(
"unhandled resource attribute type");
1200 if(!HasResourceClass) {
1201S.
Diag(AttrList.back()->getRange().getEnd(),
1202diag::err_hlsl_missing_resource_class);
1207Wrapped, ContainedTy, ResAttrs);
1209 if(LocInfo && ContainedTyInfo) {
1222 if(!
T->isHLSLResourceType()) {
1223 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1234 caseParsedAttr::AT_HLSLResourceClass: {
1236 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1247 if(!HLSLResourceClassAttr::ConvertStrToResourceClass(
Identifier, RC)) {
1248 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1256 caseParsedAttr::AT_HLSLROV:
1260 caseParsedAttr::AT_HLSLRawBuffer:
1264 caseParsedAttr::AT_HLSLContainedType: {
1266 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1272assert(TSI &&
"no type source info for attribute argument");
1274diag::err_incomplete_type))
1281llvm_unreachable(
"unhandled HLSL attribute");
1284HLSLResourcesTypeAttrs.emplace_back(A);
1290 if(!HLSLResourcesTypeAttrs.size())
1296HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1298cast<HLSLAttributedResourceType>(QT.
getTypePtr());
1304LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1306HLSLResourcesTypeAttrs.clear();
1314 autoI = LocsForHLSLAttributedResources.find(RT);
1315 if(I != LocsForHLSLAttributedResources.end()) {
1316LocInfo = I->second;
1317LocsForHLSLAttributedResources.erase(I);
1326voidSemaHLSL::collectResourcesOnUserRecordDecl(
const VarDecl*VD,
1335 "incomplete arrays inside user defined types are not supported");
1347ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1350 Bindings.addDeclBindingInfo(VD, RC);
1351}
else if(
const RecordType*RT = dyn_cast<RecordType>(Ty)) {
1357collectResourcesOnUserRecordDecl(VD, RT);
1369 boolSpecifiedSpace) {
1370 intRegTypeNum =
static_cast<int>(RegType);
1373 if(
D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
1374S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1379 if(
HLSLBufferDecl*CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(
D)) {
1380ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1381: ResourceClass::SRV;
1391assert(isa<VarDecl>(
D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
1398 if(RegType ==
getRegisterType(AttrResType->getAttrs().ResourceClass))
1412 boolDeclaredInCOrTBuffer = isa<HLSLBufferDecl>(
D->
getDeclContext());
1413 if(SpecifiedSpace && !DeclaredInCOrTBuffer)
1414S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1416 if(!DeclaredInCOrTBuffer &&
1419 if(RegType == RegisterType::CBuffer)
1420S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1421 else if(RegType != RegisterType::C)
1422S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1424 if(RegType == RegisterType::C)
1425S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1427S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1437S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1445 boolRegisterTypesDetected[5] = {
false};
1446RegisterTypesDetected[
static_cast<int>(regType)] =
true;
1449 if(HLSLResourceBindingAttr *
attr=
1450dyn_cast<HLSLResourceBindingAttr>(*it)) {
1453 if(RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
1454 intotherRegTypeNum =
static_cast<int>(otherRegType);
1456diag::err_hlsl_duplicate_register_annotation)
1460RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
1468 boolSpecifiedSpace) {
1471assert(((isa<VarDecl>(
D) && !isa<HLSLBufferDecl>(
D)) ||
1472(!isa<VarDecl>(
D) && isa<HLSLBufferDecl>(
D))) &&
1473 "expecting VarDecl or HLSLBufferDecl");
1484 if(isa<VarDecl>(TheDecl)) {
1486cast<ValueDecl>(TheDecl)->getType(),
1487diag::err_incomplete_type))
1490StringRef Space =
"space0";
1491StringRef Slot =
"";
1494 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1500StringRef Str =
Loc->Ident->getName();
1504 boolSpecifiedSpace =
false;
1506SpecifiedSpace =
true;
1509 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1515Space =
Loc->Ident->getName();
1516SpaceArgLoc =
Loc->Loc;
1522 unsignedSlotNum = 0;
1523 unsignedSpaceNum = 0;
1526 if(!Slot.empty()) {
1528 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1531 if(RegType == RegisterType::I) {
1532 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1536StringRef SlotNumStr = Slot.substr(1);
1537 if(SlotNumStr.getAsInteger(10, SlotNum)) {
1538 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1543 if(!Space.starts_with(
"space")) {
1544 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1547StringRef SpaceNumStr = Space.substr(5);
1548 if(SpaceNumStr.getAsInteger(10, SpaceNum)) {
1549 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1557HLSLResourceBindingAttr *NewAttr =
1558HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
1560NewAttr->setBinding(RegType, SlotNum, SpaceNum);
1615llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
1619llvm::Triple::EnvironmentType CurrentShaderEnvironment;
1620 unsignedCurrentShaderStageBit;
1625 boolReportOnlyShaderStageIssues;
1628 voidSetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
1629 static_assert(
sizeof(
unsigned) >= 4);
1630assert(HLSLShaderAttr::isValidShaderType(ShaderType));
1631assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
1632 "ShaderType is too big for this bitmap");
1635 unsignedbitmapIndex = ShaderType - llvm::Triple::Pixel;
1636CurrentShaderEnvironment = ShaderType;
1637CurrentShaderStageBit = (1 << bitmapIndex);
1640 voidSetUnknownShaderStageContext() {
1641CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
1642CurrentShaderStageBit = (1 << 31);
1645llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const{
1646 returnCurrentShaderEnvironment;
1649 boolInUnknownShaderStageContext()
const{
1650 returnCurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
1655 unsigned&ScannedStages = ScannedDecls[FD];
1656ScannedStages |= CurrentShaderStageBit;
1659 unsignedGetScannedStages(
const FunctionDecl*FD) {
returnScannedDecls[FD]; }
1661 boolWasAlreadyScannedInCurrentStage(
const FunctionDecl*FD) {
1662 returnWasAlreadyScannedInCurrentStage(GetScannedStages(FD));
1665 boolWasAlreadyScannedInCurrentStage(
unsignedScannerStages) {
1666 returnScannerStages & CurrentShaderStageBit;
1669 static boolNeverBeenScanned(
unsignedScannedStages) {
1670 returnScannedStages == 0;
1675 voidCheckDeclAvailability(
NamedDecl*
D,
constAvailabilityAttr *AA,
1677 constAvailabilityAttr *FindAvailabilityAttr(
const Decl*
D);
1678 boolHasMatchingEnvironmentOrNone(
constAvailabilityAttr *AA);
1681DiagnoseHLSLAvailability(
Sema&SemaRef)
1683CurrentShaderEnvironment(
llvm::Triple::UnknownEnvironment),
1684CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
1690 boolVisitDeclRefExpr(
DeclRefExpr*DRE)
override{
1693HandleFunctionOrMethodRef(FD, DRE);
1697 boolVisitMemberExpr(
MemberExpr*ME)
override{
1700HandleFunctionOrMethodRef(FD, ME);
1705voidDiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl*FD,
1707assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
1708 "expected DeclRefExpr or MemberExpr");
1712 if(FD->
hasBody(FDWithBody)) {
1713 if(!WasAlreadyScannedInCurrentStage(FDWithBody))
1714DeclsToScan.push_back(FDWithBody);
1719 constAvailabilityAttr *AA = FindAvailabilityAttr(FD);
1721CheckDeclAvailability(
1725voidDiagnoseHLSLAvailability::RunOnTranslationUnit(
1734DeclContextsToScan.push_back(TU);
1736 while(!DeclContextsToScan.empty()) {
1737 const DeclContext*DC = DeclContextsToScan.pop_back_val();
1738 for(
auto&
D: DC->
decls()) {
1745 if(llvm::dyn_cast<NamespaceDecl>(
D) || llvm::dyn_cast<ExportDecl>(
D)) {
1746DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(
D));
1756 if(HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
1757SetShaderStageContext(ShaderAttr->getType());
1766 for(
const auto*Redecl : FD->
redecls()) {
1767 if(Redecl->isInExportDeclContext()) {
1774SetUnknownShaderStageContext();
1782voidDiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl*FD) {
1783assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
1784DeclsToScan.push_back(FD);
1786 while(!DeclsToScan.empty()) {
1794 const unsignedScannedStages = GetScannedStages(FD);
1795 if(WasAlreadyScannedInCurrentStage(ScannedStages))
1798ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
1800AddToScannedFunctions(FD);
1801TraverseStmt(FD->
getBody());
1805boolDiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
1806 constAvailabilityAttr *AA) {
1811llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
1812 if(CurrentEnv == llvm::Triple::UnknownEnvironment)
1815llvm::Triple::EnvironmentType AttrEnv =
1816AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
1818 returnCurrentEnv == AttrEnv;
1821constAvailabilityAttr *
1822DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl*
D) {
1823AvailabilityAttr
const*PartialMatch =
nullptr;
1827 for(
const auto*A :
D->
attrs()) {
1828 if(
const auto*Avail = dyn_cast<AvailabilityAttr>(A)) {
1829StringRef AttrPlatform = Avail->getPlatform()->getName();
1830StringRef TargetPlatform =
1834 if(AttrPlatform == TargetPlatform) {
1836 if(HasMatchingEnvironmentOrNone(Avail))
1838PartialMatch = Avail;
1842 returnPartialMatch;
1847voidDiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl*
D,
1848 constAvailabilityAttr *AA,
1861 if(SemaRef.
getLangOpts().HLSLStrictAvailability)
1867 if(ReportOnlyShaderStageIssues)
1873 if(InUnknownShaderStageContext())
1878 boolEnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
1879VersionTuple Introduced = AA->getIntroduced();
1888llvm::StringRef PlatformName(
1891llvm::StringRef CurrentEnvStr =
1892llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
1894llvm::StringRef AttrEnvStr =
1895AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
1896 boolUseEnvironment = !AttrEnvStr.empty();
1898 if(EnvironmentMatches) {
1900<<
Range<<
D<< PlatformName << Introduced.getAsString()
1901<< UseEnvironment << CurrentEnvStr;
1907SemaRef.
Diag(
D->
getLocation(), diag::note_partial_availability_specified_here)
1908<<
D<< PlatformName << Introduced.getAsString()
1910<< UseEnvironment << AttrEnvStr << CurrentEnvStr;
1922TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
1925DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
1938 boolAllBArgAreVectors =
true;
1939 for(
unsignedi = 1; i < TheCall->
getNumArgs(); ++i) {
1943 if(VecTyB ==
nullptr)
1944AllBArgAreVectors &=
false;
1945 if(VecTyA && VecTyB ==
nullptr) {
1948S->
Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1953 if(VecTyA && VecTyB) {
1954 boolretValue =
false;
1955 if(VecTyA->getElementType() != VecTyB->getElementType()) {
1959diag::err_vec_builtin_incompatible_vector)
1964 if(VecTyA->getNumElements() != VecTyB->getNumElements()) {
1968S->
Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
1978 if(VecTyA ==
nullptr&& AllBArgAreVectors) {
1981S->
Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1992S->
Diag(Arg->
getBeginLoc(), diag::err_typecheck_convert_incompatible)
2003 if(Check(PassedType)) {
2006 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
2007S->
Diag(Arg->
getBeginLoc(), diag::err_typecheck_convert_incompatible)
2017 for(
unsignedi = 0; i < TheCall->
getNumArgs(); ++i) {
2028 return!PassedType->hasFloatingRepresentation();
2031checkAllFloatTypes);
2047 unsignedArgIndex) {
2048 auto*Arg = TheCall->
getArg(ArgIndex);
2053S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2059 if(
const auto*VecTy = PassedType->getAs<
VectorType>())
2060 returnVecTy->getElementType()->isDoubleType();
2068 return!PassedType->hasIntegerRepresentation() &&
2069!PassedType->hasFloatingRepresentation();
2072checkAllSignedTypes);
2076 autocheckAllUnsignedTypes = [](
clang::QualTypePassedType) ->
bool{
2077 return!PassedType->hasUnsignedIntegerRepresentation();
2080checkAllUnsignedTypes);
2089TheCall->
setType(ReturnType);
2093 unsignedArgIndex) {
2102diag::err_typecheck_expect_scalar_or_vector)
2103<< ArgType << Scalar;
2110 unsignedArgIndex) {
2116(VTy && VTy->getElementType()->isScalarType()))) {
2118diag::err_typecheck_expect_any_scalar_or_vector)
2135diag::err_typecheck_expect_any_scalar_or_vector)
2148diag::err_typecheck_call_different_arg_types)
2178diag::err_typecheck_call_different_arg_types)
2189diag::err_typecheck_vector_lengths_not_equal)
2208diag::err_typecheck_expect_hlsl_resource)
2212 if(Check && Check(ResTy)) {
2214diag::err_invalid_hlsl_resource_type)
2224 switch(BuiltinID) {
2225 caseBuiltin::BI__builtin_hlsl_resource_getpointer: {
2234 QualTypeContainedTy = ResourceTy->getContainedType();
2241 caseBuiltin::BI__builtin_hlsl_all:
2242 caseBuiltin::BI__builtin_hlsl_any: {
2247 caseBuiltin::BI__builtin_hlsl_asdouble: {
2256 caseBuiltin::BI__builtin_hlsl_elementwise_clamp: {
2267 caseBuiltin::BI__builtin_hlsl_cross: {
2275 intNumElementsArg1 =
2277 intNumElementsArg2 =
2280 if(NumElementsArg1 != 3) {
2281 intLessOrMore = NumElementsArg1 > 3 ? 1 : 0;
2283diag::err_vector_incorrect_num_elements)
2284<< LessOrMore << 3 << NumElementsArg1 <<
1;
2287 if(NumElementsArg2 != 3) {
2288 intLessOrMore = NumElementsArg2 > 3 ? 1 : 0;
2291diag::err_vector_incorrect_num_elements)
2292<< LessOrMore << 3 << NumElementsArg2 <<
1;
2302 caseBuiltin::BI__builtin_hlsl_dot: {
2313 caseBuiltin::BI__builtin_hlsl_elementwise_firstbithigh:
2314 caseBuiltin::BI__builtin_hlsl_elementwise_firstbitlow: {
2325EltTy = VecTy->getElementType();
2327VecTy->getVectorKind());
2339 caseBuiltin::BI__builtin_hlsl_select: {
2348 if(VTy && VTy->getElementType()->isBooleanType() &&
2353 caseBuiltin::BI__builtin_hlsl_elementwise_saturate:
2354 caseBuiltin::BI__builtin_hlsl_elementwise_rcp: {
2361 caseBuiltin::BI__builtin_hlsl_elementwise_degrees:
2362 caseBuiltin::BI__builtin_hlsl_elementwise_radians:
2363 caseBuiltin::BI__builtin_hlsl_elementwise_rsqrt:
2364 caseBuiltin::BI__builtin_hlsl_elementwise_frac: {
2371 caseBuiltin::BI__builtin_hlsl_elementwise_isinf: {
2379 caseBuiltin::BI__builtin_hlsl_lerp: {
2390 caseBuiltin::BI__builtin_hlsl_mad: {
2401 caseBuiltin::BI__builtin_hlsl_normalize: {
2413 caseBuiltin::BI__builtin_hlsl_elementwise_sign: {
2421 caseBuiltin::BI__builtin_hlsl_step: {
2433 caseBuiltin::BI__builtin_hlsl_wave_active_max:
2434 caseBuiltin::BI__builtin_hlsl_wave_active_sum: {
2445TheCall->
setType(ArgTyExpr);
2450 caseBuiltin::BI__builtin_elementwise_bitreverse: {
2455 caseBuiltin::BI__builtin_hlsl_wave_read_lane_at: {
2461 QualTypeArgTyIndex = Index.get()->getType();
2464diag::err_typecheck_convert_incompatible)
2475TheCall->
setType(ArgTyExpr);
2478 caseBuiltin::BI__builtin_hlsl_wave_get_lane_index: {
2483 caseBuiltin::BI__builtin_hlsl_elementwise_splitdouble: {
2499 caseBuiltin::BI__builtin_hlsl_elementwise_clip: {
2507 caseBuiltin::BI__builtin_elementwise_acos:
2508 caseBuiltin::BI__builtin_elementwise_asin:
2509 caseBuiltin::BI__builtin_elementwise_atan:
2510 caseBuiltin::BI__builtin_elementwise_atan2:
2511 caseBuiltin::BI__builtin_elementwise_ceil:
2512 caseBuiltin::BI__builtin_elementwise_cos:
2513 caseBuiltin::BI__builtin_elementwise_cosh:
2514 caseBuiltin::BI__builtin_elementwise_exp:
2515 caseBuiltin::BI__builtin_elementwise_exp2:
2516 caseBuiltin::BI__builtin_elementwise_floor:
2517 caseBuiltin::BI__builtin_elementwise_fmod:
2518 caseBuiltin::BI__builtin_elementwise_log:
2519 caseBuiltin::BI__builtin_elementwise_log2:
2520 caseBuiltin::BI__builtin_elementwise_log10:
2521 caseBuiltin::BI__builtin_elementwise_pow:
2522 caseBuiltin::BI__builtin_elementwise_roundeven:
2523 caseBuiltin::BI__builtin_elementwise_sin:
2524 caseBuiltin::BI__builtin_elementwise_sinh:
2525 caseBuiltin::BI__builtin_elementwise_sqrt:
2526 caseBuiltin::BI__builtin_elementwise_tan:
2527 caseBuiltin::BI__builtin_elementwise_tanh:
2528 caseBuiltin::BI__builtin_elementwise_trunc: {
2533 caseBuiltin::BI__builtin_hlsl_buffer_update_counter: {
2535 return!(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
2536ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
2544std::optional<llvm::APSInt> Offset =
2546 if(!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
2548diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
2561WorkList.push_back(BaseTy);
2562 while(!WorkList.empty()) {
2564 T=
T.getCanonicalType().getUnqualifiedType();
2565assert(!isa<MatrixType>(
T) &&
"Matrix types not yet supported in HLSL");
2566 if(
const auto*AT = dyn_cast<ConstantArrayType>(
T)) {
2574 for(uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
2575List.insert(List.end(), ElementFields.begin(), ElementFields.end());
2580 if(
const auto*VT = dyn_cast<VectorType>(
T)) {
2581List.insert(List.end(), VT->getNumElements(), VT->getElementType());
2584 if(
const auto*RT = dyn_cast<RecordType>(
T)) {
2587List.push_back(
T);
2596 for(
const auto*FD : RD->
fields())
2597FieldTypes.push_back(FD->
getType());
2599std::reverse(FieldTypes.begin(), FieldTypes.end());
2600WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2606 for(
const auto&
Base: CXXD->
bases())
2607FieldTypes.push_back(
Base.getType());
2608std::reverse(FieldTypes.begin(), FieldTypes.end());
2609WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2613List.push_back(
T);
2637 intArraySize = VT->getNumElements();
2642 QualTypeElTy = VT->getElementType();
2671 returnllvm::equal(T1Types, T2Types,
2682 boolHadError =
false;
2684 for(
unsignedi = 0, e = New->
getNumParams(); i != e; ++i) {
2692 const auto*NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
2693 unsignedNSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
2694 const auto*ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
2695 unsignedOSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
2697 if(NSpellingIdx != OSpellingIdx) {
2699diag::err_hlsl_param_qualifier_mismatch)
2700<< NDAttr << NewParam;
2710assert(Param->
hasAttr<HLSLParamModifierAttr>() &&
2711 "We should not get here without a parameter modifier expression");
2712 const auto*
Attr= Param->
getAttr<HLSLParamModifierAttr>();
2719<< Arg << (IsInOut ? 1 : 0);
2732<< Arg << (IsInOut ? 1 : 0);
2750 auto*OpV =
new(Ctx)
2756tok::equal, ArgOpV, OpV);
2760 Expr*Writeback = Res.
get();
2772 "Pointer and reference types cannot be inout or out parameters");
2784diag::err_typecheck_decl_incomplete_type)) {
2791collectResourcesOnVarDecl(VD);
2794processExplicitBindingsOnDecl(VD);
2800voidSemaHLSL::collectResourcesOnVarDecl(
VarDecl*VD) {
2802 "expected global variable that contains HLSL resource");
2805 if(
const HLSLBufferDecl*CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
2806 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
2807? ResourceClass::CBuffer
2808: ResourceClass::SRV);
2823 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
2828 if(
const RecordType*RT = dyn_cast<RecordType>(Ty))
2829collectResourcesOnUserRecordDecl(VD, RT);
2835voidSemaHLSL::processExplicitBindingsOnDecl(
VarDecl*VD) {
2839HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
2844assert(RT != RegisterType::I &&
"invalid or obsolete register type should " 2845 "never have an attribute created");
2847 if(RT == RegisterType::C) {
2848 if(
Bindings.hasBindingInfoForDecl(VD))
2850diag::warn_hlsl_user_defined_type_missing_member)
2851<<
static_cast<int>(RT);
2864diag::warn_hlsl_user_defined_type_missing_member)
2865<<
static_cast<int>(RT);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static bool isResourceRecordType(const clang::Type *Ty)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
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 isZeroSizedArray(const ConstantArrayType *CAT)
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 FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
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 CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
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 CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
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)
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
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 various enumerations that describe declaration and type specifiers.
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....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
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)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
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 base class of a C++ class.
Represents a C++ struct/union/class.
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.
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr, bool DelayTypeCreation=false)
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
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.
bool isZeroSize() const
Return true if the size is zero.
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.
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.
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()
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
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 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 ...
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
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.
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.
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
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.
const Type * getTypeForDecl() const
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
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isBooleanType() const
bool isIncompleteArrayType() const
bool isConstantArrayType() const
bool isArithmeticType() const
bool isHLSLBuiltinIntangibleType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
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<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
void setType(QualType newType)
Represents a variable declaration or definition.
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
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
The JSON file list parser is used to communicate input to InstallAPI.
@ ICIS_NoInit
No in-class initializer.
@ 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.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4