@@ -40,14 +40,66 @@ static bool reportError(LLVMContext *Ctx, Twine Message,
4040 return true ;
4141}
4242
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+
4358static bool parseRootFlags (LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
4459 MDNode *RootFlagNode) {
4560
4661 if (RootFlagNode->getNumOperands () != 2 )
4762 return reportError (Ctx, " Invalid format for RootFlag Element" );
4863
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);
51103
52104 return false ;
53105}
@@ -62,12 +114,16 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
62114 RootSignatureElementKind ElementKind =
63115 StringSwitch<RootSignatureElementKind>(ElementText->getString ())
64116 .Case (" RootFlags" , RootSignatureElementKind::RootFlags)
117+ .Case (" RootConstants" , RootSignatureElementKind::RootConstants)
65118 .Default (RootSignatureElementKind::Error);
66119
67120 switch (ElementKind) {
68121
69122 case RootSignatureElementKind::RootFlags:
70123 return parseRootFlags (Ctx, RSD, Element);
124+ case RootSignatureElementKind::RootConstants:
125+ return parseRootConstants (Ctx, RSD, Element);
126+ break ;
71127 case RootSignatureElementKind::Error:
72128 return reportError (Ctx, " Invalid Root Signature Element: " +
73129 ElementText->getString ());
@@ -94,10 +150,29 @@ static bool parse(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
94150
95151static bool verifyRootFlag (uint32_t Flags) { return (Flags & ~0xfff ) == 0 ; }
96152
153+ static bool verifyVersion (uint32_t Version) {
154+ return (Version == 1 || Version == 2 );
155+ }
156+
97157static bool validate (LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
158+
159+ if (!verifyVersion (RSD.Version )) {
160+ return reportValueError (Ctx, " Version" , RSD.Version );
161+ }
162+
98163 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" );
100174 }
175+
101176 return false ;
102177}
103178
@@ -166,6 +241,10 @@ analyzeModule(Module &M) {
166241 }
167242
168243 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);
169248
170249 if (parse (Ctx, RSD, RootElementListNode) || validate (Ctx, RSD)) {
171250 return RSDMap;
@@ -192,7 +271,6 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
192271 SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> &RSDMap =
193272 AM.getResult <RootSignatureAnalysis>(M);
194273
195- const size_t RSHSize = sizeof (dxbc::RootSignatureHeader);
196274 OS << " Root Signature Definitions"
197275 << " \n " ;
198276 uint8_t Space = 0 ;
@@ -205,14 +283,33 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
205283
206284 // start root signature header
207285 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+
216313 Space--;
217314 // end root signature header
218315 }
0 commit comments