================
@@ -89,37 +88,178 @@ bool RootSignatureParser::parseDescriptorTableClause() {
           CurToken.TokKind == TokenKind::kw_UAV ||
           CurToken.TokKind == TokenKind::kw_Sampler) &&
          "Expects to only be invoked starting at given keyword");
+  TokenKind ParamKind = CurToken.TokKind; // retain for diagnostics
 
   DescriptorTableClause Clause;
-  switch (CurToken.TokKind) {
+  TokenKind ExpectedRegister;
+  switch (ParamKind) {
   default:
     llvm_unreachable("Switch for consumed token was not provided");
   case TokenKind::kw_CBV:
     Clause.Type = ClauseType::CBuffer;
+    ExpectedRegister = TokenKind::bReg;
     break;
   case TokenKind::kw_SRV:
     Clause.Type = ClauseType::SRV;
+    ExpectedRegister = TokenKind::tReg;
     break;
   case TokenKind::kw_UAV:
     Clause.Type = ClauseType::UAV;
+    ExpectedRegister = TokenKind::uReg;
     break;
   case TokenKind::kw_Sampler:
     Clause.Type = ClauseType::Sampler;
+    ExpectedRegister = TokenKind::sReg;
     break;
   }
 
   if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
-                           CurToken.TokKind))
+                           ParamKind))
     return true;
 
-  if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_after,
-                           CurToken.TokKind))
+  llvm::SmallDenseMap<TokenKind, ParamType> Params = {
----------------
inbelic wrote:

> I don't think what you've described int he code example here is where the 
> genericness becomes a problem.

> I think you draw a false equivalence. You seem to be saying we either do this 
> generically, or we do this like DXC... That's not what I'm saying. The 
> approach that Clang takes generally in parsing is to parse things out, and 
> from the parsed information construct a declaration or statement, which then 
> gets validated during construction.
> 
> That is not how DXC's parser for root signatures works, nor is it what you're 
> proposing, but maybe it's the better approach.

I see, then I did misinterpret what the other approach could be.

IIUC in this context, we might have an intermediate object `ParsedParamState` 
used to represent parameter values. `parseParams` would go through and parse 
the values to this object. Then we can construct our in-memory structs 
(`DescriptorTableClause`) from this object and validate the parameter values 
were specified correctly.

The most recent commit is a prototype of this, expect we allow some validation 
to be done when parsing.

> I think the bigger question is at what layer of abstraction does being 
> generic help and at what layer of abstraction is it a hinderance.

I think a good case to illustrate what level of abstraction we want is to 
consider parsing the `flags = FLAGS` parameter, where `FLAGS` could be a 
variety of flag types (`RootFlags`, `DescriptorRangeFlags`, etc.

Given the root element, (`RootCBV`, `CBV`, etc), it will directly imply the 
expected flag type.

Imo, we should validate it is the expected flag type during parsing instead of 
validation. Otherwise, we are throwing out that information and are forced to 
parse the flags in a general manner, only to rederive what the valid type is 
later.

Similar with register types, if we have `CBV` we should only parse a `b` 
register.

This allows for better localized diag messages by raising an error earlier at 
the invalid register or flag type.

So, I don't think the abstraction to have _all_ validation after parsing is 
beneficial. But we can have the ones that make sense to be when constructing 
the elements (checking which are mandatory), as this is more clear.

> Having a `parseRootParam` function that "generically" parses a root-level 
> parameter seems like a good idea, but should it remain generic based on the 
> type of the parameter? Should we have a single "parseArgument" function? 
> Maybe... Should these functions produce the same structural result for every 
> parameter? These things are less clear to me.

> The reasons that led you to a generic solution, might be reasons why 
> following existing patterns that Clang uses for order-independent parsing 
> (like attributes), might be the better architectural decision. Maybe we 
> should borrow more from Clang's AST design and have polymorphic returned 
> objects rather than variants.

I do think that using variants and mapping the variant types to a `parseMethod` 
is more confusing than it needs to be. Using a stateful struct is more clear in 
assigning them and easy to follow. And it removes the need for having to work 
around having an `any` type with polymorphic objects or variants.

https://github.com/llvm/llvm-project/pull/133800
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to