@@ -38,6 +38,148 @@ bool Parser::ParseRootFlags() {
3838 return false ;
3939}
4040
41+ bool Parser::ParseRootParameter () {
42+ RootParameter Parameter;
43+ Parameter.Type = llvm::StringSwitch<RootType>(Token)
44+ .Case (" CBV" , RootType::CBV)
45+ .Case (" SRV" , RootType::SRV)
46+ .Case (" UAV" , RootType::UAV)
47+ .Case (" RootConstants" , RootType::Constants);
48+ // Will never reach here as Token was just verified in dispatch
49+
50+ // Remove any whitespace
51+ Buffer = Buffer.drop_while (isspace);
52+
53+ // Retreive mandatory num32BitConstant arg for RootConstants
54+ if (Parameter.Type == RootType::Constants) {
55+ if (!Buffer.consume_front (" num32BitConstants" ))
56+ return ReportError ();
57+
58+ if (ParseAssign ())
59+ return ReportError ();
60+
61+ if (ParseUnsignedInt (Parameter.Num32BitConstants ))
62+ return ReportError ();
63+
64+ if (ParseOptComma ())
65+ return ReportError ();
66+ }
67+
68+ // Retrieve mandatory register
69+ if (ParseRegister (Parameter.Register ))
70+ return true ;
71+
72+ if (ParseOptComma ())
73+ return ReportError ();
74+
75+ // Parse common optional space arg
76+ if (Buffer.consume_front (" space" )) {
77+ if (ParseAssign ())
78+ return ReportError ();
79+
80+ if (ParseUnsignedInt (Parameter.Space ))
81+ return ReportError ();
82+
83+ if (ParseOptComma ())
84+ return ReportError ();
85+ }
86+
87+ // Parse common optional visibility arg
88+ if (Buffer.consume_front (" visibility" )) {
89+ if (ParseAssign ())
90+ return ReportError ();
91+
92+ if (ParseVisibility (Parameter.Visibility ))
93+ return ReportError ();
94+
95+ if (ParseOptComma ())
96+ return ReportError ();
97+ }
98+
99+ // Retreive optional flags arg for non-RootConstants
100+ if (Parameter.Type != RootType::Constants && Buffer.consume_front (" flags" )) {
101+ if (ParseAssign ())
102+ return ReportError ();
103+
104+ if (ParseRootDescriptorFlag (Parameter.Flags ))
105+ return ReportError ();
106+
107+ // Remove trailing whitespace
108+ Buffer = Buffer.drop_while (isspace);
109+ }
110+
111+ // Create and push the root element on the parsed elements
112+ Elements->push_back (RootElement (Parameter));
113+ return false ;
114+ }
115+
116+ // Helper Parser methods
117+
118+ // Parses " = " with varying whitespace
119+ bool Parser::ParseAssign () {
120+ Buffer = Buffer.drop_while (isspace);
121+ if (!Buffer.starts_with (' =' ))
122+ return true ;
123+ Buffer = Buffer.drop_front ();
124+ Buffer = Buffer.drop_while (isspace);
125+ return false ;
126+ }
127+
128+ // Parses ", " with varying whitespace
129+ bool Parser::ParseComma () {
130+ if (!Buffer.starts_with (' ,' ))
131+ return true ;
132+ Buffer = Buffer.drop_front ();
133+ Buffer = Buffer.drop_while (isspace);
134+ return false ;
135+ }
136+
137+ // Parses ", " if possible. When successful we expect another parameter, and
138+ // return no error, otherwise we expect that we should be at the end of the
139+ // root element and return an error if this isn't the case
140+ bool Parser::ParseOptComma () {
141+ if (!ParseComma ())
142+ return false ;
143+ Buffer = Buffer.drop_while (isspace);
144+ return !Buffer.starts_with (' )' );
145+ }
146+
147+ bool Parser::ParseRegister (Register &Register) {
148+ // Parse expected register type ('b', 't', 'u', 's')
149+ if (Buffer.empty ())
150+ return ReportError ();
151+
152+ // Get type character
153+ Token = Buffer.take_front ();
154+ Buffer = Buffer.drop_front ();
155+
156+ auto MaybeType = llvm::StringSwitch<std::optional<RegisterType>>(Token)
157+ .Case (" b" , RegisterType::BReg)
158+ .Case (" t" , RegisterType::TReg)
159+ .Case (" u" , RegisterType::UReg)
160+ .Case (" s" , RegisterType::SReg)
161+ .Default (std::nullopt );
162+ if (!MaybeType)
163+ return ReportError ();
164+ Register.ViewType = *MaybeType;
165+
166+ if (ParseUnsignedInt (Register.Number ))
167+ return ReportError ();
168+
169+ return false ;
170+ }
171+
172+ // Parses "[0-9+]" as an unsigned int
173+ bool Parser::ParseUnsignedInt (uint32_t &Number) {
174+ StringRef NumString = Buffer.take_while (isdigit);
175+ APInt X = APInt (32 , 0 );
176+ if (NumString.getAsInteger (/* radix=*/ 10 , X))
177+ return true ;
178+ Number = X.getZExtValue ();
179+ Buffer = Buffer.drop_front (NumString.size ());
180+ return false ;
181+ }
182+
41183template <typename EnumType>
42184bool Parser::ParseEnum (SmallVector<std::pair<StringLiteral, EnumType>> Mapping,
43185 EnumType &Enum) {
@@ -57,6 +199,18 @@ bool Parser::ParseEnum(SmallVector<std::pair<StringLiteral, EnumType>> Mapping,
57199 return false ;
58200}
59201
202+ bool Parser::ParseRootDescriptorFlag (RootDescriptorFlags &Flag) {
203+ SmallVector<std::pair<StringLiteral, RootDescriptorFlags>> Mapping = {
204+ {" 0" , RootDescriptorFlags::None},
205+ {" DATA_VOLATILE" , RootDescriptorFlags::DataVolatile},
206+ {" DATA_STATIC_WHILE_SET_AT_EXECUTE" ,
207+ RootDescriptorFlags::DataStaticWhileSetAtExecute},
208+ {" DATA_STATIC" , RootDescriptorFlags::DataStatic},
209+ };
210+
211+ return ParseEnum<RootDescriptorFlags>(Mapping, Flag);
212+ }
213+
60214bool Parser::ParseRootFlag (RootFlags &Flag) {
61215 SmallVector<std::pair<StringLiteral, RootFlags>> Mapping = {
62216 {" 0" , RootFlags::None},
@@ -83,16 +237,36 @@ bool Parser::ParseRootFlag(RootFlags &Flag) {
83237 return ParseEnum<RootFlags>(Mapping, Flag);
84238}
85239
240+ bool Parser::ParseVisibility (ShaderVisibility &Visibility) {
241+ SmallVector<std::pair<StringLiteral, ShaderVisibility>> Mapping = {
242+ {" SHADER_VISIBILITY_ALL" , ShaderVisibility::All},
243+ {" SHADER_VISIBILITY_VERTEX" , ShaderVisibility::Vertex},
244+ {" SHADER_VISIBILITY_HULL" , ShaderVisibility::Hull},
245+ {" SHADER_VISIBILITY_DOMAIN" , ShaderVisibility::Domain},
246+ {" SHADER_VISIBILITY_GEOMETRY" , ShaderVisibility::Geometry},
247+ {" SHADER_VISIBILITY_PIXEL" , ShaderVisibility::Pixel},
248+ {" SHADER_VISIBILITY_AMPLIFICATION" , ShaderVisibility::Amplification},
249+ {" SHADER_VISIBILITY_MESH" , ShaderVisibility::Mesh},
250+ };
251+
252+ return ParseEnum<ShaderVisibility>(Mapping, Visibility);
253+ }
254+
86255bool Parser::ParseRootElement () {
87256 // Define different ParserMethods to use StringSwitch for dispatch
88257 enum class ParserMethod {
89258 ReportError,
90259 ParseRootFlags,
260+ ParseRootParameter,
91261 };
92262
93263 // Retreive which method should be used
94264 auto Method = llvm::StringSwitch<ParserMethod>(Token)
95265 .Case (" RootFlags" , ParserMethod::ParseRootFlags)
266+ .Case (" RootConstants" , ParserMethod::ParseRootParameter)
267+ .Case (" CBV" , ParserMethod::ParseRootParameter)
268+ .Case (" SRV" , ParserMethod::ParseRootParameter)
269+ .Case (" UAV" , ParserMethod::ParseRootParameter)
96270 .Default (ParserMethod::ReportError);
97271
98272 // Dispatch on the correct method
@@ -101,6 +275,8 @@ bool Parser::ParseRootElement() {
101275 return ReportError ();
102276 case ParserMethod::ParseRootFlags:
103277 return ParseRootFlags ();
278+ case ParserMethod::ParseRootParameter:
279+ return ParseRootParameter ();
104280 }
105281}
106282
0 commit comments