blob: 23ebc55535c8b62af4d2016ddb1962af63c45a91 [file] [log] [blame]
Corentin Wallez59382b72020-04-17 20:43:07 +00001#!/usr/bin/env python3
Austin Engcc2516a2023-10-17 20:57:54 +00002# Copyright 2017 The Dawn & Tint Authors
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04003#
Austin Engcc2516a2023-10-17 20:57:54 +00004# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04006#
Austin Engcc2516a2023-10-17 20:57:54 +00007# 1. Redistributions of source code must retain the above copyright notice, this
8# list of conditions and the following disclaimer.
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04009#
Austin Engcc2516a2023-10-17 20:57:54 +000010# 2. Redistributions in binary form must reproduce the above copyright notice,
11# this list of conditions and the following disclaimer in the documentation
12# and/or other materials provided with the distribution.
13#
14# 3. Neither the name of the copyright holder nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040028
Corentin Wallez0c38e922019-06-07 08:59:17 +000029import json, os, sys
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040030from collections import namedtuple
Corentin Wallez0c38e922019-06-07 08:59:17 +000031
Corentin Wallez0c38e922019-06-07 08:59:17 +000032from generator_lib import Generator, run_generator, FileRender
Corentin Wallez031fbbb2019-06-11 18:03:05 +000033
34############################################################
35# OBJECT MODEL
36############################################################
37
Kai Ninomiya01aeca22020-07-15 19:51:17 +000038
fujunwei76bda372021-11-23 08:47:35 +000039class Metadata:
40 def __init__(self, metadata):
41 self.api = metadata['api']
42 self.namespace = metadata['namespace']
43 self.c_prefix = metadata.get('c_prefix', self.namespace.upper())
fujunwei3a464762021-12-05 05:29:44 +000044 self.proc_table_prefix = metadata['proc_table_prefix']
fujunweia2241d42021-12-16 04:54:38 +000045 self.impl_dir = metadata.get('impl_dir', '')
46 self.native_namespace = metadata['native_namespace']
fujunwei76bda372021-11-23 08:47:35 +000047 self.copyright_year = metadata.get('copyright_year', None)
Jim Blackler2e2d1d72024-03-27 18:54:55 +000048 self.kotlin_package = 'android.dawn'
49 self.kotlin_path = self.kotlin_package.replace('.', '/')
fujunwei76bda372021-11-23 08:47:35 +000050
Corentin Wallez031fbbb2019-06-11 18:03:05 +000051class Name:
52 def __init__(self, name, native=False):
53 self.native = native
Austin Eng76a8d0b2020-04-03 17:37:48 +000054 self.name = name
Corentin Wallez031fbbb2019-06-11 18:03:05 +000055 if native:
56 self.chunks = [name]
57 else:
58 self.chunks = name.split(' ')
59
Austin Eng76a8d0b2020-04-03 17:37:48 +000060 def get(self):
61 return self.name
62
Corentin Wallez031fbbb2019-06-11 18:03:05 +000063 def CamelChunk(self, chunk):
64 return chunk[0].upper() + chunk[1:]
65
66 def canonical_case(self):
Corentin Wallez7d256c72023-12-01 16:27:15 +000067 return ' '.join(self.chunks)
Corentin Wallez031fbbb2019-06-11 18:03:05 +000068
69 def concatcase(self):
70 return ''.join(self.chunks)
71
72 def camelCase(self):
Kai Ninomiya01aeca22020-07-15 19:51:17 +000073 return self.chunks[0] + ''.join(
74 [self.CamelChunk(chunk) for chunk in self.chunks[1:]])
Corentin Wallez031fbbb2019-06-11 18:03:05 +000075
76 def CamelCase(self):
77 return ''.join([self.CamelChunk(chunk) for chunk in self.chunks])
78
79 def SNAKE_CASE(self):
80 return '_'.join([chunk.upper() for chunk in self.chunks])
81
82 def snake_case(self):
83 return '_'.join(self.chunks)
84
Corentin Wallezec9cf2a2022-01-12 09:17:35 +000085 def namespace_case(self):
86 return '::'.join(self.chunks)
87
Ben Clayton20cbe6d2022-02-04 12:51:25 +000088 def Dirs(self):
89 return '/'.join(self.chunks)
90
Kai Ninomiya7b6246a2020-01-28 23:54:38 +000091 def js_enum_case(self):
92 result = self.chunks[0].lower()
93 for chunk in self.chunks[1:]:
94 if not result[-1].isdigit():
95 result += '-'
96 result += chunk.lower()
97 return result
98
Kai Ninomiya01aeca22020-07-15 19:51:17 +000099
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000100def concat_names(*names):
101 return ' '.join([name.canonical_case() for name in names])
102
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000103
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000104class Type:
105 def __init__(self, name, json_data, native=False):
106 self.json_data = json_data
107 self.dict_name = name
108 self.name = Name(name, native=native)
109 self.category = json_data['category']
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000110 self.is_wire_transparent = False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000111
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000112
Kai Ninomiya930e9182021-09-17 19:44:43 +0000113EnumValue = namedtuple('EnumValue', ['name', 'value', 'valid', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000114
115
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000116class EnumType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000117 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000118 Type.__init__(self, name, json_data)
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000119
120 self.values = []
Kai Ninomiya98dce272024-01-04 08:14:00 +0000121 self.hasUndefined = False
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000122 self.contiguousFromZero = True
123 lastValue = -1
124 for m in self.json_data['values']:
Kai Ninomiya930e9182021-09-17 19:44:43 +0000125 if not is_enabled(m):
126 continue
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000127 value = m['value']
Kai Ninomiya98dce272024-01-04 08:14:00 +0000128 name = m['name']
129 if name == "undefined":
130 assert value == 0
131 self.hasUndefined = True
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000132 if value != lastValue + 1:
133 self.contiguousFromZero = False
134 lastValue = value
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000135 self.values.append(
Kai Ninomiya98dce272024-01-04 08:14:00 +0000136 EnumValue(Name(name), value, m.get('valid', True), m))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000137
Corentin Wallez7ac08152019-06-26 19:54:43 +0000138 # Assert that all values are unique in enums
139 all_values = set()
140 for value in self.values:
141 if value.value in all_values:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000142 raise Exception("Duplicate value {} in enum {}".format(
143 value.value, name))
Corentin Wallez7ac08152019-06-26 19:54:43 +0000144 all_values.add(value.value)
Jiawei Shao6d6b63c2021-12-02 07:29:41 +0000145 self.is_wire_transparent = True
Corentin Wallez7ac08152019-06-26 19:54:43 +0000146
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000147
Kai Ninomiya930e9182021-09-17 19:44:43 +0000148BitmaskValue = namedtuple('BitmaskValue', ['name', 'value', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000149
150
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000151class BitmaskType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000152 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000153 Type.__init__(self, name, json_data)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000154 self.values = [
Kai Ninomiya930e9182021-09-17 19:44:43 +0000155 BitmaskValue(Name(m['name']), m['value'], m)
156 for m in self.json_data['values'] if is_enabled(m)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000157 ]
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000158 self.full_mask = 0
159 for value in self.values:
160 self.full_mask = self.full_mask | value.value
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
fujunwei23f71622021-12-02 07:41:21 +0000164class FunctionPointerType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000165 def __init__(self, is_enabled, name, json_data):
Corentin Wallez540abab2019-11-22 13:18:22 +0000166 Type.__init__(self, name, json_data)
fujunwei23f71622021-12-02 07:41:21 +0000167 self.return_type = None
Corentin Wallez540abab2019-11-22 13:18:22 +0000168 self.arguments = []
169
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000170
Brandon Jones58a471a2021-02-08 19:48:06 +0000171class TypedefType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000172 def __init__(self, is_enabled, name, json_data):
Brandon Jones58a471a2021-02-08 19:48:06 +0000173 Type.__init__(self, name, json_data)
174 self.type = None
175
176
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000177class NativeType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000178 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000179 Type.__init__(self, name, json_data, native=True)
Loko Kung837f1512023-06-06 03:01:15 +0000180 self.is_wire_transparent = json_data.get('wire transparent', True)
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000181
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000182
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000183# Methods and structures are both "records", so record members correspond to
184# method arguments or structure members.
185class RecordMember:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000186 def __init__(self,
187 name,
188 typ,
189 annotation,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000190 json_data,
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000191 optional=False,
192 is_return_value=False,
193 default_value=None,
Austin Eng6a5418a2019-07-19 16:01:48 +0000194 skip_serialize=False):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000195 self.name = name
196 self.type = typ
197 self.annotation = annotation
Kai Ninomiya930e9182021-09-17 19:44:43 +0000198 self.json_data = json_data
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000199 self.length = None
200 self.optional = optional
201 self.is_return_value = is_return_value
202 self.handle_type = None
Brendon Tiszka27521c62023-05-15 22:22:07 +0000203 self.id_type = None
Corentin Wallez8f938712019-07-08 19:20:22 +0000204 self.default_value = default_value
Austin Eng6a5418a2019-07-19 16:01:48 +0000205 self.skip_serialize = skip_serialize
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000206
207 def set_handle_type(self, handle_type):
208 assert self.type.dict_name == "ObjectHandle"
209 self.handle_type = handle_type
210
Brendon Tiszka27521c62023-05-15 22:22:07 +0000211 def set_id_type(self, id_type):
212 assert self.type.dict_name == "ObjectId"
213 self.id_type = id_type
214
Kai Ninomiyaa8516c12024-01-09 03:33:23 +0000215 @property
216 def requires_struct_defaulting(self):
217 if self.annotation != "value":
218 return False
219
220 if self.type.category == "structure":
221 return self.type.any_member_requires_struct_defaulting
222 elif self.type.category == "enum":
223 return (self.type.hasUndefined
224 and self.default_value not in [None, "undefined"])
225 else:
226 return False
227
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000228
Le Hoang Quyen7971bfe2023-04-05 19:35:07 +0000229Method = namedtuple(
230 'Method', ['name', 'return_type', 'arguments', 'autolock', 'json_data'])
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000231
232
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000233class ObjectType(Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000234 def __init__(self, is_enabled, name, json_data):
235 json_data_override = {'methods': []}
236 if 'methods' in json_data:
237 json_data_override['methods'] = [
238 m for m in json_data['methods'] if is_enabled(m)
239 ]
240 Type.__init__(self, name, dict(json_data, **json_data_override))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000241
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000242
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000243class Record:
244 def __init__(self, name):
245 self.name = Name(name)
246 self.members = []
Austin Eng76a8d0b2020-04-03 17:37:48 +0000247 self.may_have_dawn_object = False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000248
249 def update_metadata(self):
Austin Eng76a8d0b2020-04-03 17:37:48 +0000250 def may_have_dawn_object(member):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000251 if isinstance(member.type, ObjectType):
252 return True
253 elif isinstance(member.type, StructureType):
Austin Eng76a8d0b2020-04-03 17:37:48 +0000254 return member.type.may_have_dawn_object
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000255 else:
256 return False
257
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000258 self.may_have_dawn_object = any(
259 may_have_dawn_object(member) for member in self.members)
Austin Eng76a8d0b2020-04-03 17:37:48 +0000260
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000261 # Set may_have_dawn_object to true if the type is chained or
262 # extensible. Chained structs may contain a Dawn object.
Austin Eng76a8d0b2020-04-03 17:37:48 +0000263 if isinstance(self, StructureType):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000264 self.may_have_dawn_object = (self.may_have_dawn_object
265 or self.chained or self.extensible)
266
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000267
268class StructureType(Record, Type):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000269 def __init__(self, is_enabled, name, json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000270 Record.__init__(self, name)
Kai Ninomiya930e9182021-09-17 19:44:43 +0000271 json_data_override = {}
272 if 'members' in json_data:
273 json_data_override['members'] = [
274 m for m in json_data['members'] if is_enabled(m)
275 ]
276 Type.__init__(self, name, dict(json_data, **json_data_override))
Corentin Walleza45561b2022-07-14 12:58:25 +0000277 self.chained = json_data.get('chained', None)
278 self.extensible = json_data.get('extensible', None)
Austin Eng0c824052021-09-20 16:07:25 +0000279 if self.chained:
Corentin Walleza45561b2022-07-14 12:58:25 +0000280 assert self.chained == 'in' or self.chained == 'out'
281 assert 'chain roots' in json_data
Loko Kung0af86f22023-08-17 23:39:51 +0000282 self.chain_roots = []
Austin Eng0c824052021-09-20 16:07:25 +0000283 if self.extensible:
Corentin Walleza45561b2022-07-14 12:58:25 +0000284 assert self.extensible == 'in' or self.extensible == 'out'
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000285 # Chained structs inherit from wgpu::ChainedStruct, which has
286 # nextInChain, so setting both extensible and chained would result in
287 # two nextInChain members.
288 assert not (self.extensible and self.chained)
Loko Kung0af86f22023-08-17 23:39:51 +0000289 self.extensions = []
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000290
Jiawei Shao1fa386c2021-12-21 04:04:51 +0000291 def update_metadata(self):
292 Record.update_metadata(self)
293
294 if self.may_have_dawn_object:
295 self.is_wire_transparent = False
296 return
297
298 assert not (self.chained or self.extensible)
299
300 def get_is_wire_transparent(member):
301 return member.type.is_wire_transparent and member.annotation == 'value'
302
303 self.is_wire_transparent = all(
304 get_is_wire_transparent(m) for m in self.members)
305
Austin Eng0c824052021-09-20 16:07:25 +0000306 @property
307 def output(self):
308 return self.chained == "out" or self.extensible == "out"
309
Austin Eng643625a2023-08-09 00:59:33 +0000310 @property
311 def has_free_members_function(self):
312 if not self.output:
313 return False
314 for m in self.members:
315 if m.annotation != 'value':
316 return True
317 return False
318
Kai Ninomiya98dce272024-01-04 08:14:00 +0000319 @property
320 def any_member_requires_struct_defaulting(self):
321 return any(member.requires_struct_defaulting
322 for member in self.members)
323
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000324
fujunwei4e876902021-11-25 08:44:01 +0000325class ConstantDefinition():
326 def __init__(self, is_enabled, name, json_data):
327 self.type = None
328 self.value = json_data['value']
329 self.json_data = json_data
330 self.name = Name(name)
331
332
fujunwei23f71622021-12-02 07:41:21 +0000333class FunctionDeclaration():
Austin Eng643625a2023-08-09 00:59:33 +0000334 def __init__(self, is_enabled, name, json_data, no_cpp=False):
fujunwei23f71622021-12-02 07:41:21 +0000335 self.return_type = None
336 self.arguments = []
337 self.json_data = json_data
338 self.name = Name(name)
Austin Eng643625a2023-08-09 00:59:33 +0000339 self.no_cpp = no_cpp
fujunwei23f71622021-12-02 07:41:21 +0000340
341
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000342class Command(Record):
343 def __init__(self, name, members=None):
344 Record.__init__(self, name)
345 self.members = members or []
346 self.derived_object = None
347 self.derived_method = None
348
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000349
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000350def linked_record_members(json_data, types):
351 members = []
352 members_by_name = {}
353 for m in json_data:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000354 member = RecordMember(Name(m['name']),
355 types[m['type']],
Corentin Wallez8f938712019-07-08 19:20:22 +0000356 m.get('annotation', 'value'),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000357 m,
Corentin Wallez8f938712019-07-08 19:20:22 +0000358 optional=m.get('optional', False),
359 is_return_value=m.get('is_return_value', False),
Austin Eng6a5418a2019-07-19 16:01:48 +0000360 default_value=m.get('default', None),
361 skip_serialize=m.get('skip_serialize', False))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000362 handle_type = m.get('handle_type')
363 if handle_type:
364 member.set_handle_type(types[handle_type])
Brendon Tiszka27521c62023-05-15 22:22:07 +0000365 id_type = m.get('id_type')
366 if id_type:
367 member.set_id_type(types[id_type])
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000368 members.append(member)
369 members_by_name[member.name.canonical_case()] = member
370
371 for (member, m) in zip(members, json_data):
372 if member.annotation != 'value':
373 if not 'length' in m:
374 if member.type.category != 'object':
375 member.length = "constant"
376 member.constant_length = 1
377 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000378 assert False
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000379 elif m['length'] == 'strlen':
380 member.length = 'strlen'
Yan52040532021-12-15 04:08:56 +0000381 elif isinstance(m['length'], int):
382 assert m['length'] > 0
383 member.length = "constant"
384 member.constant_length = m['length']
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000385 else:
386 member.length = members_by_name[m['length']]
387
388 return members
Corentin Walleza6416542018-05-17 16:55:53 -0400389
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000390
Brendon Tiszka27521c62023-05-15 22:22:07 +0000391def mark_lengths_non_serializable_lpm(record_members):
392 # Remove member length values from command metadata,
393 # these are set to the length of the protobuf array.
394 for record_member in record_members:
395 lengths = set()
396 for member in record_member.members:
397 lengths.add(member.length)
398
399 for member in record_member.members:
400 if member in lengths:
401 member.skip_serialize = True
402
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400403############################################################
404# PARSE
405############################################################
Corentin Wallez4b410a32017-04-20 14:42:36 -0400406
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000407
Corentin Walleze2f94842018-12-05 17:49:04 +0000408def link_object(obj, types):
Le Hoang Quyen7971bfe2023-04-05 19:35:07 +0000409 # Disable method's autolock if obj's "no autolock" = True
410 obj_scoped_autolock_enabled = not obj.json_data.get('no autolock', False)
411
Corentin Walleze2f94842018-12-05 17:49:04 +0000412 def make_method(json_data):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000413 arguments = linked_record_members(json_data.get('args', []), types)
Le Hoang Quyen7971bfe2023-04-05 19:35:07 +0000414 autolock_enabled = obj_scoped_autolock_enabled and not json_data.get(
415 'no autolock', False)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000416 return Method(Name(json_data['name']),
Le Hoang Quyen7971bfe2023-04-05 19:35:07 +0000417 types[json_data.get('returns', 'void')], arguments,
418 autolock_enabled, json_data)
Corentin Walleze2f94842018-12-05 17:49:04 +0000419
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000420 obj.methods = [make_method(m) for m in obj.json_data.get('methods', [])]
Corentin Wallez97231682019-10-08 07:38:01 +0000421 obj.methods.sort(key=lambda method: method.name.canonical_case())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400422
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000423
Corentin Walleza6416542018-05-17 16:55:53 -0400424def link_structure(struct, types):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000425 struct.members = linked_record_members(struct.json_data['members'], types)
Loko Kung0af86f22023-08-17 23:39:51 +0000426 for root in struct.json_data.get('chain roots', []):
427 struct.chain_roots.append(types[root])
428 types[root].extensions.append(struct)
Corentin Walleza45561b2022-07-14 12:58:25 +0000429 struct.chain_roots = [types[root] for root in struct.json_data.get('chain roots', [])]
430 assert all((root.category == 'structure' for root in struct.chain_roots))
Corentin Walleza6416542018-05-17 16:55:53 -0400431
Corentin Wallez540abab2019-11-22 13:18:22 +0000432
fujunwei23f71622021-12-02 07:41:21 +0000433def link_function_pointer(function_pointer, types):
434 link_function(function_pointer, types)
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000435
436
Brandon Jones58a471a2021-02-08 19:48:06 +0000437def link_typedef(typedef, types):
438 typedef.type = types[typedef.json_data['type']]
439
440
fujunwei4e876902021-11-25 08:44:01 +0000441def link_constant(constant, types):
442 constant.type = types[constant.json_data['type']]
443 assert constant.type.name.native
444
445
fujunwei23f71622021-12-02 07:41:21 +0000446def link_function(function, types):
447 function.return_type = types[function.json_data.get('returns', 'void')]
448 function.arguments = linked_record_members(function.json_data['args'],
449 types)
450
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000451# Sort structures so that if struct A has struct B as a member, then B is
452# listed before A.
453#
454# This is a form of topological sort where we try to keep the order reasonably
455# similar to the original order (though the sort isn't technically stable).
456#
457# It works by computing for each struct type what is the depth of its DAG of
Kai Ninomiya7d174a12021-09-21 17:36:27 +0000458# dependents, then re-sorting based on that depth using Python's stable sort.
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000459# This makes a toposort because if A depends on B then its depth will be bigger
460# than B's. It is also nice because all nodes with the same depth are kept in
461# the input order.
Corentin Wallez29353d62018-09-18 12:49:22 +0000462def topo_sort_structure(structs):
463 for struct in structs:
464 struct.visited = False
465 struct.subdag_depth = 0
466
467 def compute_depth(struct):
468 if struct.visited:
469 return struct.subdag_depth
470
471 max_dependent_depth = 0
472 for member in struct.members:
Corentin Walleze2f94842018-12-05 17:49:04 +0000473 if member.type.category == 'structure':
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000474 max_dependent_depth = max(max_dependent_depth,
475 compute_depth(member.type) + 1)
Corentin Wallez29353d62018-09-18 12:49:22 +0000476
477 struct.subdag_depth = max_dependent_depth
478 struct.visited = True
479 return struct.subdag_depth
480
481 for struct in structs:
482 compute_depth(struct)
483
484 result = sorted(structs, key=lambda struct: struct.subdag_depth)
485
486 for struct in structs:
487 del struct.visited
488 del struct.subdag_depth
489
490 return result
491
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000492
Austin Eng2f218e22021-12-22 19:02:23 +0000493def parse_json(json, enabled_tags, disabled_tags=None):
494 is_enabled = lambda json_data: item_is_enabled(
495 enabled_tags, json_data) and not item_is_disabled(
496 disabled_tags, json_data)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400497 category_to_parser = {
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000498 'bitmask': BitmaskType,
499 'enum': EnumType,
500 'native': NativeType,
fujunwei23f71622021-12-02 07:41:21 +0000501 'function pointer': FunctionPointerType,
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000502 'object': ObjectType,
503 'structure': StructureType,
Brandon Jones58a471a2021-02-08 19:48:06 +0000504 'typedef': TypedefType,
fujunwei4e876902021-11-25 08:44:01 +0000505 'constant': ConstantDefinition,
fujunwei23f71622021-12-02 07:41:21 +0000506 'function': FunctionDeclaration
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400507 }
508
509 types = {}
510
511 by_category = {}
512 for name in category_to_parser.keys():
513 by_category[name] = []
514
Corentin Walleze2f94842018-12-05 17:49:04 +0000515 for (name, json_data) in json.items():
Austin Eng2f218e22021-12-22 19:02:23 +0000516 if name[0] == '_' or not is_enabled(json_data):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400517 continue
Corentin Walleze2f94842018-12-05 17:49:04 +0000518 category = json_data['category']
Kai Ninomiya930e9182021-09-17 19:44:43 +0000519 parsed = category_to_parser[category](is_enabled, name, json_data)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400520 by_category[category].append(parsed)
521 types[name] = parsed
522
523 for obj in by_category['object']:
524 link_object(obj, types)
525
Corentin Walleza6416542018-05-17 16:55:53 -0400526 for struct in by_category['structure']:
527 link_structure(struct, types)
528
Austin Eng643625a2023-08-09 00:59:33 +0000529 if struct.has_free_members_function:
530 name = struct.name.get() + " free members"
531 func_decl = FunctionDeclaration(
532 True,
533 name, {
534 "returns":
535 "void",
536 "args": [{
537 "name": "value",
538 "type": struct.name.get(),
539 "annotation": "value",
540 }]
541 },
542 no_cpp=True)
543 types[name] = func_decl
544 by_category['function'].append(func_decl)
545
fujunwei23f71622021-12-02 07:41:21 +0000546 for function_pointer in by_category['function pointer']:
547 link_function_pointer(function_pointer, types)
Corentin Wallez540abab2019-11-22 13:18:22 +0000548
Brandon Jones58a471a2021-02-08 19:48:06 +0000549 for typedef in by_category['typedef']:
550 link_typedef(typedef, types)
551
fujunwei4e876902021-11-25 08:44:01 +0000552 for constant in by_category['constant']:
553 link_constant(constant, types)
554
fujunwei23f71622021-12-02 07:41:21 +0000555 for function in by_category['function']:
556 link_function(function, types)
557
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400558 for category in by_category.keys():
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000559 by_category[category] = sorted(
560 by_category[category], key=lambda typ: typ.name.canonical_case())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400561
Corentin Wallez29353d62018-09-18 12:49:22 +0000562 by_category['structure'] = topo_sort_structure(by_category['structure'])
563
Austin Engc7f416c2019-01-15 20:49:53 +0000564 for struct in by_category['structure']:
565 struct.update_metadata()
566
Kai Ninomiya930e9182021-09-17 19:44:43 +0000567 api_params = {
568 'types': types,
569 'by_category': by_category,
570 'enabled_tags': enabled_tags,
Austin Eng2f218e22021-12-22 19:02:23 +0000571 'disabled_tags': disabled_tags,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000572 }
573 return {
fujunwei76bda372021-11-23 08:47:35 +0000574 'metadata': Metadata(json['_metadata']),
Kai Ninomiya930e9182021-09-17 19:44:43 +0000575 'types': types,
576 'by_category': by_category,
577 'enabled_tags': enabled_tags,
Austin Eng2f218e22021-12-22 19:02:23 +0000578 'disabled_tags': disabled_tags,
Kai Ninomiya930e9182021-09-17 19:44:43 +0000579 'c_methods': lambda typ: c_methods(api_params, typ),
580 'c_methods_sorted_by_name': get_c_methods_sorted_by_name(api_params),
581 }
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000582
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400583
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000584############################################################
585# WIRE STUFF
586############################################################
587
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000588
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000589# Create wire commands from api methods
590def compute_wire_params(api_params, wire_json):
591 wire_params = api_params.copy()
592 types = wire_params['types']
593
594 commands = []
595 return_commands = []
596
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000597 wire_json['special items']['client_handwritten_commands'] += wire_json[
598 'special items']['client_side_commands']
Corentin Wallez540abab2019-11-22 13:18:22 +0000599
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000600 # Generate commands from object methods
601 for api_object in wire_params['by_category']['object']:
602 for method in api_object.methods:
603 command_name = concat_names(api_object.name, method.name)
604 command_suffix = Name(command_name).CamelCase()
605
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000606 # Only object return values or void are supported.
607 # Other methods must be handwritten.
608 is_object = method.return_type.category == 'object'
609 is_void = method.return_type.name.canonical_case() == 'void'
610 if not (is_object or is_void):
611 assert command_suffix in (
Kai Ninomiya8d524b22023-09-02 01:11:30 +0000612 wire_json['special items']['client_handwritten_commands']
613 ), command_suffix
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000614 continue
615
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000616 if command_suffix in (
617 wire_json['special items']['client_side_commands']):
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000618 continue
619
620 # Create object method commands by prepending "self"
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000621 members = [
622 RecordMember(Name('self'), types[api_object.dict_name],
Kai Ninomiya930e9182021-09-17 19:44:43 +0000623 'value', {})
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000624 ]
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000625 members += method.arguments
626
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000627 # Client->Server commands that return an object return the
628 # result object handle
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000629 if method.return_type.category == 'object':
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000630 result = RecordMember(Name('result'),
631 types['ObjectHandle'],
Kai Ninomiya930e9182021-09-17 19:44:43 +0000632 'value', {},
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000633 is_return_value=True)
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000634 result.set_handle_type(method.return_type)
635 members.append(result)
636
637 command = Command(command_name, members)
638 command.derived_object = api_object
639 command.derived_method = method
640 commands.append(command)
641
642 for (name, json_data) in wire_json['commands'].items():
643 commands.append(Command(name, linked_record_members(json_data, types)))
644
645 for (name, json_data) in wire_json['return commands'].items():
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000646 return_commands.append(
647 Command(name, linked_record_members(json_data, types)))
Corentin Wallez031fbbb2019-06-11 18:03:05 +0000648
649 wire_params['cmd_records'] = {
650 'command': commands,
651 'return command': return_commands
652 }
653
654 for commands in wire_params['cmd_records'].values():
655 for command in commands:
656 command.update_metadata()
657 commands.sort(key=lambda c: c.name.canonical_case())
658
659 wire_params.update(wire_json.get('special items', {}))
660
661 return wire_params
662
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000663############################################################
664# DAWN LPM FUZZ STUFF
665############################################################
666
667
668def compute_lpm_params(api_and_wire_params, lpm_json):
669 # Start with all commands in dawn.json and dawn_wire.json
670 lpm_params = api_and_wire_params.copy()
671
Brendon Tiszka1f8413f2023-05-02 21:41:22 +0000672 # Commands that are built through codegen
673 generated_commands = []
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000674
675 # All commands, including hand written commands that we can't generate
676 # through codegen
Brendon Tiszka1f8413f2023-05-02 21:41:22 +0000677 all_commands = []
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000678
679 # Remove blocklisted commands from protobuf generation params
680 blocklisted_cmds_proto = lpm_json.get('blocklisted_cmds')
681 custom_cmds_proto = lpm_json.get('custom_cmds')
682 for command in lpm_params['cmd_records']['command']:
683 blocklisted = command.name.get() in blocklisted_cmds_proto
684 custom = command.name.get() in custom_cmds_proto
685
Brendon Tiszka1f8413f2023-05-02 21:41:22 +0000686 if blocklisted:
687 continue
688
689 if not custom:
690 generated_commands.append(command)
691 all_commands.append(command)
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000692
Brendon Tiszka27521c62023-05-15 22:22:07 +0000693 # Set all fields that are marked as the "length" of another field to
694 # skip_serialize. The values passed by libprotobuf-mutator will cause
695 # an instant crash during serialization if these don't match the length
696 # of the data they are passing. These values aren't used in
697 # deserialization.
698 mark_lengths_non_serializable_lpm(
699 api_and_wire_params['cmd_records']['command'])
700 mark_lengths_non_serializable_lpm(
701 api_and_wire_params['by_category']['structure'])
702
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000703 lpm_params['cmd_records'] = {
Brendon Tiszka1f8413f2023-05-02 21:41:22 +0000704 'proto_generated_commands': generated_commands,
705 'proto_all_commands': all_commands,
Brendon Tiszka27521c62023-05-15 22:22:07 +0000706 'cpp_generated_commands': generated_commands,
707 'lpm_info': lpm_json.get("lpm_info")
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000708 }
709
710 return lpm_params
711
712
713def as_protobufTypeLPM(member):
714 assert 'type' in member.json_data
715
716 if member.type.name.native:
717 typ = member.json_data['type']
718 cpp_to_protobuf_type = {
719 "bool": "bool",
720 "float": "float",
721 "double": "double",
722 "int8_t": "int32",
723 "int16_t": "int32",
724 "int32_t": "int32",
725 "int64_t": "int64",
726 "uint8_t": "uint32",
727 "uint16_t": "uint32",
728 "uint32_t": "uint32",
729 "uint64_t": "uint64",
Brendon Tiszka881dc3b2023-09-20 12:22:26 +0000730 "size_t": "uint64",
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000731 }
732
733 assert typ in cpp_to_protobuf_type
734
735 return cpp_to_protobuf_type[typ]
736
737 return member.type.name.CamelCase()
738
739
Brendon Tiszka27521c62023-05-15 22:22:07 +0000740# Helper that generates names for protobuf grammars from contents
741# of dawn*.json like files. example: membera
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000742def as_protobufNameLPM(*names):
Brendon Tiszka27521c62023-05-15 22:22:07 +0000743 # `descriptor` is a reserved keyword in lib-protobuf-mutator
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000744 if (names[0].concatcase() == "descriptor"):
745 return "desc"
746 return as_varName(*names)
747
748
Brendon Tiszka27521c62023-05-15 22:22:07 +0000749# Helper to generate member accesses within C++ of protobuf objects
750# example: cmd.membera().memberb()
751def as_protobufMemberNameLPM(*names):
752 # `descriptor` is a reserved keyword in lib-protobuf-mutator
753 if (names[0].concatcase() == "descriptor"):
754 return "desc"
755 return ''.join([name.concatcase().lower() for name in names])
756
757
Brendon Tiszkaa0456432023-03-23 16:02:20 +0000758def unreachable_code():
759 assert False
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000760
Brendon Tiszka27521c62023-05-15 22:22:07 +0000761
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400762#############################################################
Corentin Wallez0c38e922019-06-07 08:59:17 +0000763# Generator
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400764#############################################################
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400765
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000766
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400767def as_varName(*names):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000768 return names[0].camelCase() + ''.join(
769 [name.CamelCase() for name in names[1:]])
770
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400771
fujunwei76bda372021-11-23 08:47:35 +0000772def as_cType(c_prefix, name):
Loko Kung440a30c2023-08-04 23:41:21 +0000773 # Special case for 'bool' because it has a typedef for compatibility.
774 if name.native and name.get() != 'bool':
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400775 return name.concatcase()
776 else:
fujunwei76bda372021-11-23 08:47:35 +0000777 return c_prefix + name.CamelCase()
Corentin Wallez919812e2019-10-17 08:46:07 +0000778
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000779
Loko Kungcd162942023-06-01 19:03:05 +0000780def as_cReturnType(c_prefix, typ):
781 if typ.category != 'bitmask':
782 return as_cType(c_prefix, typ.name)
783 else:
784 return as_cType(c_prefix, typ.name) + 'Flags'
785
786
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400787def as_cppType(name):
Loko Kung440a30c2023-08-04 23:41:21 +0000788 # Special case for 'bool' because it has a typedef for compatibility.
789 if name.native and name.get() != 'bool':
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400790 return name.concatcase()
791 else:
792 return name.CamelCase()
793
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000794
Jim Blackler2e2d1d72024-03-27 18:54:55 +0000795def as_ktName(name):
796 return '_' + name if '0' <= name[0] <= '9' else name
797
798
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000799def as_jsEnumValue(value):
Kai Ninomiya930e9182021-09-17 19:44:43 +0000800 if 'jsrepr' in value.json_data: return value.json_data['jsrepr']
Kai Ninomiya7b6246a2020-01-28 23:54:38 +0000801 return "'" + value.name.js_enum_case() + "'"
802
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000803
Austin Eng740995c2019-05-15 18:55:22 +0000804def convert_cType_to_cppType(typ, annotation, arg, indent=0):
805 if typ.category == 'native':
806 return arg
807 if annotation == 'value':
808 if typ.category == 'object':
809 return '{}::Acquire({})'.format(as_cppType(typ.name), arg)
810 elif typ.category == 'structure':
811 converted_members = [
812 convert_cType_to_cppType(
813 member.type, member.annotation,
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000814 '{}.{}'.format(arg, as_varName(member.name)), indent + 1)
815 for member in typ.members
816 ]
Austin Eng740995c2019-05-15 18:55:22 +0000817
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000818 converted_members = [(' ' * 4) + m for m in converted_members]
Austin Eng740995c2019-05-15 18:55:22 +0000819 converted_members = ',\n'.join(converted_members)
820
821 return as_cppType(typ.name) + ' {\n' + converted_members + '\n}'
fujunweid3cac112021-12-14 02:20:15 +0000822 elif typ.category == 'function pointer':
823 return 'reinterpret_cast<{}>({})'.format(as_cppType(typ.name), arg)
Austin Eng740995c2019-05-15 18:55:22 +0000824 else:
825 return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
826 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000827 return 'reinterpret_cast<{} {}>({})'.format(as_cppType(typ.name),
828 annotation, arg)
829
Austin Eng740995c2019-05-15 18:55:22 +0000830
Austin Eng643625a2023-08-09 00:59:33 +0000831def decorate(name, typ, arg, make_const=False):
832 maybe_const = ' const ' if make_const else ' '
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400833 if arg.annotation == 'value':
Austin Eng643625a2023-08-09 00:59:33 +0000834 return typ + maybe_const + name
Austin Eng740995c2019-05-15 18:55:22 +0000835 elif arg.annotation == '*':
Austin Eng643625a2023-08-09 00:59:33 +0000836 return typ + ' *' + maybe_const + name
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400837 elif arg.annotation == 'const*':
Austin Eng643625a2023-08-09 00:59:33 +0000838 return typ + ' const *' + maybe_const + name
Austin Eng2f218e22021-12-22 19:02:23 +0000839 elif arg.annotation == 'const*const*':
Austin Eng643625a2023-08-09 00:59:33 +0000840 return 'const ' + typ + '* const *' + maybe_const + name
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400841 else:
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000842 assert False
843
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400844
Austin Eng643625a2023-08-09 00:59:33 +0000845def annotated(typ, arg, make_const=False):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400846 name = as_varName(arg.name)
Austin Eng643625a2023-08-09 00:59:33 +0000847 return decorate(name, typ, arg, make_const)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400848
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000849
Kai Ninomiya930e9182021-09-17 19:44:43 +0000850def item_is_enabled(enabled_tags, json_data):
851 tags = json_data.get('tags')
852 if tags is None: return True
853 return any(tag in enabled_tags for tag in tags)
854
855
Austin Eng2f218e22021-12-22 19:02:23 +0000856def item_is_disabled(disabled_tags, json_data):
857 if disabled_tags is None: return False
858 tags = json_data.get('tags')
859 if tags is None: return False
860
861 return any(tag in disabled_tags for tag in tags)
862
863
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400864def as_cppEnum(value_name):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000865 assert not value_name.native
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400866 if value_name.concatcase()[0].isdigit():
867 return "e" + value_name.CamelCase()
868 return value_name.CamelCase()
869
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000870
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400871def as_MethodSuffix(type_name, method_name):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000872 assert not type_name.native and not method_name.native
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400873 return type_name.CamelCase() + method_name.CamelCase()
874
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000875
Loko Kungd46120e2024-03-01 08:51:34 +0000876def as_CppMethodSuffix(type_name, method_name):
877 assert not type_name.native and not method_name.native
878 original_method_name_str = method_name.CamelCase()
879 if method_name.chunks[-1] == 'f':
880 return type_name.CamelCase() + original_method_name_str[:-1]
881 return type_name.CamelCase() + original_method_name_str
882
883
fujunwei76bda372021-11-23 08:47:35 +0000884def as_frontendType(metadata, typ):
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400885 if typ.category == 'object':
Corentin Wallez4f5fc2d2019-04-01 21:48:38 +0000886 return typ.name.CamelCase() + 'Base*'
Loko Kung440a30c2023-08-04 23:41:21 +0000887 elif typ.category in ['bitmask', 'enum'] or typ.name.get() == 'bool':
fujunwei76bda372021-11-23 08:47:35 +0000888 return metadata.namespace + '::' + typ.name.CamelCase()
Corentin Wallezfe253f12018-08-01 15:12:10 +0200889 elif typ.category == 'structure':
890 return as_cppType(typ.name)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400891 else:
fujunwei76bda372021-11-23 08:47:35 +0000892 return as_cType(metadata.c_prefix, typ.name)
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400893
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000894
fujunwei76bda372021-11-23 08:47:35 +0000895def as_wireType(metadata, typ):
Austin Engcb0cb652019-08-27 21:41:56 +0000896 if typ.category == 'object':
897 return typ.name.CamelCase() + '*'
Brandon Jones6f2bbe92021-04-05 23:34:17 +0000898 elif typ.category in ['bitmask', 'enum', 'structure']:
fujunwei76bda372021-11-23 08:47:35 +0000899 return metadata.c_prefix + typ.name.CamelCase()
Austin Engcb0cb652019-08-27 21:41:56 +0000900 else:
901 return as_cppType(typ.name)
902
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000903
Loko Kung4d835252022-03-19 00:21:48 +0000904def as_formatType(typ):
905 # Unsigned integral types
906 if typ.json_data['type'] in ['bool', 'uint32_t', 'uint64_t']:
907 return 'u'
908
909 # Defaults everything else to strings.
910 return 's'
911
912
Kai Ninomiya930e9182021-09-17 19:44:43 +0000913def c_methods(params, typ):
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000914 return typ.methods + [
Corentin Wallez2c89f5c2023-05-23 09:39:29 +0000915 Method(Name('reference'), params['types']['void'], [], False, {}),
916 Method(Name('release'), params['types']['void'], [], False, {}),
Corentin Wallez4b410a32017-04-20 14:42:36 -0400917 ]
918
Corentin Wallezaca8c4a2019-11-22 14:02:52 +0000919def get_c_methods_sorted_by_name(api_params):
Corentin Wallezc57b1802019-10-15 12:08:48 +0000920 unsorted = [(as_MethodSuffix(typ.name, method.name), typ, method) \
921 for typ in api_params['by_category']['object'] \
Kai Ninomiya930e9182021-09-17 19:44:43 +0000922 for method in c_methods(api_params, typ) ]
Corentin Wallezc57b1802019-10-15 12:08:48 +0000923 return [(typ, method) for (_, typ, method) in sorted(unsorted)]
924
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000925
Corentin Wallez540abab2019-11-22 13:18:22 +0000926def has_callback_arguments(method):
fujunwei23f71622021-12-02 07:41:21 +0000927 return any(arg.type.category == 'function pointer' for arg in method.arguments)
Corentin Wallez540abab2019-11-22 13:18:22 +0000928
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000929
Loko Kungd46120e2024-03-01 08:51:34 +0000930def has_callback_info(method):
931 return method.return_type.name.get() == 'future' and any(
932 arg.name.get() == 'callback info' for arg in method.arguments)
933
fujunwei76bda372021-11-23 08:47:35 +0000934def make_base_render_params(metadata):
935 c_prefix = metadata.c_prefix
936
937 def as_cTypeEnumSpecialCase(typ):
938 if typ.category == 'bitmask':
939 return as_cType(c_prefix, typ.name) + 'Flags'
940 return as_cType(c_prefix, typ.name)
941
942 def as_cEnum(type_name, value_name):
943 assert not type_name.native and not value_name.native
944 return c_prefix + type_name.CamelCase() + '_' + value_name.CamelCase()
945
946 def as_cMethod(type_name, method_name):
fujunwei23f71622021-12-02 07:41:21 +0000947 c_method = c_prefix.lower()
948 if type_name != None:
949 assert not type_name.native
950 c_method += type_name.CamelCase()
951 assert not method_name.native
952 c_method += method_name.CamelCase()
953 return c_method
fujunwei76bda372021-11-23 08:47:35 +0000954
955 def as_cProc(type_name, method_name):
fujunwei23f71622021-12-02 07:41:21 +0000956 c_proc = c_prefix + 'Proc'
957 if type_name != None:
958 assert not type_name.native
959 c_proc += type_name.CamelCase()
960 assert not method_name.native
961 c_proc += method_name.CamelCase()
962 return c_proc
fujunwei76bda372021-11-23 08:47:35 +0000963
964 return {
965 'Name': lambda name: Name(name),
966 'as_annotated_cType': \
Austin Eng643625a2023-08-09 00:59:33 +0000967 lambda arg, make_const=False: annotated(as_cTypeEnumSpecialCase(arg.type), arg, make_const),
fujunwei76bda372021-11-23 08:47:35 +0000968 'as_annotated_cppType': \
Austin Eng643625a2023-08-09 00:59:33 +0000969 lambda arg, make_const=False: annotated(as_cppType(arg.type.name), arg, make_const),
fujunwei76bda372021-11-23 08:47:35 +0000970 'as_cEnum': as_cEnum,
971 'as_cppEnum': as_cppEnum,
972 'as_cMethod': as_cMethod,
973 'as_MethodSuffix': as_MethodSuffix,
Loko Kungd46120e2024-03-01 08:51:34 +0000974 'as_CppMethodSuffix': as_CppMethodSuffix,
fujunwei76bda372021-11-23 08:47:35 +0000975 'as_cProc': as_cProc,
976 'as_cType': lambda name: as_cType(c_prefix, name),
Loko Kungcd162942023-06-01 19:03:05 +0000977 'as_cReturnType': lambda typ: as_cReturnType(c_prefix, typ),
fujunwei76bda372021-11-23 08:47:35 +0000978 'as_cppType': as_cppType,
979 'as_jsEnumValue': as_jsEnumValue,
980 'convert_cType_to_cppType': convert_cType_to_cppType,
981 'as_varName': as_varName,
Loko Kung4d835252022-03-19 00:21:48 +0000982 'decorate': decorate,
Jim Blackler2e2d1d72024-03-27 18:54:55 +0000983 'as_formatType': as_formatType,
984 'as_ktName': as_ktName
fujunwei76bda372021-11-23 08:47:35 +0000985 }
986
987
Corentin Wallez0c38e922019-06-07 08:59:17 +0000988class MultiGeneratorFromDawnJSON(Generator):
989 def get_description(self):
990 return 'Generates code for various target from Dawn.json.'
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400991
Corentin Wallez0c38e922019-06-07 08:59:17 +0000992 def add_commandline_arguments(self, parser):
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000993 allowed_targets = [
Ben Clayton35940f92022-02-04 17:15:16 +0000994 'dawn_headers', 'cpp_headers', 'cpp', 'proc', 'mock_api', 'wire',
Jim Blackler2e2d1d72024-03-27 18:54:55 +0000995 'native_utils', 'dawn_lpmfuzz_cpp', 'dawn_lpmfuzz_proto', 'kotlin'
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000996 ]
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400997
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000998 parser.add_argument('--dawn-json',
999 required=True,
1000 type=str,
1001 help='The DAWN JSON definition to use.')
1002 parser.add_argument('--wire-json',
1003 default=None,
1004 type=str,
1005 help='The DAWN WIRE JSON definition to use.')
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001006 parser.add_argument("--lpm-json",
1007 default=None,
1008 type=str,
1009 help='The DAWN LPM FUZZER definitions to use.')
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001010 parser.add_argument(
1011 '--targets',
1012 required=True,
1013 type=str,
1014 help=
1015 'Comma-separated subset of targets to output. Available targets: '
1016 + ', '.join(allowed_targets))
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001017
Corentin Wallez0c38e922019-06-07 08:59:17 +00001018 def get_file_renders(self, args):
1019 with open(args.dawn_json) as f:
1020 loaded_json = json.loads(f.read())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001021
Corentin Wallez0c38e922019-06-07 08:59:17 +00001022 targets = args.targets.split(',')
Corentin Wallez4b410a32017-04-20 14:42:36 -04001023
Corentin Wallez0c38e922019-06-07 08:59:17 +00001024 wire_json = None
1025 if args.wire_json:
1026 with open(args.wire_json) as f:
1027 wire_json = json.loads(f.read())
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001028
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001029 lpm_json = None
1030 if args.lpm_json:
1031 with open(args.lpm_json) as f:
1032 lpm_json = json.loads(f.read())
1033
Kai Ninomiya930e9182021-09-17 19:44:43 +00001034 renders = []
1035
Kai Ninomiya930e9182021-09-17 19:44:43 +00001036 params_dawn = parse_json(loaded_json,
1037 enabled_tags=['dawn', 'native', 'deprecated'])
fujunwei76bda372021-11-23 08:47:35 +00001038 metadata = params_dawn['metadata']
1039 RENDER_PARAMS_BASE = make_base_render_params(metadata)
Corentin Wallez79a62bf2017-05-24 16:04:55 +02001040
fujunweic7d4f2c2021-12-07 00:46:35 +00001041 api = metadata.api.lower()
fujunweia8405742021-12-10 01:35:19 +00001042 prefix = metadata.proc_table_prefix.lower()
Ben Clayton35940f92022-02-04 17:15:16 +00001043 if 'headers' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001044 renders.append(
Ben Clayton9fb7a512022-02-04 18:18:18 +00001045 FileRender('api.h', 'include/dawn/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001046 [RENDER_PARAMS_BASE, params_dawn]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001047 renders.append(
1048 FileRender('dawn_proc_table.h',
Ben Clayton9fb7a512022-02-04 18:18:18 +00001049 'include/dawn/' + prefix + '_proc_table.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001050 [RENDER_PARAMS_BASE, params_dawn]))
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001051
Ben Clayton35940f92022-02-04 17:15:16 +00001052 if 'cpp_headers' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001053 renders.append(
Ben Clayton9fb7a512022-02-04 18:18:18 +00001054 FileRender('api_cpp.h', 'include/dawn/' + api + '_cpp.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001055 [RENDER_PARAMS_BASE, params_dawn]))
Austin Engcc071e42019-10-16 10:26:01 +00001056
Austin Enga9e39e12021-06-01 18:49:12 +00001057 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +00001058 FileRender('api_cpp_print.h',
Ben Clayton9fb7a512022-02-04 18:18:18 +00001059 'include/dawn/' + api + '_cpp_print.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001060 [RENDER_PARAMS_BASE, params_dawn]))
Austin Enga9e39e12021-06-01 18:49:12 +00001061
Loko Kung14ed5332023-05-16 04:50:32 +00001062 renders.append(
1063 FileRender('api_cpp_chained_struct.h',
Kai Ninomiya68892272024-01-04 10:02:49 +00001064 'include/webgpu/' + api + '_cpp_chained_struct.h',
Loko Kung14ed5332023-05-16 04:50:32 +00001065 [RENDER_PARAMS_BASE, params_dawn]))
1066
Ben Clayton35940f92022-02-04 17:15:16 +00001067 if 'proc' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001068 renders.append(
fujunweia8405742021-12-10 01:35:19 +00001069 FileRender('dawn_proc.c', 'src/dawn/' + prefix + '_proc.c',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001070 [RENDER_PARAMS_BASE, params_dawn]))
Austin Eng16e01af2020-10-06 16:13:42 +00001071 renders.append(
1072 FileRender('dawn_thread_dispatch_proc.cpp',
fujunweia8405742021-12-10 01:35:19 +00001073 'src/dawn/' + prefix + '_thread_dispatch_proc.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001074 [RENDER_PARAMS_BASE, params_dawn]))
Corentin Wallez96496822019-10-15 11:44:38 +00001075
Austin Eng63f65462021-12-09 20:03:48 +00001076 if 'webgpu_dawn_native_proc' in targets:
1077 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001078 FileRender('dawn/native/api_dawn_native_proc.cpp',
1079 'src/dawn/native/webgpu_dawn_native_proc.cpp',
Austin Eng63f65462021-12-09 20:03:48 +00001080 [RENDER_PARAMS_BASE, params_dawn]))
1081
Ben Clayton35940f92022-02-04 17:15:16 +00001082 if 'cpp' in targets:
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001083 renders.append(
fujunweid3cac112021-12-14 02:20:15 +00001084 FileRender('api_cpp.cpp', 'src/dawn/' + api + '_cpp.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001085 [RENDER_PARAMS_BASE, params_dawn]))
1086
1087 if 'webgpu_headers' in targets:
1088 params_upstream = parse_json(loaded_json,
Shrek Shao1554a7d2022-03-08 20:56:10 +00001089 enabled_tags=['upstream', 'native'],
1090 disabled_tags=['dawn'])
Kai Ninomiya930e9182021-09-17 19:44:43 +00001091 renders.append(
fujunweic7d4f2c2021-12-07 00:46:35 +00001092 FileRender('api.h', 'webgpu-headers/' + api + '.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001093 [RENDER_PARAMS_BASE, params_upstream]))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001094
Kai Ninomiya7b6246a2020-01-28 23:54:38 +00001095 if 'emscripten_bits' in targets:
Kai Ninomiya68892272024-01-04 10:02:49 +00001096 assert api == 'webgpu'
Shrek Shaoee50bc02022-02-08 20:21:40 +00001097 params_emscripten = parse_json(loaded_json,
1098 enabled_tags=['emscripten'])
Kai Ninomiya68892272024-01-04 10:02:49 +00001099 # system/include/webgpu
Kai Ninomiya930e9182021-09-17 19:44:43 +00001100 renders.append(
Kai Ninomiya68892272024-01-04 10:02:49 +00001101 FileRender('api.h',
1102 'emscripten-bits/system/include/webgpu/webgpu.h',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001103 [RENDER_PARAMS_BASE, params_emscripten]))
1104 renders.append(
Kai Ninomiya68892272024-01-04 10:02:49 +00001105 FileRender(
1106 'api_cpp.h',
1107 'emscripten-bits/system/include/webgpu/webgpu_cpp.h',
1108 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya930e9182021-09-17 19:44:43 +00001109 renders.append(
Kai Ninomiya68892272024-01-04 10:02:49 +00001110 FileRender(
1111 'api_cpp_chained_struct.h',
1112 'emscripten-bits/system/include/webgpu/webgpu_cpp_chained_struct.h',
1113 [RENDER_PARAMS_BASE, params_emscripten]))
1114 # system/lib/webgpu
1115 renders.append(
1116 FileRender('api_cpp.cpp',
1117 'emscripten-bits/system/lib/webgpu/webgpu_cpp.cpp',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001118 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya68892272024-01-04 10:02:49 +00001119 # Snippets to paste into existing Emscripten files
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001120 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +00001121 FileRender('api_struct_info.json',
Kai Ninomiya68892272024-01-04 10:02:49 +00001122 'emscripten-bits/webgpu_struct_info.json',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001123 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001124 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +00001125 FileRender('library_api_enum_tables.js',
Kai Ninomiya68892272024-01-04 10:02:49 +00001126 'emscripten-bits/library_webgpu_enum_tables.js',
Kai Ninomiya930e9182021-09-17 19:44:43 +00001127 [RENDER_PARAMS_BASE, params_emscripten]))
Kai Ninomiya7b6246a2020-01-28 23:54:38 +00001128
fujunwei16ae3b82021-12-15 04:35:26 +00001129 if 'mock_api' in targets:
Corentin Wallez540abab2019-11-22 13:18:22 +00001130 mock_params = [
Kai Ninomiya930e9182021-09-17 19:44:43 +00001131 RENDER_PARAMS_BASE, params_dawn, {
Loko Kungd46120e2024-03-01 08:51:34 +00001132 'has_callback_arguments': has_callback_arguments,
1133 "has_callback_info": has_callback_info
Corentin Wallez540abab2019-11-22 13:18:22 +00001134 }
1135 ]
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001136 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +00001137 FileRender('mock_api.h', 'src/dawn/mock_' + api + '.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001138 mock_params))
1139 renders.append(
fujunwei16ae3b82021-12-15 04:35:26 +00001140 FileRender('mock_api.cpp', 'src/dawn/mock_' + api + '.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001141 mock_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001142
Ben Clayton818001d2022-02-04 17:07:46 +00001143 if 'native_utils' in targets:
Corentin Wallez0c38e922019-06-07 08:59:17 +00001144 frontend_params = [
Kai Ninomiya930e9182021-09-17 19:44:43 +00001145 RENDER_PARAMS_BASE,
1146 params_dawn,
Corentin Wallez0c38e922019-06-07 08:59:17 +00001147 {
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001148 # TODO: as_frontendType and co. take a Type, not a Name :(
fujunwei76bda372021-11-23 08:47:35 +00001149 'as_frontendType': lambda typ: as_frontendType(metadata, typ),
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001150 'as_annotated_frontendType': \
fujunwei76bda372021-11-23 08:47:35 +00001151 lambda arg: annotated(as_frontendType(metadata, arg.type), arg),
Corentin Wallez0c38e922019-06-07 08:59:17 +00001152 }
1153 ]
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001154
fujunweia2241d42021-12-16 04:54:38 +00001155 impl_dir = metadata.impl_dir + '/' if metadata.impl_dir else ''
Ben Clayton818001d2022-02-04 17:07:46 +00001156 native_dir = impl_dir + Name(metadata.native_namespace).Dirs()
fujunwei7f3f8ac2021-12-21 03:27:34 +00001157 namespace = metadata.namespace
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001158 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001159 FileRender('dawn/native/ValidationUtils.h',
fujunweia2241d42021-12-16 04:54:38 +00001160 'src/' + native_dir + '/ValidationUtils_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001161 frontend_params))
1162 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001163 FileRender('dawn/native/ValidationUtils.cpp',
fujunweia2241d42021-12-16 04:54:38 +00001164 'src/' + native_dir + '/ValidationUtils_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001165 frontend_params))
1166 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001167 FileRender('dawn/native/dawn_platform.h',
fujunweifc38f7d2021-12-17 00:46:08 +00001168 'src/' + native_dir + '/' + prefix + '_platform_autogen.h',
Austin Eng3faa4782021-10-27 19:07:37 +00001169 frontend_params))
1170 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001171 FileRender('dawn/native/api_structs.h',
fujunwei7f3f8ac2021-12-21 03:27:34 +00001172 'src/' + native_dir + '/' + namespace + '_structs_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001173 frontend_params))
1174 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001175 FileRender('dawn/native/api_structs.cpp',
fujunwei7f3f8ac2021-12-21 03:27:34 +00001176 'src/' + native_dir + '/' + namespace + '_structs_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001177 frontend_params))
1178 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001179 FileRender('dawn/native/ProcTable.cpp',
Ningxin Hu7e5930b2021-12-22 06:12:13 +00001180 'src/' + native_dir + '/ProcTable.cpp', frontend_params))
Brian Ho5346e772021-04-22 17:49:42 +00001181 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001182 FileRender('dawn/native/ChainUtils.h',
fujunwei2b1dcd92021-12-22 01:05:03 +00001183 'src/' + native_dir + '/ChainUtils_autogen.h',
Brian Ho5346e772021-04-22 17:49:42 +00001184 frontend_params))
1185 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001186 FileRender('dawn/native/ChainUtils.cpp',
fujunwei2b1dcd92021-12-22 01:05:03 +00001187 'src/' + native_dir + '/ChainUtils_autogen.cpp',
Brian Ho5346e772021-04-22 17:49:42 +00001188 frontend_params))
Brandon Jonesba662952021-09-23 21:26:33 +00001189 renders.append(
Austin Engd1dcb502023-08-21 22:03:00 +00001190 FileRender('dawn/native/Features.h',
1191 'src/' + native_dir + '/Features_autogen.h',
1192 frontend_params))
1193 renders.append(
1194 FileRender('dawn/native/Features.inl',
1195 'src/' + native_dir + '/Features_autogen.inl',
1196 frontend_params))
1197 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001198 FileRender('dawn/native/api_absl_format.h',
fujunweif001ef52021-12-23 05:16:04 +00001199 'src/' + native_dir + '/' + api + '_absl_format_autogen.h',
Brandon Jonesba662952021-09-23 21:26:33 +00001200 frontend_params))
1201 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001202 FileRender('dawn/native/api_absl_format.cpp',
fujunweif001ef52021-12-23 05:16:04 +00001203 'src/' + native_dir + '/' + api + '_absl_format_autogen.cpp',
Brandon Jonesba662952021-09-23 21:26:33 +00001204 frontend_params))
Loko Kung8d195d52021-09-28 15:40:01 +00001205 renders.append(
Austin Engbc285fb2022-07-29 00:36:21 +00001206 FileRender(
1207 'dawn/native/api_StreamImpl.cpp', 'src/' + native_dir +
1208 '/' + api + '_StreamImpl_autogen.cpp', frontend_params))
1209 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001210 FileRender('dawn/native/ObjectType.h',
fujunwei2b1dcd92021-12-22 01:05:03 +00001211 'src/' + native_dir + '/ObjectType_autogen.h',
Loko Kung8d195d52021-09-28 15:40:01 +00001212 frontend_params))
1213 renders.append(
Ben Clayton818001d2022-02-04 17:07:46 +00001214 FileRender('dawn/native/ObjectType.cpp',
fujunwei2b1dcd92021-12-22 01:05:03 +00001215 'src/' + native_dir + '/ObjectType_autogen.cpp',
Loko Kung8d195d52021-09-28 15:40:01 +00001216 frontend_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001217
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001218 if 'wire' in targets:
Austin Eng2f218e22021-12-22 19:02:23 +00001219 params_dawn_wire = parse_json(loaded_json,
1220 enabled_tags=['dawn', 'deprecated'],
1221 disabled_tags=['native'])
1222 additional_params = compute_wire_params(params_dawn_wire,
1223 wire_json)
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001224
Corentin Wallez0c38e922019-06-07 08:59:17 +00001225 wire_params = [
Austin Eng2f218e22021-12-22 19:02:23 +00001226 RENDER_PARAMS_BASE, params_dawn_wire, {
fujunwei76bda372021-11-23 08:47:35 +00001227 'as_wireType': lambda type : as_wireType(metadata, type),
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001228 'as_annotated_wireType': \
fujunwei76bda372021-11-23 08:47:35 +00001229 lambda arg: annotated(as_wireType(metadata, arg.type), arg),
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001230 }, additional_params
Corentin Wallez0c38e922019-06-07 08:59:17 +00001231 ]
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001232 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001233 FileRender('dawn/wire/ObjectType.h',
1234 'src/dawn/wire/ObjectType_autogen.h', wire_params))
Austin Eng3120d5e2020-11-11 19:46:18 +00001235 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001236 FileRender('dawn/wire/WireCmd.h',
1237 'src/dawn/wire/WireCmd_autogen.h', wire_params))
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001238 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001239 FileRender('dawn/wire/WireCmd.cpp',
1240 'src/dawn/wire/WireCmd_autogen.cpp', wire_params))
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001241 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001242 FileRender('dawn/wire/client/ApiObjects.h',
1243 'src/dawn/wire/client/ApiObjects_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001244 wire_params))
1245 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001246 FileRender('dawn/wire/client/ApiProcs.cpp',
1247 'src/dawn/wire/client/ApiProcs_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001248 wire_params))
1249 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001250 FileRender('dawn/wire/client/ClientBase.h',
1251 'src/dawn/wire/client/ClientBase_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001252 wire_params))
1253 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001254 FileRender('dawn/wire/client/ClientHandlers.cpp',
1255 'src/dawn/wire/client/ClientHandlers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001256 wire_params))
1257 renders.append(
1258 FileRender(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001259 'dawn/wire/client/ClientPrototypes.inc',
1260 'src/dawn/wire/client/ClientPrototypes_autogen.inc',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001261 wire_params))
1262 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001263 FileRender('dawn/wire/server/ServerBase.h',
1264 'src/dawn/wire/server/ServerBase_autogen.h',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001265 wire_params))
1266 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001267 FileRender('dawn/wire/server/ServerDoers.cpp',
1268 'src/dawn/wire/server/ServerDoers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001269 wire_params))
1270 renders.append(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001271 FileRender('dawn/wire/server/ServerHandlers.cpp',
1272 'src/dawn/wire/server/ServerHandlers_autogen.cpp',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001273 wire_params))
1274 renders.append(
1275 FileRender(
Ben Clayton20cbe6d2022-02-04 12:51:25 +00001276 'dawn/wire/server/ServerPrototypes.inc',
1277 'src/dawn/wire/server/ServerPrototypes_autogen.inc',
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001278 wire_params))
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001279
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001280 if 'dawn_lpmfuzz_proto' in targets:
1281 params_dawn_wire = parse_json(loaded_json,
1282 enabled_tags=['dawn', 'deprecated'],
1283 disabled_tags=['native'])
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001284 api_and_wire_params = compute_wire_params(params_dawn_wire,
1285 wire_json)
1286
1287 fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001288
1289 lpm_params = [
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001290 RENDER_PARAMS_BASE, params_dawn_wire, {
1291 'as_protobufTypeLPM': as_protobufTypeLPM,
1292 'as_protobufNameLPM': as_protobufNameLPM,
1293 'unreachable': unreachable_code
1294 }, api_and_wire_params, fuzzer_params
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001295 ]
1296
1297 renders.append(
1298 FileRender('dawn/fuzzers/lpmfuzz/dawn_lpm.proto',
1299 'src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.proto',
1300 lpm_params))
1301
Brendon Tiszka1f8413f2023-05-02 21:41:22 +00001302 renders.append(
1303 FileRender(
1304 'dawn/fuzzers/lpmfuzz/dawn_object_types_lpm.proto',
1305 'src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.proto',
1306 lpm_params))
1307
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001308 if 'dawn_lpmfuzz_cpp' in targets:
1309 params_dawn_wire = parse_json(loaded_json,
1310 enabled_tags=['dawn', 'deprecated'],
1311 disabled_tags=['native'])
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001312 api_and_wire_params = compute_wire_params(params_dawn_wire,
1313 wire_json)
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001314
Brendon Tiszka1f8413f2023-05-02 21:41:22 +00001315 fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
1316
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001317 lpm_params = [
Brendon Tiszka27521c62023-05-15 22:22:07 +00001318 RENDER_PARAMS_BASE, params_dawn_wire, {
1319 'as_protobufMemberName': as_protobufMemberNameLPM,
1320 'unreachable_code': unreachable_code
1321 }, api_and_wire_params, fuzzer_params
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001322 ]
1323
1324 renders.append(
1325 FileRender(
1326 'dawn/fuzzers/lpmfuzz/DawnLPMSerializer.cpp',
1327 'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.cpp',
1328 lpm_params))
1329
1330 renders.append(
1331 FileRender(
1332 'dawn/fuzzers/lpmfuzz/DawnLPMSerializer.h',
1333 'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h',
1334 lpm_params))
1335
Brendon Tiszkaa0456432023-03-23 16:02:20 +00001336 renders.append(
1337 FileRender(
1338 'dawn/fuzzers/lpmfuzz/DawnLPMConstants.h',
1339 'src/dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h',
1340 lpm_params))
1341
Jim Blackler2e2d1d72024-03-27 18:54:55 +00001342 if 'kotlin' in targets:
1343 params_kotlin = parse_json(loaded_json,
1344 enabled_tags=['dawn', 'native'])
1345
1346 for enum in (params_kotlin['by_category']['bitmask'] +
1347 params_kotlin['by_category']['enum']):
1348 renders.append(
1349 FileRender(
1350 'art/api_kotlin_enum.kt',
1351 'java/' + metadata.kotlin_path + '/' +
1352 enum.name.CamelCase() + '.kt',
1353 [RENDER_PARAMS_BASE, params_kotlin, {
1354 'enum': enum
1355 }]))
1356
1357 renders.append(
1358 FileRender('art/api_kotlin_constants.kt',
1359 'java/' + metadata.kotlin_path + '/Constants.kt',
1360 [RENDER_PARAMS_BASE, params_kotlin]))
1361
Corentin Wallez0c38e922019-06-07 08:59:17 +00001362 return renders
Corentin Wallez59e7fad2018-08-16 15:32:35 +02001363
Corentin Wallez0c38e922019-06-07 08:59:17 +00001364 def get_dependencies(self, args):
1365 deps = [os.path.abspath(args.dawn_json)]
1366 if args.wire_json != None:
1367 deps += [os.path.abspath(args.wire_json)]
Brendon Tiszkad0b284b2023-02-08 20:43:18 +00001368 if args.lpm_json != None:
1369 deps += [os.path.abspath(args.lpm_json)]
Corentin Wallez0c38e922019-06-07 08:59:17 +00001370 return deps
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001371
Kai Ninomiya01aeca22020-07-15 19:51:17 +00001372
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001373if __name__ == '__main__':
Corentin Wallez0c38e922019-06-07 08:59:17 +00001374 sys.exit(run_generator(MultiGeneratorFromDawnJSON()))