|
43 | 43 | #include "llvm/Support/Casting.h" |
44 | 44 | #include "llvm/Support/DXILABI.h" |
45 | 45 | #include "llvm/Support/ErrorHandling.h" |
| 46 | +#include "llvm/Support/FormatVariadic.h" |
46 | 47 | #include "llvm/TargetParser/Triple.h" |
| 48 | +#include <cmath> |
47 | 49 | #include <cstddef> |
48 | 50 | #include <iterator> |
49 | 51 | #include <utility> |
@@ -1083,6 +1085,92 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( |
1083 | 1085 |
|
1084 | 1086 | bool SemaHLSL::handleRootSignatureElements( |
1085 | 1087 | ArrayRef<hlsl::RootSignatureElement> Elements) { |
| 1088 | + // Define some common error handling functions |
| 1089 | + bool HadError = false; |
| 1090 | + auto ReportError = [this, &HadError](SourceLocation Loc, uint32_t LowerBound, |
| 1091 | + uint32_t UpperBound) { |
| 1092 | + HadError = true; |
| 1093 | + this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value) |
| 1094 | + << LowerBound << UpperBound; |
| 1095 | + }; |
| 1096 | + |
| 1097 | + auto ReportFloatError = [this, &HadError](SourceLocation Loc, |
| 1098 | + float LowerBound, |
| 1099 | + float UpperBound) { |
| 1100 | + HadError = true; |
| 1101 | + this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value) |
| 1102 | + << llvm::formatv("{0:f}", LowerBound).sstr<6>() |
| 1103 | + << llvm::formatv("{0:f}", UpperBound).sstr<6>(); |
| 1104 | + }; |
| 1105 | + |
| 1106 | + auto VerifyRegister = [ReportError](SourceLocation Loc, uint32_t Register) { |
| 1107 | + if (!llvm::hlsl::rootsig::verifyRegisterValue(Register)) |
| 1108 | + ReportError(Loc, 0, 0xfffffffe); |
| 1109 | + }; |
| 1110 | + |
| 1111 | + auto VerifySpace = [ReportError](SourceLocation Loc, uint32_t Space) { |
| 1112 | + if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space)) |
| 1113 | + ReportError(Loc, 0, 0xffffffef); |
| 1114 | + }; |
| 1115 | + |
| 1116 | + const uint32_t Version = |
| 1117 | + llvm::to_underlying(SemaRef.getLangOpts().HLSLRootSigVer); |
| 1118 | + const uint32_t VersionEnum = Version - 1; |
| 1119 | + auto ReportFlagError = [this, &HadError, VersionEnum](SourceLocation Loc) { |
| 1120 | + HadError = true; |
| 1121 | + this->Diag(Loc, diag::err_hlsl_invalid_rootsig_flag) |
| 1122 | + << /*version minor*/ VersionEnum; |
| 1123 | + }; |
| 1124 | + |
| 1125 | + // Iterate through the elements and do basic validations |
| 1126 | + for (const hlsl::RootSignatureElement &RootSigElem : Elements) { |
| 1127 | + SourceLocation Loc = RootSigElem.getLocation(); |
| 1128 | + const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement(); |
| 1129 | + if (const auto *Descriptor = |
| 1130 | + std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) { |
| 1131 | + VerifyRegister(Loc, Descriptor->Reg.Number); |
| 1132 | + VerifySpace(Loc, Descriptor->Space); |
| 1133 | + |
| 1134 | + if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag( |
| 1135 | + Version, llvm::to_underlying(Descriptor->Flags))) |
| 1136 | + ReportFlagError(Loc); |
| 1137 | + } else if (const auto *Constants = |
| 1138 | + std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) { |
| 1139 | + VerifyRegister(Loc, Constants->Reg.Number); |
| 1140 | + VerifySpace(Loc, Constants->Space); |
| 1141 | + } else if (const auto *Sampler = |
| 1142 | + std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) { |
| 1143 | + VerifyRegister(Loc, Sampler->Reg.Number); |
| 1144 | + VerifySpace(Loc, Sampler->Space); |
| 1145 | + |
| 1146 | + assert(!std::isnan(Sampler->MaxLOD) && !std::isnan(Sampler->MinLOD) && |
| 1147 | + "By construction, parseFloatParam can't produce a NaN from a " |
| 1148 | + "float_literal token"); |
| 1149 | + |
| 1150 | + if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy)) |
| 1151 | + ReportError(Loc, 0, 16); |
| 1152 | + if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias)) |
| 1153 | + ReportFloatError(Loc, -16.f, 15.99); |
| 1154 | + } else if (const auto *Clause = |
| 1155 | + std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>( |
| 1156 | + &Elem)) { |
| 1157 | + VerifyRegister(Loc, Clause->Reg.Number); |
| 1158 | + VerifySpace(Loc, Clause->Space); |
| 1159 | + |
| 1160 | + if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) { |
| 1161 | + // NumDescriptor could techincally be ~0u but that is reserved for |
| 1162 | + // unbounded, so the diagnostic will not report that as a valid int |
| 1163 | + // value |
| 1164 | + ReportError(Loc, 1, 0xfffffffe); |
| 1165 | + } |
| 1166 | + |
| 1167 | + if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag( |
| 1168 | + Version, llvm::to_underlying(Clause->Type), |
| 1169 | + llvm::to_underlying(Clause->Flags))) |
| 1170 | + ReportFlagError(Loc); |
| 1171 | + } |
| 1172 | + } |
| 1173 | + |
1086 | 1174 | using RangeInfo = llvm::hlsl::rootsig::RangeInfo; |
1087 | 1175 | using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges; |
1088 | 1176 | using InfoPairT = std::pair<RangeInfo, const hlsl::RootSignatureElement *>; |
@@ -1130,7 +1218,10 @@ bool SemaHLSL::handleRootSignatureElements( |
1130 | 1218 | &Elem)) { |
1131 | 1219 | RangeInfo Info; |
1132 | 1220 | Info.LowerBound = Clause->Reg.Number; |
1133 | | - assert(0 < Clause->NumDescriptors && "Verified as part of TODO(#129940)"); |
| 1221 | + // Relevant error will have already been reported above and needs to be |
| 1222 | + // fixed before we can conduct range analysis, so shortcut error return |
| 1223 | + if (Clause->NumDescriptors == 0) |
| 1224 | + return true; |
1134 | 1225 | Info.UpperBound = Clause->NumDescriptors == RangeInfo::Unbounded |
1135 | 1226 | ? RangeInfo::Unbounded |
1136 | 1227 | : Info.LowerBound + Clause->NumDescriptors - |
|
0 commit comments