@@ -40,14 +40,66 @@ static bool reportError(LLVMContext *Ctx, Twine Message,
40
40
return true ;
41
41
}
42
42
43
+ static bool reportValueError (LLVMContext *Ctx, Twine ParamName,
44
+ uint32_t Value) {
45
+ Ctx->diagnose (DiagnosticInfoGeneric (
46
+ " Invalid value for " + ParamName + " : " + Twine (Value), DS_Error));
47
+ return true ;
48
+ }
49
+
50
+ static std::optional<uint32_t > extractMdIntValue (MDNode *Node,
51
+ unsigned int OpId) {
52
+ if (auto *CI =
53
+ mdconst::dyn_extract<ConstantInt>(Node->getOperand (OpId).get ()))
54
+ return CI->getZExtValue ();
55
+ return std::nullopt;
56
+ }
57
+
43
58
static bool parseRootFlags (LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
44
59
MDNode *RootFlagNode) {
45
60
46
61
if (RootFlagNode->getNumOperands () != 2 )
47
62
return reportError (Ctx, " Invalid format for RootFlag Element" );
48
63
49
- auto *Flag = mdconst::extract<ConstantInt>(RootFlagNode->getOperand (1 ));
50
- RSD.Flags = Flag->getZExtValue ();
64
+ if (std::optional<uint32_t > Val = extractMdIntValue (RootFlagNode, 1 ))
65
+ RSD.Flags = *Val;
66
+ else
67
+ return reportError (Ctx, " Invalid value for RootFlag" );
68
+
69
+ return false ;
70
+ }
71
+
72
+ static bool parseRootConstants (LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
73
+ MDNode *RootConstantNode) {
74
+
75
+ if (RootConstantNode->getNumOperands () != 5 )
76
+ return reportError (Ctx, " Invalid format for RootConstants Element" );
77
+
78
+ mcdxbc::RootParameter NewParameter;
79
+ NewParameter.Header .ParameterType =
80
+ llvm::to_underlying (dxbc::RootParameterType::Constants32Bit);
81
+
82
+ if (std::optional<uint32_t > Val = extractMdIntValue (RootConstantNode, 1 ))
83
+ NewParameter.Header .ShaderVisibility = *Val;
84
+ else
85
+ return reportError (Ctx, " Invalid value for ShaderVisibility" );
86
+
87
+ if (std::optional<uint32_t > Val = extractMdIntValue (RootConstantNode, 2 ))
88
+ NewParameter.Constants .ShaderRegister = *Val;
89
+ else
90
+ return reportError (Ctx, " Invalid value for ShaderRegister" );
91
+
92
+ if (std::optional<uint32_t > Val = extractMdIntValue (RootConstantNode, 3 ))
93
+ NewParameter.Constants .RegisterSpace = *Val;
94
+ else
95
+ return reportError (Ctx, " Invalid value for RegisterSpace" );
96
+
97
+ if (std::optional<uint32_t > Val = extractMdIntValue (RootConstantNode, 4 ))
98
+ NewParameter.Constants .Num32BitValues = *Val;
99
+ else
100
+ return reportError (Ctx, " Invalid value for Num32BitValues" );
101
+
102
+ RSD.Parameters .push_back (NewParameter);
51
103
52
104
return false ;
53
105
}
@@ -62,12 +114,16 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
62
114
RootSignatureElementKind ElementKind =
63
115
StringSwitch<RootSignatureElementKind>(ElementText->getString ())
64
116
.Case (" RootFlags" , RootSignatureElementKind::RootFlags)
117
+ .Case (" RootConstants" , RootSignatureElementKind::RootConstants)
65
118
.Default (RootSignatureElementKind::Error);
66
119
67
120
switch (ElementKind) {
68
121
69
122
case RootSignatureElementKind::RootFlags:
70
123
return parseRootFlags (Ctx, RSD, Element);
124
+ case RootSignatureElementKind::RootConstants:
125
+ return parseRootConstants (Ctx, RSD, Element);
126
+ break ;
71
127
case RootSignatureElementKind::Error:
72
128
return reportError (Ctx, " Invalid Root Signature Element: " +
73
129
ElementText->getString ());
@@ -94,10 +150,29 @@ static bool parse(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
94
150
95
151
static bool verifyRootFlag (uint32_t Flags) { return (Flags & ~0xfff ) == 0 ; }
96
152
153
+ static bool verifyVersion (uint32_t Version) {
154
+ return (Version == 1 || Version == 2 );
155
+ }
156
+
97
157
static bool validate (LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
158
+
159
+ if (!verifyVersion (RSD.Version )) {
160
+ return reportValueError (Ctx, " Version" , RSD.Version );
161
+ }
162
+
98
163
if (!verifyRootFlag (RSD.Flags )) {
99
- return reportError (Ctx, " Invalid Root Signature flag value" );
164
+ return reportValueError (Ctx, " RootFlags" , RSD.Flags );
165
+ }
166
+
167
+ for (const mcdxbc::RootParameter &P : RSD.Parameters ) {
168
+ if (!dxbc::isValidShaderVisibility (P.Header .ShaderVisibility ))
169
+ return reportValueError (Ctx, " ShaderVisibility" ,
170
+ P.Header .ShaderVisibility );
171
+
172
+ assert (dxbc::isValidParameterType (P.Header .ParameterType ) &&
173
+ " Invalid value for ParameterType" );
100
174
}
175
+
101
176
return false ;
102
177
}
103
178
@@ -166,6 +241,10 @@ analyzeModule(Module &M) {
166
241
}
167
242
168
243
mcdxbc::RootSignatureDesc RSD;
244
+ // Clang emits the root signature data in dxcontainer following a specific
245
+ // sequence. First the header, then the root parameters. So the header
246
+ // offset will always equal to the header size.
247
+ RSD.RootParameterOffset = sizeof (dxbc::RootSignatureHeader);
169
248
170
249
if (parse (Ctx, RSD, RootElementListNode) || validate (Ctx, RSD)) {
171
250
return RSDMap;
@@ -192,7 +271,6 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
192
271
SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> &RSDMap =
193
272
AM.getResult <RootSignatureAnalysis>(M);
194
273
195
- const size_t RSHSize = sizeof (dxbc::RootSignatureHeader);
196
274
OS << " Root Signature Definitions"
197
275
<< " \n " ;
198
276
uint8_t Space = 0 ;
@@ -205,14 +283,33 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
205
283
206
284
// start root signature header
207
285
Space++;
208
- OS << indent (Space) << " Flags: " << format_hex (RS.Flags , 8 ) << " :\n " ;
209
- OS << indent (Space) << " Version: " << RS.Version << " :\n " ;
210
- OS << indent (Space) << " NumParameters: " << RS.Parameters .size () << " :\n " ;
211
- OS << indent (Space) << " RootParametersOffset: " << RSHSize << " :\n " ;
212
- OS << indent (Space) << " NumStaticSamplers: " << 0 << " :\n " ;
213
- OS << indent (Space)
214
- << " StaticSamplersOffset: " << RSHSize + RS.Parameters .size_in_bytes ()
215
- << " :\n " ;
286
+ OS << indent (Space) << " Flags: " << format_hex (RS.Flags , 8 ) << " \n " ;
287
+ OS << indent (Space) << " Version: " << RS.Version << " \n " ;
288
+ OS << indent (Space) << " RootParametersOffset: " << RS.RootParameterOffset
289
+ << " \n " ;
290
+ OS << indent (Space) << " NumParameters: " << RS.Parameters .size () << " \n " ;
291
+ Space++;
292
+ for (auto const &P : RS.Parameters ) {
293
+ OS << indent (Space) << " - Parameter Type: " << P.Header .ParameterType
294
+ << " \n " ;
295
+ OS << indent (Space + 2 )
296
+ << " Shader Visibility: " << P.Header .ShaderVisibility << " \n " ;
297
+ switch (P.Header .ParameterType ) {
298
+ case llvm::to_underlying (dxbc::RootParameterType::Constants32Bit):
299
+ OS << indent (Space + 2 )
300
+ << " Register Space: " << P.Constants .RegisterSpace << " \n " ;
301
+ OS << indent (Space + 2 )
302
+ << " Shader Register: " << P.Constants .ShaderRegister << " \n " ;
303
+ OS << indent (Space + 2 )
304
+ << " Num 32 Bit Values: " << P.Constants .Num32BitValues << " \n " ;
305
+ break ;
306
+ }
307
+ }
308
+ Space--;
309
+ OS << indent (Space) << " NumStaticSamplers: " << 0 << " \n " ;
310
+ OS << indent (Space) << " StaticSamplersOffset: " << RS.StaticSamplersOffset
311
+ << " \n " ;
312
+
216
313
Space--;
217
314
// end root signature header
218
315
}
0 commit comments