@@ -1064,27 +1064,33 @@ SemaHLSL::ActOnStartRootSignatureDecl(StringRef Signature) {
1064
1064
1065
1065
void SemaHLSL::ActOnFinishRootSignatureDecl (
1066
1066
SourceLocation Loc, IdentifierInfo *DeclIdent,
1067
- SmallVector<llvm::hlsl::rootsig::RootElement> &Elements) {
1067
+ ArrayRef<hlsl::RootSignatureElement> RootElements) {
1068
+
1069
+ if (handleRootSignatureElements (RootElements))
1070
+ return ;
1071
+
1072
+ SmallVector<llvm::hlsl::rootsig::RootElement> Elements;
1073
+ for (auto &RootSigElement : RootElements)
1074
+ Elements.push_back (RootSigElement.getElement ());
1068
1075
1069
1076
auto *SignatureDecl = HLSLRootSignatureDecl::Create (
1070
1077
SemaRef.getASTContext (), /* DeclContext=*/ SemaRef.CurContext , Loc,
1071
1078
DeclIdent, SemaRef.getLangOpts ().HLSLRootSigVer , Elements);
1072
1079
1073
- if (handleRootSignatureDecl (SignatureDecl, Loc))
1074
- return ;
1075
-
1076
1080
SignatureDecl->setImplicit ();
1077
1081
SemaRef.PushOnScopeChains (SignatureDecl, SemaRef.getCurScope ());
1078
1082
}
1079
1083
1080
- bool SemaHLSL::handleRootSignatureDecl (HLSLRootSignatureDecl *D,
1081
- SourceLocation Loc ) {
1084
+ bool SemaHLSL::handleRootSignatureElements (
1085
+ ArrayRef<hlsl::RootSignatureElement> Elements ) {
1082
1086
using RangeInfo = llvm::hlsl::rootsig::RangeInfo;
1083
1087
using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges;
1088
+ using InfoPairT = std::pair<RangeInfo, const hlsl::RootSignatureElement *>;
1084
1089
1085
1090
// 1. Collect RangeInfos
1086
- llvm::SmallVector<RangeInfo> Infos;
1087
- for (const llvm::hlsl::rootsig::RootElement &Elem : D->getRootElements ()) {
1091
+ llvm::SmallVector<InfoPairT> InfoPairs;
1092
+ for (const hlsl::RootSignatureElement &RootSigElem : Elements) {
1093
+ const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement ();
1088
1094
if (const auto *Descriptor =
1089
1095
std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1090
1096
RangeInfo Info;
@@ -1095,7 +1101,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
1095
1101
llvm::dxil::ResourceClass (llvm::to_underlying (Descriptor->Type ));
1096
1102
Info.Space = Descriptor->Space ;
1097
1103
Info.Visibility = Descriptor->Visibility ;
1098
- Infos.push_back (Info);
1104
+
1105
+ InfoPairs.push_back ({Info, &RootSigElem});
1099
1106
} else if (const auto *Constants =
1100
1107
std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1101
1108
RangeInfo Info;
@@ -1105,7 +1112,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
1105
1112
Info.Class = llvm::dxil::ResourceClass::CBuffer;
1106
1113
Info.Space = Constants->Space ;
1107
1114
Info.Visibility = Constants->Visibility ;
1108
- Infos.push_back (Info);
1115
+
1116
+ InfoPairs.push_back ({Info, &RootSigElem});
1109
1117
} else if (const auto *Sampler =
1110
1118
std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1111
1119
RangeInfo Info;
@@ -1115,7 +1123,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
1115
1123
Info.Class = llvm::dxil::ResourceClass::Sampler;
1116
1124
Info.Space = Sampler->Space ;
1117
1125
Info.Visibility = Sampler->Visibility ;
1118
- Infos.push_back (Info);
1126
+
1127
+ InfoPairs.push_back ({Info, &RootSigElem});
1119
1128
} else if (const auto *Clause =
1120
1129
std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1121
1130
&Elem)) {
@@ -1129,38 +1138,83 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
1129
1138
1130
1139
Info.Class = Clause->Type ;
1131
1140
Info.Space = Clause->Space ;
1141
+
1132
1142
// Note: Clause does not hold the visibility this will need to
1133
- Infos .push_back (Info);
1143
+ InfoPairs .push_back ({ Info, &RootSigElem} );
1134
1144
} else if (const auto *Table =
1135
1145
std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1136
1146
// Table holds the Visibility of all owned Clauses in Table, so iterate
1137
1147
// owned Clauses and update their corresponding RangeInfo
1138
- assert (Table->NumClauses <= Infos .size () && " RootElement" );
1148
+ assert (Table->NumClauses <= InfoPairs .size () && " RootElement" );
1139
1149
// The last Table->NumClauses elements of Infos are the owned Clauses
1140
1150
// generated RangeInfo
1141
1151
auto TableInfos =
1142
- MutableArrayRef<RangeInfo>(Infos ).take_back (Table->NumClauses );
1143
- for (RangeInfo &Info : TableInfos)
1144
- Info .Visibility = Table->Visibility ;
1152
+ MutableArrayRef<InfoPairT>(InfoPairs ).take_back (Table->NumClauses );
1153
+ for (InfoPairT &Pair : TableInfos)
1154
+ Pair. first .Visibility = Table->Visibility ;
1145
1155
}
1146
1156
}
1147
1157
1148
- // Helper to report diagnostics
1149
- auto ReportOverlap = [this , Loc](OverlappingRanges Overlap) {
1158
+ // 2. Sort with the RangeInfo <operator to prepare it for findOverlapping
1159
+ llvm::sort (InfoPairs,
1160
+ [](InfoPairT A, InfoPairT B) { return A.first < B.first ; });
1161
+
1162
+ llvm::SmallVector<RangeInfo> Infos;
1163
+ for (const InfoPairT &Pair : InfoPairs)
1164
+ Infos.push_back (Pair.first );
1165
+
1166
+ // Helpers to report diagnostics
1167
+ uint32_t DuplicateCounter = 0 ;
1168
+ using ElemPair = std::pair<const hlsl::RootSignatureElement *,
1169
+ const hlsl::RootSignatureElement *>;
1170
+ auto GetElemPair = [&Infos, &InfoPairs, &DuplicateCounter](
1171
+ OverlappingRanges Overlap) -> ElemPair {
1172
+ // Given we sorted the InfoPairs (and by implication) Infos, and,
1173
+ // that Overlap.B is the item retrieved from the ResourceRange. Then it is
1174
+ // guarenteed that Overlap.B <= Overlap.A.
1175
+ //
1176
+ // So we will find Overlap.B first and then continue to find Overlap.A
1177
+ // after
1178
+ auto InfoB = std::lower_bound (Infos.begin (), Infos.end (), *Overlap.B );
1179
+ auto DistB = std::distance (Infos.begin (), InfoB);
1180
+ auto PairB = InfoPairs.begin ();
1181
+ std::advance (PairB, DistB);
1182
+
1183
+ auto InfoA = std::lower_bound (InfoB, Infos.end (), *Overlap.A );
1184
+ // Similarily, from the property that we have sorted the RangeInfos,
1185
+ // all duplicates will be processed one after the other. So
1186
+ // DuplicateCounter can be re-used for each set of duplicates we
1187
+ // encounter as we handle incoming errors
1188
+ DuplicateCounter = InfoA == InfoB ? DuplicateCounter + 1 : 0 ;
1189
+ auto DistA = std::distance (InfoB, InfoA) + DuplicateCounter;
1190
+ auto PairA = PairB;
1191
+ std::advance (PairA, DistA);
1192
+
1193
+ return {PairA->second , PairB->second };
1194
+ };
1195
+
1196
+ auto ReportOverlap = [this , &GetElemPair](OverlappingRanges Overlap) {
1197
+ auto Pair = GetElemPair (Overlap);
1150
1198
const RangeInfo *Info = Overlap.A ;
1199
+ const hlsl::RootSignatureElement *Elem = Pair.first ;
1151
1200
const RangeInfo *OInfo = Overlap.B ;
1201
+
1152
1202
auto CommonVis = Info->Visibility == llvm::dxbc::ShaderVisibility::All
1153
1203
? OInfo->Visibility
1154
1204
: Info->Visibility ;
1155
- this ->Diag (Loc , diag::err_hlsl_resource_range_overlap)
1205
+ this ->Diag (Elem-> getLocation () , diag::err_hlsl_resource_range_overlap)
1156
1206
<< llvm::to_underlying (Info->Class ) << Info->LowerBound
1157
1207
<< /* unbounded=*/ (Info->UpperBound == RangeInfo::Unbounded)
1158
1208
<< Info->UpperBound << llvm::to_underlying (OInfo->Class )
1159
1209
<< OInfo->LowerBound
1160
1210
<< /* unbounded=*/ (OInfo->UpperBound == RangeInfo::Unbounded)
1161
1211
<< OInfo->UpperBound << Info->Space << CommonVis;
1212
+
1213
+ const hlsl::RootSignatureElement *OElem = Pair.second ;
1214
+ this ->Diag (OElem->getLocation (), diag::note_hlsl_resource_range_here);
1162
1215
};
1163
1216
1217
+ // 3. Invoke find overlapping ranges
1164
1218
llvm::SmallVector<OverlappingRanges> Overlaps =
1165
1219
llvm::hlsl::rootsig::findOverlappingRanges (Infos);
1166
1220
for (OverlappingRanges Overlap : Overlaps)
0 commit comments