ChainUtil autogenerated validation for unpacking.

- The new generated functions only unpack the chains while verifying
  only expected extensions are on the chain.
- Further validations can be implemented on top of the tuples with
  templating if desired.

Bug: dawn:1955
Change-Id: Iec47072299dd4bb6d6cb093fdd7c211f8dbdb494
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/146361
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index 91c8ee7..1ebf88b 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -247,12 +247,14 @@
         if self.chained:
             assert self.chained == 'in' or self.chained == 'out'
             assert 'chain roots' in json_data
+            self.chain_roots = []
         if self.extensible:
             assert self.extensible == 'in' or self.extensible == 'out'
         # Chained structs inherit from wgpu::ChainedStruct, which has
         # nextInChain, so setting both extensible and chained would result in
         # two nextInChain members.
         assert not (self.extensible and self.chained)
+        self.extensions = []
 
     def update_metadata(self):
         Record.update_metadata(self)
@@ -384,6 +386,9 @@
 
 def link_structure(struct, types):
     struct.members = linked_record_members(struct.json_data['members'], types)
+    for root in struct.json_data.get('chain roots', []):
+        struct.chain_roots.append(types[root])
+        types[root].extensions.append(struct)
     struct.chain_roots = [types[root] for root in struct.json_data.get('chain roots', [])]
     assert all((root.category == 'structure' for root in struct.chain_roots))