blob: 705948cd490e64d6861785d6e4009352014e54e6 [file] [log] [blame]
Corentin Wallez59382b72020-04-17 20:43:07 +00001#!/usr/bin/env python3
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02002# Copyright 2017 The Dawn Authors
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04003#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Corentin Wallez0c38e922019-06-07 08:59:17 +000016import json, os, sys
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040017from collections import namedtuple
Corentin Wallez0c38e922019-06-07 08:59:17 +000018
Corentin Wallez0c38e922019-06-07 08:59:17 +000019from generator_lib import Generator, run_generator, FileRender
Corentin Wallez031fbbb2019-06-11 18:03:05 +000020
21############################################################
22# OBJECT MODEL
23############################################################
24
Kai Ninomiya01aeca22020-07-15 19:51:17 +000025
fujunwei76bda372021-11-23 08:47:35 +000026class Metadata:
27 def __init__(self, metadata):
28 self.api = metadata['api']
29 self.namespace = metadata['namespace']
30 self.c_prefix = metadata.get('c_prefix', self.namespace.upper())
fujunwei3a464762021-12-05 05:29:44 +000031 self.proc_table_prefix = metadata['proc_table_prefix']
fujunweia2241d42021-12-16 04:54:38 +000032 self.impl_dir = metadata.get('impl_dir', '')
33 self.native_namespace = metadata['native_namespace']
fujunwei76bda372021-11-23 08:47:35 +000034 self.copyright_year = metadata.get('copyright_year', None)
35
36
Corentin Wallez031fbbb2019-06-11 18:03:05 +000037class Name:
38 def __init__(self, name, native=False):
39 self.native = native
Austin Eng76a8d0b2020-04-03 17:37:48 +000040 self.name = name
Corentin Wallez031fbbb2019-06-11 18:03:05 +000041 if native:
42 self.chunks = [name]
43 else:
44 self.chunks = name.split(' ')
45
Austin Eng76a8d0b2020-04-03 17:37:48 +000046 def get(self):
47 return self.name
48
Corentin Wallez031fbbb2019-06-11 18:03:05 +000049 def CamelChunk(self, chunk):
50 return chunk[0].upper() + chunk[1:]
51
52 def canonical_case(self):
53 return (' '.join(self.chunks)).lower()
54
55 def concatcase(self):
56 return ''.join(self.chunks)
57
58 def camelCase(self):
Kai Ninomiya01aeca22020-07-15 19:51:17 +000059 return self.chunks[0] + ''.join(
60 [self.CamelChunk(chunk) for chunk in self.chunks[1:]])
Corentin Wallez031fbbb2019-06-11 18:03:05 +000061
62 def CamelCase(self):
63 return ''.join([self.CamelChunk(chunk) for chunk in self.chunks])
64
65 def SNAKE_CASE(self):
66 return '_'.join([chunk.upper() for chunk in self.chunks])
67
68 def snake_case(self):
69 return '_'.join(self.chunks)
70
Corentin Wallezec9cf2a2022-01-12 09:17:35 +000071 def namespace_case(self):
72 return '::'.join(self.chunks)
73
Ben Clayton20cbe6d2022-02-04 12:51:25 +000074 def Dirs(self):
75 return '/'.join(self.chunks)
76
Kai Ninomiya7b6246a2020-01-28 23:54:38 +000077 def js_enum_case(self):
78 result = self.chunks[0].lower()
79 for chunk in self.chunks[1:]:
80 if not result[-1].isdigit():
81 result += '-'
82 result += chunk.lower()
83 return result
84
Kai Ninomiya01aeca22020-07-15 19:51:17 +000085
Corentin Wallez031fbbb2019-06-11 18:03:05 +000086def concat_names(*names):
87 return ' '.join([name.canonical_case() for name in names])
88
Kai Ninomiya01aeca22020-07-15 19:51:17 +000089
Corentin Wallez031fbbb2019-06-11 18:03:05 +000090class Type:
91 def __init__(self, name, json_data, native=False):
92 self.json_data = json_data
93 self.dict_name = name
94 self.name = Name(name, native=native)
95 self.category = json_data['category']
Jiawei Shao6d6b63c2021-12-02 07:29:41 +000096 self.is_wire_transparent = False
Corentin Wallez031fbbb2019-06-11 18:03:05 +000097
Kai Ninomiya01aeca22020-07-15 19:51:17 +000098
Kai Ninomiya930e9182021-09-17 19:44:43 +000099EnumValue = namedtuple('EnumValue', ['name', 'value', 'valid', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000100
101
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000102class EnumType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000103 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000104 Type.__init__(self, name, json_data)
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000105
106 self.values = []
107 self.contiguousFromZero = True
108 lastValue = -1
109 for m in self.json_data['values']:
Kai Ninomiya930e9182021-09-17 19:44:43 +0000110 if not is_enabled(m):
111 continue
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000112 value = m['value']
113 if value != lastValue + 1:
114 self.contiguousFromZero = False
115 lastValue = value
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000116 self.values.append(
Kai Ninomiya930e9182021-09-17 19:44:43 +0000117 EnumValue(Name(m['name']), value, m.get('valid', True), m))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000118
Corentin Wallez7ac08152019-06-26 19:54:43 +0000119 # Assert that all values are unique in enums
120 all_values = set()
121 for value in self.values:
122 if value.value in all_values:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000123 raise Exception("Duplicate value {} in enum {}".format(
124 value.value, name))
Corentin Wallez7ac08152019-06-26 19:54:43 +0000125 all_values.add(value.value)
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000126 self.is_wire_transparent = True
Corentin Wallez7ac08152019-06-26 19:54:43 +0000127
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000128
Kai Ninomiya930e9182021-09-17 19:44:43 +0000129BitmaskValue = namedtuple('BitmaskValue', ['name', 'value', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000130
131
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000132class BitmaskType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000133 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000134 Type.__init__(self, name, json_data)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000135 self.values = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000136 BitmaskValue(Name(m['name']), m['value'], m)
137 for m in self.json_data['values'] if is_enabled(m)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000138 ]
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000139 self.full_mask = 0
140 for value in self.values:
141 self.full_mask = self.full_mask | value.value
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000142 self.is_wire_transparent = True
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000143
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000144
fujunwei23f71622021-12-02 07:41:21 +0000145class FunctionPointerType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000146 def __init__(self, is_enabled, name, json_data):
Corentin Wallez540abab2019-11-22 13:18:22 +0000147 Type.__init__(self, name, json_data)
fujunwei23f71622021-12-02 07:41:21 +0000148 self.return_type = None
Corentin Wallez540abab2019-11-22 13:18:22 +0000149 self.arguments = []
150
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000151
Brandon Jones58a471a2021-02-08 19:48:06 +0000152class TypedefType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000153 def __init__(self, is_enabled, name, json_data):
Brandon Jones58a471a2021-02-08 19:48:06 +0000154 Type.__init__(self, name, json_data)
155 self.type = None
156
157
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000158class NativeType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000159 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000160 Type.__init__(self, name, json_data, native=True)
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000161 self.is_wire_transparent = True
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000162
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000163
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000164# Methods and structures are both "records", so record members correspond to
165# method arguments or structure members.
166class RecordMember:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000167 def __init__(self,
168 name,
169 typ,
170 annotation,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000171 json_data,
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000172 optional=False,
173 is_return_value=False,
174 default_value=None,
Austin Eng6a5418a2019-07-19 16:01:48 +0000175 skip_serialize=False):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000176 self.name = name
177 self.type = typ
178 self.annotation = annotation
Kai Ninomiya930e9182021-09-17 19:44:43 +0000179 self.json_data = json_data
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000180 self.length = None
181 self.optional = optional
182 self.is_return_value = is_return_value
183 self.handle_type = None
Corentin Wallez8f938712019-07-08 19:20:22 +0000184 self.default_value = default_value
Austin Eng6a5418a2019-07-19 16:01:48 +0000185 self.skip_serialize = skip_serialize
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000186
187 def set_handle_type(self, handle_type):
188 assert self.type.dict_name == "ObjectHandle"
189 self.handle_type = handle_type
190
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000191
Kai Ninomiya930e9182021-09-17 19:44:43 +0000192Method = namedtuple('Method',
193 ['name', 'return_type', 'arguments', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000194
195
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000196class ObjectType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000197 def __init__(self, is_enabled, name, json_data):
198 json_data_override = {'methods': []}
199 if 'methods' in json_data:
200 json_data_override['methods'] = [
201 m for m in json_data['methods'] if is_enabled(m)
202 ]
203 Type.__init__(self, name, dict(json_data, **json_data_override))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000204
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000205
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000206class Record:
207 def __init__(self, name):
208 self.name = Name(name)
209 self.members = []
Austin Eng76a8d0b2020-04-03 17:37:48 +0000210 self.may_have_dawn_object = False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000211
212 def update_metadata(self):
Austin Eng76a8d0b2020-04-03 17:37:48 +0000213 def may_have_dawn_object(member):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000214 if isinstance(member.type, ObjectType):
215 return True
216 elif isinstance(member.type, StructureType):
Austin Eng76a8d0b2020-04-03 17:37:48 +0000217 return member.type.may_have_dawn_object
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000218 else:
219 return False
220
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000221 self.may_have_dawn_object = any(
222 may_have_dawn_object(member) for member in self.members)
Austin Eng76a8d0b2020-04-03 17:37:48 +0000223
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000224 # Set may_have_dawn_object to true if the type is chained or
225 # extensible. Chained structs may contain a Dawn object.
Austin Eng76a8d0b2020-04-03 17:37:48 +0000226 if isinstance(self, StructureType):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000227 self.may_have_dawn_object = (self.may_have_dawn_object
228 or self.chained or self.extensible)
229
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000230
231class StructureType(Record, Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000232 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000233 Record.__init__(self, name)
Kai Ninomiya930e9182021-09-17 19:44:43 +0000234 json_data_override = {}
235 if 'members' in json_data:
236 json_data_override['members'] = [
237 m for m in json_data['members'] if is_enabled(m)
238 ]
239 Type.__init__(self, name, dict(json_data, **json_data_override))
Corentin Walleza45561b2022-07-14 12:58:25 +0000240 self.chained = json_data.get('chained', None)
241 self.extensible = json_data.get('extensible', None)
Austin Eng0c824052021-09-20 16:07:25 +0000242 if self.chained:
Corentin Walleza45561b2022-07-14 12:58:25 +0000243 assert self.chained == 'in' or self.chained == 'out'
244 assert 'chain roots' in json_data
Austin Eng0c824052021-09-20 16:07:25 +0000245 if self.extensible:
Corentin Walleza45561b2022-07-14 12:58:25 +0000246 assert self.extensible == 'in' or self.extensible == 'out'
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000247 # Chained structs inherit from wgpu::ChainedStruct, which has
248 # nextInChain, so setting both extensible and chained would result in
249 # two nextInChain members.
250 assert not (self.extensible and self.chained)
251
Jiawei Shao1fa386c2021-12-21 04:04:51 +0000252 def update_metadata(self):
253 Record.update_metadata(self)
254
255 if self.may_have_dawn_object:
256 self.is_wire_transparent = False
257 return
258
259 assert not (self.chained or self.extensible)
260
261 def get_is_wire_transparent(member):
262 return member.type.is_wire_transparent and member.annotation == 'value'
263
264 self.is_wire_transparent = all(
265 get_is_wire_transparent(m) for m in self.members)
266
Austin Eng0c824052021-09-20 16:07:25 +0000267 @property
268 def output(self):
269 return self.chained == "out" or self.extensible == "out"
270
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000271
fujunwei4e876902021-11-25 08:44:01 +0000272class ConstantDefinition():
273 def __init__(self, is_enabled, name, json_data):
274 self.type = None
275 self.value = json_data['value']
276 self.json_data = json_data
277 self.name = Name(name)
278
279
fujunwei23f71622021-12-02 07:41:21 +0000280class FunctionDeclaration():
281 def __init__(self, is_enabled, name, json_data):
282 self.return_type = None
283 self.arguments = []
284 self.json_data = json_data
285 self.name = Name(name)
286
287
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000288class Command(Record):
289 def __init__(self, name, members=None):
290 Record.__init__(self, name)
291 self.members = members or []
292 self.derived_object = None
293 self.derived_method = None
294
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000295
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000296def linked_record_members(json_data, types):
297 members = []
298 members_by_name = {}
299 for m in json_data:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000300 member = RecordMember(Name(m['name']),
301 types[m['type']],
Corentin Wallez8f938712019-07-08 19:20:22 +0000302 m.get('annotation', 'value'),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000303 m,
Corentin Wallez8f938712019-07-08 19:20:22 +0000304 optional=m.get('optional', False),
305 is_return_value=m.get('is_return_value', False),
Austin Eng6a5418a2019-07-19 16:01:48 +0000306 default_value=m.get('default', None),
307 skip_serialize=m.get('skip_serialize', False))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000308 handle_type = m.get('handle_type')
309 if handle_type:
310 member.set_handle_type(types[handle_type])
311 members.append(member)
312 members_by_name[member.name.canonical_case()] = member
313
314 for (member, m) in zip(members, json_data):
315 if member.annotation != 'value':
316 if not 'length' in m:
317 if member.type.category != 'object':
318 member.length = "constant"
319 member.constant_length = 1
320 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000321 assert False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000322 elif m['length'] == 'strlen':
323 member.length = 'strlen'
Yan52040532021-12-15 04:08:56 +0000324 elif isinstance(m['length'], int):
325 assert m['length'] > 0
326 member.length = "constant"
327 member.constant_length = m['length']
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000328 else:
329 member.length = members_by_name[m['length']]
330
331 return members
Corentin Walleza6416542018-05-17 16:55:53 -0400332
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000333
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400334############################################################
335# PARSE
336############################################################
Corentin Wallez4b410a32017-04-20 14:42:36 -0400337
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000338
Corentin Walleze2f94842018-12-05 17:49:04 +0000339def link_object(obj, types):
340 def make_method(json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000341 arguments = linked_record_members(json_data.get('args', []), types)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000342 return Method(Name(json_data['name']),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000343 types[json_data.get('returns',
344 'void')], arguments, json_data)
Corentin Walleze2f94842018-12-05 17:49:04 +0000345
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000346 obj.methods = [make_method(m) for m in obj.json_data.get('methods', [])]
Corentin Wallez97231682019-10-08 07:38:01 +0000347 obj.methods.sort(key=lambda method: method.name.canonical_case())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400348
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000349
Corentin Walleza6416542018-05-17 16:55:53 -0400350def link_structure(struct, types):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000351 struct.members = linked_record_members(struct.json_data['members'], types)
Corentin Walleza45561b2022-07-14 12:58:25 +0000352 struct.chain_roots = [types[root] for root in struct.json_data.get('chain roots', [])]
353 assert all((root.category == 'structure' for root in struct.chain_roots))
Corentin Walleza6416542018-05-17 16:55:53 -0400354
Corentin Wallez540abab2019-11-22 13:18:22 +0000355
fujunwei23f71622021-12-02 07:41:21 +0000356def link_function_pointer(function_pointer, types):
357 link_function(function_pointer, types)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000358
359
Brandon Jones58a471a2021-02-08 19:48:06 +0000360def link_typedef(typedef, types):
361 typedef.type = types[typedef.json_data['type']]
362
363
fujunwei4e876902021-11-25 08:44:01 +0000364def link_constant(constant, types):
365 constant.type = types[constant.json_data['type']]
366 assert constant.type.name.native
367
368
fujunwei23f71622021-12-02 07:41:21 +0000369def link_function(function, types):
370 function.return_type = types[function.json_data.get('returns', 'void')]
371 function.arguments = linked_record_members(function.json_data['args'],
372 types)
373
374
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000375# Sort structures so that if struct A has struct B as a member, then B is
376# listed before A.
377#
378# This is a form of topological sort where we try to keep the order reasonably
379# similar to the original order (though the sort isn't technically stable).
380#
381# It works by computing for each struct type what is the depth of its DAG of
Kai Ninomiya7d174a12021-09-21 17:36:27 +0000382# dependents, then re-sorting based on that depth using Python's stable sort.
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000383# This makes a toposort because if A depends on B then its depth will be bigger
384# than B's. It is also nice because all nodes with the same depth are kept in
385# the input order.
Corentin Wallez29353d62018-09-18 12:49:22 +0000386def topo_sort_structure(structs):
387 for struct in structs:
388 struct.visited = False
389 struct.subdag_depth = 0
390
391 def compute_depth(struct):
392 if struct.visited:
393 return struct.subdag_depth
394
395 max_dependent_depth = 0
396 for member in struct.members:
Corentin Walleze2f94842018-12-05 17:49:04 +0000397 if member.type.category == 'structure':
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000398 max_dependent_depth = max(max_dependent_depth,
399 compute_depth(member.type) + 1)
Corentin Wallez29353d62018-09-18 12:49:22 +0000400
401 struct.subdag_depth = max_dependent_depth
402 struct.visited = True
403 return struct.subdag_depth
404
405 for struct in structs:
406 compute_depth(struct)
407
408 result = sorted(structs, key=lambda struct: struct.subdag_depth)
409
410 for struct in structs:
411 del struct.visited
412 del struct.subdag_depth
413
414 return result
415
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000416
Austin Eng2f218e22021-12-22 19:02:23 +0000417def parse_json(json, enabled_tags, disabled_tags=None):
418 is_enabled = lambda json_data: item_is_enabled(
419 enabled_tags, json_data) and not item_is_disabled(
420 disabled_tags, json_data)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400421 category_to_parser = {
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000422 'bitmask': BitmaskType,
423 'enum': EnumType,
424 'native': NativeType,
fujunwei23f71622021-12-02 07:41:21 +0000425 'function pointer': FunctionPointerType,
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000426 'object': ObjectType,
427 'structure': StructureType,
Brandon Jones58a471a2021-02-08 19:48:06 +0000428 'typedef': TypedefType,
fujunwei4e876902021-11-25 08:44:01 +0000429 'constant': ConstantDefinition,
fujunwei23f71622021-12-02 07:41:21 +0000430 'function': FunctionDeclaration
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400431 }
432
433 types = {}
434
435 by_category = {}
436 for name in category_to_parser.keys():
437 by_category[name] = []
438
Corentin Walleze2f94842018-12-05 17:49:04 +0000439 for (name, json_data) in json.items():
Austin Eng2f218e22021-12-22 19:02:23 +0000440 if name[0] == '_' or not is_enabled(json_data):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400441 continue
Corentin Walleze2f94842018-12-05 17:49:04 +0000442 category = json_data['category']
Kai Ninomiya930e9182021-09-17 19:44:43 +0000443 parsed = category_to_parser[category](is_enabled, name, json_data)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400444 by_category[category].append(parsed)
445 types[name] = parsed
446
447 for obj in by_category['object']:
448 link_object(obj, types)
449
Corentin Walleza6416542018-05-17 16:55:53 -0400450 for struct in by_category['structure']:
451 link_structure(struct, types)
452
fujunwei23f71622021-12-02 07:41:21 +0000453 for function_pointer in by_category['function pointer']:
454 link_function_pointer(function_pointer, types)
Corentin Wallez540abab2019-11-22 13:18:22 +0000455
Brandon Jones58a471a2021-02-08 19:48:06 +0000456 for typedef in by_category['typedef']:
457 link_typedef(typedef, types)
458
fujunwei4e876902021-11-25 08:44:01 +0000459 for constant in by_category['constant']:
460 link_constant(constant, types)
461
fujunwei23f71622021-12-02 07:41:21 +0000462 for function in by_category['function']:
463 link_function(function, types)
464
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400465 for category in by_category.keys():
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000466 by_category[category] = sorted(
467 by_category[category], key=lambda typ: typ.name.canonical_case())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400468
Corentin Wallez29353d62018-09-18 12:49:22 +0000469 by_category['structure'] = topo_sort_structure(by_category['structure'])
470
Austin Engc7f416c2019-01-15 20:49:53 +0000471 for struct in by_category['structure']:
472 struct.update_metadata()
473
Kai Ninomiya930e9182021-09-17 19:44:43 +0000474 api_params = {
475 'types': types,
476 'by_category': by_category,
477 'enabled_tags': enabled_tags,
Austin Eng2f218e22021-12-22 19:02:23 +0000478 'disabled_tags': disabled_tags,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000479 }
480 return {
fujunwei76bda372021-11-23 08:47:35 +0000481 'metadata': Metadata(json['_metadata']),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000482 'types': types,
483 'by_category': by_category,
484 'enabled_tags': enabled_tags,
Austin Eng2f218e22021-12-22 19:02:23 +0000485 'disabled_tags': disabled_tags,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000486 'c_methods': lambda typ: c_methods(api_params, typ),
487 'c_methods_sorted_by_name': get_c_methods_sorted_by_name(api_params),
488 }
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000489
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400490
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000491############################################################
492# WIRE STUFF
493############################################################
494
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000495
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000496# Create wire commands from api methods
497def compute_wire_params(api_params, wire_json):
498 wire_params = api_params.copy()
499 types = wire_params['types']
500
501 commands = []
502 return_commands = []
503
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000504 wire_json['special items']['client_handwritten_commands'] += wire_json[
505 'special items']['client_side_commands']
Corentin Wallez540abab2019-11-22 13:18:22 +0000506
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000507 # Generate commands from object methods
508 for api_object in wire_params['by_category']['object']:
509 for method in api_object.methods:
510 command_name = concat_names(api_object.name, method.name)
511 command_suffix = Name(command_name).CamelCase()
512
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000513 # Only object return values or void are supported.
514 # Other methods must be handwritten.
515 is_object = method.return_type.category == 'object'
516 is_void = method.return_type.name.canonical_case() == 'void'
517 if not (is_object or is_void):
518 assert command_suffix in (
519 wire_json['special items']['client_handwritten_commands'])
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000520 continue
521
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000522 if command_suffix in (
523 wire_json['special items']['client_side_commands']):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000524 continue
525
526 # Create object method commands by prepending "self"
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000527 members = [
528 RecordMember(Name('self'), types[api_object.dict_name],
Kai Ninomiya930e9182021-09-17 19:44:43 +0000529 'value', {})
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000530 ]
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000531 members += method.arguments
532
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000533 # Client->Server commands that return an object return the
534 # result object handle
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000535 if method.return_type.category == 'object':
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000536 result = RecordMember(Name('result'),
537 types['ObjectHandle'],
Kai Ninomiya930e9182021-09-17 19:44:43 +0000538 'value', {},
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000539 is_return_value=True)
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000540 result.set_handle_type(method.return_type)
541 members.append(result)
542
543 command = Command(command_name, members)
544 command.derived_object = api_object
545 command.derived_method = method
546 commands.append(command)
547
548 for (name, json_data) in wire_json['commands'].items():
549 commands.append(Command(name, linked_record_members(json_data, types)))
550
551 for (name, json_data) in wire_json['return commands'].items():
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000552 return_commands.append(
553 Command(name, linked_record_members(json_data, types)))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000554
555 wire_params['cmd_records'] = {
556 'command': commands,
557 'return command': return_commands
558 }
559
560 for commands in wire_params['cmd_records'].values():
561 for command in commands:
562 command.update_metadata()
563 commands.sort(key=lambda c: c.name.canonical_case())
564
565 wire_params.update(wire_json.get('special items', {}))
566
567 return wire_params
568
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000569############################################################
570# DAWN LPM FUZZ STUFF
571############################################################
572
573
574def compute_lpm_params(api_and_wire_params, lpm_json):
575 # Start with all commands in dawn.json and dawn_wire.json
576 lpm_params = api_and_wire_params.copy()
577
578 # Commands that are built through generation
579 proto_generated_commands = []
580
581 # All commands, including hand written commands that we can't generate
582 # through codegen
583 proto_all_commands = []
584
585 # Remove blocklisted commands from protobuf generation params
586 blocklisted_cmds_proto = lpm_json.get('blocklisted_cmds')
587 custom_cmds_proto = lpm_json.get('custom_cmds')
588 for command in lpm_params['cmd_records']['command']:
589 blocklisted = command.name.get() in blocklisted_cmds_proto
590 custom = command.name.get() in custom_cmds_proto
591
592 if not blocklisted and not custom:
593 proto_generated_commands.append(command)
594 proto_all_commands.append(command)
595
596 lpm_params['cmd_records'] = {
597 'proto_generated_commands': proto_generated_commands,
598 'proto_all_commands': proto_all_commands,
599 }
600
601 return lpm_params
602
603
604def as_protobufTypeLPM(member):
605 assert 'type' in member.json_data
606
607 if member.type.name.native:
608 typ = member.json_data['type']
609 cpp_to_protobuf_type = {
610 "bool": "bool",
611 "float": "float",
612 "double": "double",
613 "int8_t": "int32",
614 "int16_t": "int32",
615 "int32_t": "int32",
616 "int64_t": "int64",
617 "uint8_t": "uint32",
618 "uint16_t": "uint32",
619 "uint32_t": "uint32",
620 "uint64_t": "uint64",
621 }
622
623 assert typ in cpp_to_protobuf_type
624
625 return cpp_to_protobuf_type[typ]
626
627 return member.type.name.CamelCase()
628
629
630def as_protobufNameLPM(*names):
631 # `descriptor` is a reserved keyword in lpm
632 if (names[0].concatcase() == "descriptor"):
633 return "desc"
634 return as_varName(*names)
635
636
637def unreachable_code():
638 assert False
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000639
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400640#############################################################
Corentin Wallez0c38e922019-06-07 08:59:17 +0000641# Generator
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400642#############################################################
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400643
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000644
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400645def as_varName(*names):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000646 return names[0].camelCase() + ''.join(
647 [name.CamelCase() for name in names[1:]])
648
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400649
fujunwei76bda372021-11-23 08:47:35 +0000650def as_cType(c_prefix, name):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400651 if name.native:
652 return name.concatcase()
653 else:
fujunwei76bda372021-11-23 08:47:35 +0000654 return c_prefix + name.CamelCase()
Corentin Wallez919812e2019-10-17 08:46:07 +0000655
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000656
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400657def as_cppType(name):
658 if name.native:
659 return name.concatcase()
660 else:
661 return name.CamelCase()
662
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000663
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000664def as_jsEnumValue(value):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000665 if 'jsrepr' in value.json_data: return value.json_data['jsrepr']
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000666 return "'" + value.name.js_enum_case() + "'"
667
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000668
Austin Eng740995c2019-05-15 18:55:22 +0000669def convert_cType_to_cppType(typ, annotation, arg, indent=0):
670 if typ.category == 'native':
671 return arg
672 if annotation == 'value':
673 if typ.category == 'object':
674 return '{}::Acquire({})'.format(as_cppType(typ.name), arg)
675 elif typ.category == 'structure':
676 converted_members = [
677 convert_cType_to_cppType(
678 member.type, member.annotation,
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000679 '{}.{}'.format(arg, as_varName(member.name)), indent + 1)
680 for member in typ.members
681 ]
Austin Eng740995c2019-05-15 18:55:22 +0000682
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000683 converted_members = [(' ' * 4) + m for m in converted_members]
Austin Eng740995c2019-05-15 18:55:22 +0000684 converted_members = ',\n'.join(converted_members)
685
686 return as_cppType(typ.name) + ' {\n' + converted_members + '\n}'
fujunweid3cac112021-12-14 02:20:15 +0000687 elif typ.category == 'function pointer':
688 return 'reinterpret_cast<{}>({})'.format(as_cppType(typ.name), arg)
Austin Eng740995c2019-05-15 18:55:22 +0000689 else:
690 return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
691 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000692 return 'reinterpret_cast<{} {}>({})'.format(as_cppType(typ.name),
693 annotation, arg)
694
Austin Eng740995c2019-05-15 18:55:22 +0000695
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400696def decorate(name, typ, arg):
697 if arg.annotation == 'value':
698 return typ + ' ' + name
Austin Eng740995c2019-05-15 18:55:22 +0000699 elif arg.annotation == '*':
700 return typ + ' * ' + name
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400701 elif arg.annotation == 'const*':
702 return typ + ' const * ' + name
Austin Eng2f218e22021-12-22 19:02:23 +0000703 elif arg.annotation == 'const*const*':
704 return 'const ' + typ + '* const * ' + name
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400705 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000706 assert False
707
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400708
709def annotated(typ, arg):
710 name = as_varName(arg.name)
711 return decorate(name, typ, arg)
712
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000713
Kai Ninomiya930e9182021-09-17 19:44:43 +0000714def item_is_enabled(enabled_tags, json_data):
715 tags = json_data.get('tags')
716 if tags is None: return True
717 return any(tag in enabled_tags for tag in tags)
718
719
Austin Eng2f218e22021-12-22 19:02:23 +0000720def item_is_disabled(disabled_tags, json_data):
721 if disabled_tags is None: return False
722 tags = json_data.get('tags')
723 if tags is None: return False
724
725 return any(tag in disabled_tags for tag in tags)
726
727
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400728def as_cppEnum(value_name):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000729 assert not value_name.native
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400730 if value_name.concatcase()[0].isdigit():
731 return "e" + value_name.CamelCase()
732 return value_name.CamelCase()
733
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000734
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400735def as_MethodSuffix(type_name, method_name):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000736 assert not type_name.native and not method_name.native
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400737 return type_name.CamelCase() + method_name.CamelCase()
738
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000739
fujunwei76bda372021-11-23 08:47:35 +0000740def as_frontendType(metadata, typ):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400741 if typ.category == 'object':
Corentin Wallez4f5fc2d2019-04-01 21:48:38 +0000742 return typ.name.CamelCase() + 'Base*'
Corentin Wallezfe253f12018-08-01 15:12:10 +0200743 elif typ.category in ['bitmask', 'enum']:
fujunwei76bda372021-11-23 08:47:35 +0000744 return metadata.namespace + '::' + typ.name.CamelCase()
Corentin Wallezfe253f12018-08-01 15:12:10 +0200745 elif typ.category == 'structure':
746 return as_cppType(typ.name)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400747 else:
fujunwei76bda372021-11-23 08:47:35 +0000748 return as_cType(metadata.c_prefix, typ.name)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400749
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000750
fujunwei76bda372021-11-23 08:47:35 +0000751def as_wireType(metadata, typ):
Austin Engcb0cb652019-08-27 21:41:56 +0000752 if typ.category == 'object':
753 return typ.name.CamelCase() + '*'
Brandon Jones6f2bbe92021-04-05 23:34:17 +0000754 elif typ.category in ['bitmask', 'enum', 'structure']:
fujunwei76bda372021-11-23 08:47:35 +0000755 return metadata.c_prefix + typ.name.CamelCase()
Austin Engcb0cb652019-08-27 21:41:56 +0000756 else:
757 return as_cppType(typ.name)
758
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000759
Loko Kung4d835252022-03-19 00:21:48 +0000760def as_formatType(typ):
761 # Unsigned integral types
762 if typ.json_data['type'] in ['bool', 'uint32_t', 'uint64_t']:
763 return 'u'
764
765 # Defaults everything else to strings.
766 return 's'
767
768
Kai Ninomiya930e9182021-09-17 19:44:43 +0000769def c_methods(params, typ):
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000770 return typ.methods + [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000771 x for x in [
772 Method(Name('reference'), params['types']['void'], [],
773 {'tags': ['dawn', 'emscripten']}),
774 Method(Name('release'), params['types']['void'], [],
775 {'tags': ['dawn', 'emscripten']}),
776 ] if item_is_enabled(params['enabled_tags'], x.json_data)
Austin Eng2f218e22021-12-22 19:02:23 +0000777 and not item_is_disabled(params['disabled_tags'], x.json_data)
Corentin Wallez4b410a32017-04-20 14:42:36 -0400778 ]
779
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000780
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000781def get_c_methods_sorted_by_name(api_params):
Corentin Wallezc57b1802019-10-15 12:08:48 +0000782 unsorted = [(as_MethodSuffix(typ.name, method.name), typ, method) \
783 for typ in api_params['by_category']['object'] \
Kai Ninomiya930e9182021-09-17 19:44:43 +0000784 for method in c_methods(api_params, typ) ]
Corentin Wallezc57b1802019-10-15 12:08:48 +0000785 return [(typ, method) for (_, typ, method) in sorted(unsorted)]
786
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000787
Corentin Wallez540abab2019-11-22 13:18:22 +0000788def has_callback_arguments(method):
fujunwei23f71622021-12-02 07:41:21 +0000789 return any(arg.type.category == 'function pointer' for arg in method.arguments)
Corentin Wallez540abab2019-11-22 13:18:22 +0000790
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000791
fujunwei76bda372021-11-23 08:47:35 +0000792def make_base_render_params(metadata):
793 c_prefix = metadata.c_prefix
794
795 def as_cTypeEnumSpecialCase(typ):
796 if typ.category == 'bitmask':
797 return as_cType(c_prefix, typ.name) + 'Flags'
798 return as_cType(c_prefix, typ.name)
799
800 def as_cEnum(type_name, value_name):
801 assert not type_name.native and not value_name.native
802 return c_prefix + type_name.CamelCase() + '_' + value_name.CamelCase()
803
804 def as_cMethod(type_name, method_name):
fujunwei23f71622021-12-02 07:41:21 +0000805 c_method = c_prefix.lower()
806 if type_name != None:
807 assert not type_name.native
808 c_method += type_name.CamelCase()
809 assert not method_name.native
810 c_method += method_name.CamelCase()
811 return c_method
fujunwei76bda372021-11-23 08:47:35 +0000812
813 def as_cProc(type_name, method_name):
fujunwei23f71622021-12-02 07:41:21 +0000814 c_proc = c_prefix + 'Proc'
815 if type_name != None:
816 assert not type_name.native
817 c_proc += type_name.CamelCase()
818 assert not method_name.native
819 c_proc += method_name.CamelCase()
820 return c_proc
fujunwei76bda372021-11-23 08:47:35 +0000821
822 return {
823 'Name': lambda name: Name(name),
824 'as_annotated_cType': \
825 lambda arg: annotated(as_cTypeEnumSpecialCase(arg.type), arg),
826 'as_annotated_cppType': \
827 lambda arg: annotated(as_cppType(arg.type.name), arg),
828 'as_cEnum': as_cEnum,
829 'as_cppEnum': as_cppEnum,
830 'as_cMethod': as_cMethod,
831 'as_MethodSuffix': as_MethodSuffix,
832 'as_cProc': as_cProc,
833 'as_cType': lambda name: as_cType(c_prefix, name),
834 'as_cppType': as_cppType,
835 'as_jsEnumValue': as_jsEnumValue,
836 'convert_cType_to_cppType': convert_cType_to_cppType,
837 'as_varName': as_varName,
Loko Kung4d835252022-03-19 00:21:48 +0000838 'decorate': decorate,
839 'as_formatType': as_formatType
fujunwei76bda372021-11-23 08:47:35 +0000840 }
841
842
Corentin Wallez0c38e922019-06-07 08:59:17 +0000843class MultiGeneratorFromDawnJSON(Generator):
844 def get_description(self):
845 return 'Generates code for various target from Dawn.json.'
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400846
Corentin Wallez0c38e922019-06-07 08:59:17 +0000847 def add_commandline_arguments(self, parser):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000848 allowed_targets = [
Ben Clayton35940f92022-02-04 17:15:16 +0000849 'dawn_headers', 'cpp_headers', 'cpp', 'proc', 'mock_api', 'wire',
Brendon Tiszkad0b284b2023-02-08 20:43:18 +0000850 'native_utils', 'dawn_lpmfuzz_cpp', 'dawn_lpmfuzz_proto'
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000851 ]
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400852
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000853 parser.add_argument('--dawn-json',
854 required=True,
855 type=str,
856 help='The DAWN JSON definition to use.')
857 parser.add_argument('--wire-json',
858 default=None,
859 type=str,
860 help='The DAWN WIRE JSON definition to use.')
Brendon Tiszkad0b284b2023-02-08 20:43:18 +0000861 parser.add_argument("--lpm-json",
862 default=None,
863 type=str,
864 help='The DAWN LPM FUZZER definitions to use.')
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000865 parser.add_argument(
866 '--targets',
867 required=True,
868 type=str,
869 help=
870 'Comma-separated subset of targets to output. Available targets: '
871 + ', '.join(allowed_targets))
Brendon Tiszkad0b284b2023-02-08 20:43:18 +0000872
Corentin Wallez0c38e922019-06-07 08:59:17 +0000873 def get_file_renders(self, args):
874 with open(args.dawn_json) as f:
875 loaded_json = json.loads(f.read())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400876
Corentin Wallez0c38e922019-06-07 08:59:17 +0000877 targets = args.targets.split(',')
Corentin Wallez4b410a32017-04-20 14:42:36 -0400878
Corentin Wallez0c38e922019-06-07 08:59:17 +0000879 wire_json = None
880 if args.wire_json:
881 with open(args.wire_json) as f:
882 wire_json = json.loads(f.read())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400883
Brendon Tiszkad0b284b2023-02-08 20:43:18 +0000884 lpm_json = None
885 if args.lpm_json:
886 with open(args.lpm_json) as f:
887 lpm_json = json.loads(f.read())
888
Kai Ninomiya930e9182021-09-17 19:44:43 +0000889 renders = []
890
Kai Ninomiya930e9182021-09-17 19:44:43 +0000891 params_dawn = parse_json(loaded_json,
892 enabled_tags=['dawn', 'native', 'deprecated'])
fujunwei76bda372021-11-23 08:47:35 +0000893 metadata = params_dawn['metadata']
894 RENDER_PARAMS_BASE = make_base_render_params(metadata)
Corentin Wallez79a62bf2017-05-24 16:04:55 +0200895
fujunweic7d4f2c2021-12-07 00:46:35 +0000896 api = metadata.api.lower()
fujunweia8405742021-12-10 01:35:19 +0000897 prefix = metadata.proc_table_prefix.lower()
Ben Clayton35940f92022-02-04 17:15:16 +0000898 if 'headers' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000899 renders.append(
Ben Clayton9fb7a512022-02-04 18:18:18 +0000900 FileRender('api.h', 'include/dawn/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000901 [RENDER_PARAMS_BASE, params_dawn]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000902 renders.append(
903 FileRender('dawn_proc_table.h',
Ben Clayton9fb7a512022-02-04 18:18:18 +0000904 'include/dawn/' + prefix + '_proc_table.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000905 [RENDER_PARAMS_BASE, params_dawn]))
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400906
Ben Clayton35940f92022-02-04 17:15:16 +0000907 if 'cpp_headers' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000908 renders.append(
Ben Clayton9fb7a512022-02-04 18:18:18 +0000909 FileRender('api_cpp.h', 'include/dawn/' + api + '_cpp.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000910 [RENDER_PARAMS_BASE, params_dawn]))
Austin Engcc071e42019-10-16 10:26:01 +0000911
Austin Enga9e39e12021-06-01 18:49:12 +0000912 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000913 FileRender('api_cpp_print.h',
Ben Clayton9fb7a512022-02-04 18:18:18 +0000914 'include/dawn/' + api + '_cpp_print.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000915 [RENDER_PARAMS_BASE, params_dawn]))
Austin Enga9e39e12021-06-01 18:49:12 +0000916
Ben Clayton35940f92022-02-04 17:15:16 +0000917 if 'proc' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000918 renders.append(
fujunweia8405742021-12-10 01:35:19 +0000919 FileRender('dawn_proc.c', 'src/dawn/' + prefix + '_proc.c',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000920 [RENDER_PARAMS_BASE, params_dawn]))
Austin Eng16e01af2020-10-06 16:13:42 +0000921 renders.append(
922 FileRender('dawn_thread_dispatch_proc.cpp',
fujunweia8405742021-12-10 01:35:19 +0000923 'src/dawn/' + prefix + '_thread_dispatch_proc.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000924 [RENDER_PARAMS_BASE, params_dawn]))
Corentin Wallez96496822019-10-15 11:44:38 +0000925
Austin Eng63f65462021-12-09 20:03:48 +0000926 if 'webgpu_dawn_native_proc' in targets:
927 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000928 FileRender('dawn/native/api_dawn_native_proc.cpp',
929 'src/dawn/native/webgpu_dawn_native_proc.cpp',
Austin Eng63f65462021-12-09 20:03:48 +0000930 [RENDER_PARAMS_BASE, params_dawn]))
931
Ben Clayton35940f92022-02-04 17:15:16 +0000932 if 'cpp' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000933 renders.append(
fujunweid3cac112021-12-14 02:20:15 +0000934 FileRender('api_cpp.cpp', 'src/dawn/' + api + '_cpp.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000935 [RENDER_PARAMS_BASE, params_dawn]))
936
937 if 'webgpu_headers' in targets:
938 params_upstream = parse_json(loaded_json,
Shrek Shao1554a7d2022-03-08 20:56:10 +0000939 enabled_tags=['upstream', 'native'],
940 disabled_tags=['dawn'])
Kai Ninomiya930e9182021-09-17 19:44:43 +0000941 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000942 FileRender('api.h', 'webgpu-headers/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000943 [RENDER_PARAMS_BASE, params_upstream]))
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200944
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000945 if 'emscripten_bits' in targets:
Shrek Shaoee50bc02022-02-08 20:21:40 +0000946 params_emscripten = parse_json(loaded_json,
947 enabled_tags=['emscripten'])
Kai Ninomiya930e9182021-09-17 19:44:43 +0000948 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000949 FileRender('api.h', 'emscripten-bits/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000950 [RENDER_PARAMS_BASE, params_emscripten]))
951 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +0000952 FileRender('api_cpp.h', 'emscripten-bits/' + api + '_cpp.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000953 [RENDER_PARAMS_BASE, params_emscripten]))
954 renders.append(
fujunweid3cac112021-12-14 02:20:15 +0000955 FileRender('api_cpp.cpp', 'emscripten-bits/' + api + '_cpp.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000956 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000957 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000958 FileRender('api_struct_info.json',
959 'emscripten-bits/' + api + '_struct_info.json',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000960 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000961 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000962 FileRender('library_api_enum_tables.js',
963 'emscripten-bits/library_' + api + '_enum_tables.js',
Kai Ninomiya930e9182021-09-17 19:44:43 +0000964 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000965
fujunwei16ae3b82021-12-15 04:35:26 +0000966 if 'mock_api' in targets:
Corentin Wallez540abab2019-11-22 13:18:22 +0000967 mock_params = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000968 RENDER_PARAMS_BASE, params_dawn, {
Corentin Wallez540abab2019-11-22 13:18:22 +0000969 'has_callback_arguments': has_callback_arguments
970 }
971 ]
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000972 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000973 FileRender('mock_api.h', 'src/dawn/mock_' + api + '.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000974 mock_params))
975 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +0000976 FileRender('mock_api.cpp', 'src/dawn/mock_' + api + '.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000977 mock_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200978
Ben Clayton818001d2022-02-04 17:07:46 +0000979 if 'native_utils' in targets:
Corentin Wallez0c38e922019-06-07 08:59:17 +0000980 frontend_params = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000981 RENDER_PARAMS_BASE,
982 params_dawn,
Corentin Wallez0c38e922019-06-07 08:59:17 +0000983 {
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000984 # TODO: as_frontendType and co. take a Type, not a Name :(
fujunwei76bda372021-11-23 08:47:35 +0000985 'as_frontendType': lambda typ: as_frontendType(metadata, typ),
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000986 'as_annotated_frontendType': \
fujunwei76bda372021-11-23 08:47:35 +0000987 lambda arg: annotated(as_frontendType(metadata, arg.type), arg),
Corentin Wallez0c38e922019-06-07 08:59:17 +0000988 }
989 ]
Corentin Wallez59e7fad2018-08-16 15:32:35 +0200990
fujunweia2241d42021-12-16 04:54:38 +0000991 impl_dir = metadata.impl_dir + '/' if metadata.impl_dir else ''
Ben Clayton818001d2022-02-04 17:07:46 +0000992 native_dir = impl_dir + Name(metadata.native_namespace).Dirs()
fujunwei7f3f8ac2021-12-21 03:27:34 +0000993 namespace = metadata.namespace
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000994 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000995 FileRender('dawn/native/ValidationUtils.h',
fujunweia2241d42021-12-16 04:54:38 +0000996 'src/' + native_dir + '/ValidationUtils_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000997 frontend_params))
998 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +0000999 FileRender('dawn/native/ValidationUtils.cpp',
fujunweia2241d42021-12-16 04:54:38 +00001000 'src/' + native_dir + '/ValidationUtils_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001001 frontend_params))
1002 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001003 FileRender('dawn/native/dawn_platform.h',
fujunweifc38f7d2021-12-17 00:46:08 +00001004 'src/' + native_dir + '/' + prefix + '_platform_autogen.h',
Austin Eng3faa4782021-10-27 19:07:37 +00001005 frontend_params))
1006 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001007 FileRender('dawn/native/api_structs.h',
fujunwei7f3f8ac2021-12-21 03:27:34 +00001008 'src/' + native_dir + '/' + namespace + '_structs_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001009 frontend_params))
1010 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001011 FileRender('dawn/native/api_structs.cpp',
fujunwei7f3f8ac2021-12-21 03:27:34 +00001012 'src/' + native_dir + '/' + namespace + '_structs_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001013 frontend_params))
1014 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001015 FileRender('dawn/native/ProcTable.cpp',
Ningxin Hu7e5930b2021-12-22 06:12:13 +00001016 'src/' + native_dir + '/ProcTable.cpp', frontend_params))
Brian Ho5346e772021-04-22 17:49:42 +00001017 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001018 FileRender('dawn/native/ChainUtils.h',
fujunwei2b1dcd92021-12-22 01:05:03 +00001019 'src/' + native_dir + '/ChainUtils_autogen.h',
Brian Ho5346e772021-04-22 17:49:42 +00001020 frontend_params))
1021 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001022 FileRender('dawn/native/ChainUtils.cpp',
fujunwei2b1dcd92021-12-22 01:05:03 +00001023 'src/' + native_dir + '/ChainUtils_autogen.cpp',
Brian Ho5346e772021-04-22 17:49:42 +00001024 frontend_params))
Brandon Jonesba662952021-09-23 21:26:33 +00001025 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001026 FileRender('dawn/native/api_absl_format.h',
fujunweif001ef52021-12-23 05:16:04 +00001027 'src/' + native_dir + '/' + api + '_absl_format_autogen.h',
Brandon Jonesba662952021-09-23 21:26:33 +00001028 frontend_params))
1029 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001030 FileRender('dawn/native/api_absl_format.cpp',
fujunweif001ef52021-12-23 05:16:04 +00001031 'src/' + native_dir + '/' + api + '_absl_format_autogen.cpp',
Brandon Jonesba662952021-09-23 21:26:33 +00001032 frontend_params))
Loko Kung8d195d52021-09-28 15:40:01 +00001033 renders.append(
Austin Engbc285fb2022-07-29 00:36:21 +00001034 FileRender(
1035 'dawn/native/api_StreamImpl.cpp', 'src/' + native_dir +
1036 '/' + api + '_StreamImpl_autogen.cpp', frontend_params))
1037 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001038 FileRender('dawn/native/ObjectType.h',
fujunwei2b1dcd92021-12-22 01:05:03 +00001039 'src/' + native_dir + '/ObjectType_autogen.h',
Loko Kung8d195d52021-09-28 15:40:01 +00001040 frontend_params))
1041 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001042 FileRender('dawn/native/ObjectType.cpp',
fujunwei2b1dcd92021-12-22 01:05:03 +00001043 'src/' + native_dir + '/ObjectType_autogen.cpp',
Loko Kung8d195d52021-09-28 15:40:01 +00001044 frontend_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001045
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001046 if 'wire' in targets:
Austin Eng2f218e22021-12-22 19:02:23 +00001047 params_dawn_wire = parse_json(loaded_json,
1048 enabled_tags=['dawn', 'deprecated'],
1049 disabled_tags=['native'])
1050 additional_params = compute_wire_params(params_dawn_wire,
1051 wire_json)
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001052
Corentin Wallez0c38e922019-06-07 08:59:17 +00001053 wire_params = [
Austin Eng2f218e22021-12-22 19:02:23 +00001054 RENDER_PARAMS_BASE, params_dawn_wire, {
fujunwei76bda372021-11-23 08:47:35 +00001055 'as_wireType': lambda type : as_wireType(metadata, type),
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001056 'as_annotated_wireType': \
fujunwei76bda372021-11-23 08:47:35 +00001057 lambda arg: annotated(as_wireType(metadata, arg.type), arg),
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001058 }, additional_params
Corentin Wallez0c38e922019-06-07 08:59:17 +00001059 ]
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001060 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001061 FileRender('dawn/wire/ObjectType.h',
1062 'src/dawn/wire/ObjectType_autogen.h', wire_params))
Austin Eng3120d5e2020-11-11 19:46:18 +00001063 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001064 FileRender('dawn/wire/WireCmd.h',
1065 'src/dawn/wire/WireCmd_autogen.h', wire_params))
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001066 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001067 FileRender('dawn/wire/WireCmd.cpp',
1068 'src/dawn/wire/WireCmd_autogen.cpp', wire_params))
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001069 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001070 FileRender('dawn/wire/client/ApiObjects.h',
1071 'src/dawn/wire/client/ApiObjects_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001072 wire_params))
1073 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001074 FileRender('dawn/wire/client/ApiProcs.cpp',
1075 'src/dawn/wire/client/ApiProcs_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001076 wire_params))
1077 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001078 FileRender('dawn/wire/client/ClientBase.h',
1079 'src/dawn/wire/client/ClientBase_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001080 wire_params))
1081 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001082 FileRender('dawn/wire/client/ClientHandlers.cpp',
1083 'src/dawn/wire/client/ClientHandlers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001084 wire_params))
1085 renders.append(
1086 FileRender(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001087 'dawn/wire/client/ClientPrototypes.inc',
1088 'src/dawn/wire/client/ClientPrototypes_autogen.inc',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001089 wire_params))
1090 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001091 FileRender('dawn/wire/server/ServerBase.h',
1092 'src/dawn/wire/server/ServerBase_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001093 wire_params))
1094 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001095 FileRender('dawn/wire/server/ServerDoers.cpp',
1096 'src/dawn/wire/server/ServerDoers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001097 wire_params))
1098 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001099 FileRender('dawn/wire/server/ServerHandlers.cpp',
1100 'src/dawn/wire/server/ServerHandlers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001101 wire_params))
1102 renders.append(
1103 FileRender(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001104 'dawn/wire/server/ServerPrototypes.inc',
1105 'src/dawn/wire/server/ServerPrototypes_autogen.inc',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001106 wire_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001107
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001108 if 'dawn_lpmfuzz_proto' in targets:
1109 params_dawn_wire = parse_json(loaded_json,
1110 enabled_tags=['dawn', 'deprecated'],
1111 disabled_tags=['native'])
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001112 api_and_wire_params = compute_wire_params(params_dawn_wire,
1113 wire_json)
1114
1115 fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001116
1117 lpm_params = [
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001118 RENDER_PARAMS_BASE, params_dawn_wire, {
1119 'as_protobufTypeLPM': as_protobufTypeLPM,
1120 'as_protobufNameLPM': as_protobufNameLPM,
1121 'unreachable': unreachable_code
1122 }, api_and_wire_params, fuzzer_params
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001123 ]
1124
1125 renders.append(
1126 FileRender('dawn/fuzzers/lpmfuzz/dawn_lpm.proto',
1127 'src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.proto',
1128 lpm_params))
1129
1130 if 'dawn_lpmfuzz_cpp' in targets:
1131 params_dawn_wire = parse_json(loaded_json,
1132 enabled_tags=['dawn', 'deprecated'],
1133 disabled_tags=['native'])
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001134 api_and_wire_params = compute_wire_params(params_dawn_wire,
1135 wire_json)
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001136
1137 lpm_params = [
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001138 RENDER_PARAMS_BASE, params_dawn_wire, {}, api_and_wire_params
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001139 ]
1140
1141 renders.append(
1142 FileRender(
1143 'dawn/fuzzers/lpmfuzz/DawnLPMSerializer.cpp',
1144 'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.cpp',
1145 lpm_params))
1146
1147 renders.append(
1148 FileRender(
1149 'dawn/fuzzers/lpmfuzz/DawnLPMSerializer.h',
1150 'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h',
1151 lpm_params))
1152
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001153 renders.append(
1154 FileRender(
1155 'dawn/fuzzers/lpmfuzz/DawnLPMConstants.h',
1156 'src/dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h',
1157 lpm_params))
1158
Corentin Wallez0c38e922019-06-07 08:59:17 +00001159 return renders
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001160
Corentin Wallez0c38e922019-06-07 08:59:17 +00001161 def get_dependencies(self, args):
1162 deps = [os.path.abspath(args.dawn_json)]
1163 if args.wire_json != None:
1164 deps += [os.path.abspath(args.wire_json)]
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001165 if args.lpm_json != None:
1166 deps += [os.path.abspath(args.lpm_json)]
Corentin Wallez0c38e922019-06-07 08:59:17 +00001167 return deps
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001168
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001169
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001170if __name__ == '__main__':
Corentin Wallez0c38e922019-06-07 08:59:17 +00001171 sys.exit(run_generator(MultiGeneratorFromDawnJSON()))