xref: /aosp_15_r20/external/OpenCL-ICD-Loader/scripts/gen/__init__.py (revision 1cddb830dba8aa7c1cc1039338e56b3b9fa24952)
1*1cddb830SAndroid Build Coastguard Worker# Copyright (c) 2020 The Khronos Group Inc.
2*1cddb830SAndroid Build Coastguard Worker#
3*1cddb830SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*1cddb830SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*1cddb830SAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*1cddb830SAndroid Build Coastguard Worker#
7*1cddb830SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*1cddb830SAndroid Build Coastguard Worker#
9*1cddb830SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*1cddb830SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*1cddb830SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1cddb830SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*1cddb830SAndroid Build Coastguard Worker# limitations under the License.
14*1cddb830SAndroid Build Coastguard Worker
15*1cddb830SAndroid Build Coastguard Workerfrom collections import OrderedDict
16*1cddb830SAndroid Build Coastguard Workerfrom collections import namedtuple
17*1cddb830SAndroid Build Coastguard Worker
18*1cddb830SAndroid Build Coastguard Workerimport argparse
19*1cddb830SAndroid Build Coastguard Workerimport sys
20*1cddb830SAndroid Build Coastguard Workerimport urllib
21*1cddb830SAndroid Build Coastguard Workerimport xml.etree.ElementTree as etree
22*1cddb830SAndroid Build Coastguard Workerimport urllib.request
23*1cddb830SAndroid Build Coastguard Worker
24*1cddb830SAndroid Build Coastguard Worker# parse_xml - Helper function to parse the XML file from a URL or local file.
25*1cddb830SAndroid Build Coastguard Workerdef parse_xml(path):
26*1cddb830SAndroid Build Coastguard Worker    file = urllib.request.urlopen(path) if path.startswith("http") else open(path, 'r')
27*1cddb830SAndroid Build Coastguard Worker    with file:
28*1cddb830SAndroid Build Coastguard Worker        tree = etree.parse(file)
29*1cddb830SAndroid Build Coastguard Worker        return tree
30*1cddb830SAndroid Build Coastguard Worker
31*1cddb830SAndroid Build Coastguard Worker# noneStr - returns string argument, or "" if argument is None.
32*1cddb830SAndroid Build Coastguard Workerdef noneStr(s):
33*1cddb830SAndroid Build Coastguard Worker    if s:
34*1cddb830SAndroid Build Coastguard Worker        return s
35*1cddb830SAndroid Build Coastguard Worker    return ""
36*1cddb830SAndroid Build Coastguard Worker
37*1cddb830SAndroid Build Coastguard Workerdef parse_args():
38*1cddb830SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser()
39*1cddb830SAndroid Build Coastguard Worker
40*1cddb830SAndroid Build Coastguard Worker    # To pull the latest registry file from GitHub, pass:
41*1cddb830SAndroid Build Coastguard Worker    # -registry "https://raw.githubusercontent.com/KhronosGroup/OpenCL-Docs/main/xml/cl.xml"
42*1cddb830SAndroid Build Coastguard Worker
43*1cddb830SAndroid Build Coastguard Worker    parser.add_argument('-registry', action='store',
44*1cddb830SAndroid Build Coastguard Worker                        default='cl.xml',
45*1cddb830SAndroid Build Coastguard Worker                        help='Use specified registry file instead of cl.xml')
46*1cddb830SAndroid Build Coastguard Worker    parser.add_argument('-o', action='store', dest='directory',
47*1cddb830SAndroid Build Coastguard Worker                        default='.',
48*1cddb830SAndroid Build Coastguard Worker                        help='Create target and related files in specified directory')
49*1cddb830SAndroid Build Coastguard Worker
50*1cddb830SAndroid Build Coastguard Worker    args = parser.parse_args()
51*1cddb830SAndroid Build Coastguard Worker    return args
52*1cddb830SAndroid Build Coastguard Worker
53*1cddb830SAndroid Build Coastguard Workerdef load_spec(args):
54*1cddb830SAndroid Build Coastguard Worker    specpath = args.registry
55*1cddb830SAndroid Build Coastguard Worker
56*1cddb830SAndroid Build Coastguard Worker    print('Parsing XML file from: ' + specpath)
57*1cddb830SAndroid Build Coastguard Worker    spec = parse_xml(specpath)
58*1cddb830SAndroid Build Coastguard Worker    return spec
59*1cddb830SAndroid Build Coastguard Worker
60*1cddb830SAndroid Build Coastguard Workerdef get_apisigs(spec):
61*1cddb830SAndroid Build Coastguard Worker    # Generate the API function signatures dictionary:
62*1cddb830SAndroid Build Coastguard Worker    apisigs = OrderedDict()
63*1cddb830SAndroid Build Coastguard Worker    ApiSignature = namedtuple('ApiSignature', 'Name RetType Params Suffix')
64*1cddb830SAndroid Build Coastguard Worker    ApiParam = namedtuple('ApiParam', 'Type TypeEnd Name')
65*1cddb830SAndroid Build Coastguard Worker    print('Generating API signatures dictionary...')
66*1cddb830SAndroid Build Coastguard Worker    for command in spec.findall('commands/command'):
67*1cddb830SAndroid Build Coastguard Worker        suffix = noneStr(command.get('suffix'))
68*1cddb830SAndroid Build Coastguard Worker        proto = command.find('proto')
69*1cddb830SAndroid Build Coastguard Worker        ret = noneStr(proto.text)
70*1cddb830SAndroid Build Coastguard Worker        name = ""
71*1cddb830SAndroid Build Coastguard Worker        params = ""
72*1cddb830SAndroid Build Coastguard Worker        for elem in proto:
73*1cddb830SAndroid Build Coastguard Worker            if elem.tag == 'name':
74*1cddb830SAndroid Build Coastguard Worker                name = noneStr(elem.text) + noneStr(elem.tail)
75*1cddb830SAndroid Build Coastguard Worker            else:
76*1cddb830SAndroid Build Coastguard Worker                ret = ret + noneStr(elem.text) + noneStr(elem.tail)
77*1cddb830SAndroid Build Coastguard Worker        ret = ret.strip()
78*1cddb830SAndroid Build Coastguard Worker        name = name.strip()
79*1cddb830SAndroid Build Coastguard Worker
80*1cddb830SAndroid Build Coastguard Worker        plist = []
81*1cddb830SAndroid Build Coastguard Worker        for param in command.findall('param'):
82*1cddb830SAndroid Build Coastguard Worker            ptype = noneStr(param.text)
83*1cddb830SAndroid Build Coastguard Worker            ptypeend = ""
84*1cddb830SAndroid Build Coastguard Worker            pname = ""
85*1cddb830SAndroid Build Coastguard Worker            for elem in param:
86*1cddb830SAndroid Build Coastguard Worker                if elem.tag == 'name':
87*1cddb830SAndroid Build Coastguard Worker                    pname = noneStr(elem.text)
88*1cddb830SAndroid Build Coastguard Worker                    ptypeend = noneStr(elem.tail)
89*1cddb830SAndroid Build Coastguard Worker                else:
90*1cddb830SAndroid Build Coastguard Worker                    ptype = ptype + noneStr(elem.text) + noneStr(elem.tail)
91*1cddb830SAndroid Build Coastguard Worker            ptype = ptype.strip()
92*1cddb830SAndroid Build Coastguard Worker            ptypeend = ptypeend.strip()
93*1cddb830SAndroid Build Coastguard Worker            pname = pname.strip()
94*1cddb830SAndroid Build Coastguard Worker            plist.append(ApiParam(ptype, ptypeend, pname))
95*1cddb830SAndroid Build Coastguard Worker
96*1cddb830SAndroid Build Coastguard Worker        # For an empty parameter list (for e.g. clUnloadCompiler), add a single
97*1cddb830SAndroid Build Coastguard Worker        # unnamed void parameter to make generation easier.
98*1cddb830SAndroid Build Coastguard Worker        if len(plist) == 0:
99*1cddb830SAndroid Build Coastguard Worker            plist.append(ApiParam("void", "", ""))
100*1cddb830SAndroid Build Coastguard Worker
101*1cddb830SAndroid Build Coastguard Worker        apisigs[name] = ApiSignature(name, ret, plist, suffix)
102*1cddb830SAndroid Build Coastguard Worker    return apisigs
103*1cddb830SAndroid Build Coastguard Worker
104*1cddb830SAndroid Build Coastguard Workerdef get_apis(spec, apisigs):
105*1cddb830SAndroid Build Coastguard Worker    # Generate the core API dictionary:
106*1cddb830SAndroid Build Coastguard Worker    coreapis = OrderedDict()
107*1cddb830SAndroid Build Coastguard Worker    print('Generating core API dictionary...')
108*1cddb830SAndroid Build Coastguard Worker    for feature in spec.findall('feature'):
109*1cddb830SAndroid Build Coastguard Worker        version = noneStr(feature.get('name'))
110*1cddb830SAndroid Build Coastguard Worker
111*1cddb830SAndroid Build Coastguard Worker        alist = []
112*1cddb830SAndroid Build Coastguard Worker        for function in feature.findall('require/command'):
113*1cddb830SAndroid Build Coastguard Worker            name = function.get('name')
114*1cddb830SAndroid Build Coastguard Worker            alist.append(apisigs[name])
115*1cddb830SAndroid Build Coastguard Worker        coreapis[version] = alist
116*1cddb830SAndroid Build Coastguard Worker
117*1cddb830SAndroid Build Coastguard Worker    # Generate the extensions API dictionary:
118*1cddb830SAndroid Build Coastguard Worker    extapis = OrderedDict()
119*1cddb830SAndroid Build Coastguard Worker    print('Generating API extensions dictionary...')
120*1cddb830SAndroid Build Coastguard Worker    for feature in spec.findall('extensions/extension'):
121*1cddb830SAndroid Build Coastguard Worker        extension = noneStr(feature.get('name'))
122*1cddb830SAndroid Build Coastguard Worker
123*1cddb830SAndroid Build Coastguard Worker        alist = []
124*1cddb830SAndroid Build Coastguard Worker        for function in feature.findall('require/command'):
125*1cddb830SAndroid Build Coastguard Worker            name = function.get('name')
126*1cddb830SAndroid Build Coastguard Worker            alist.append(apisigs[name])
127*1cddb830SAndroid Build Coastguard Worker        extapis[extension] = alist
128*1cddb830SAndroid Build Coastguard Worker    return (coreapis, extapis)
129*1cddb830SAndroid Build Coastguard Worker
130*1cddb830SAndroid Build Coastguard Worker
131