• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding=utf-8
2#
3# Copyright (c) 2025 Huawei Device Co., Ltd.
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
16from taihe.codegen.abi.analyses import (
17    GlobFuncABIInfo,
18    IfaceABIInfo,
19    IfaceMethodABIInfo,
20    PackageABIInfo,
21    StructABIInfo,
22    TypeABIInfo,
23    UnionABIInfo,
24)
25from taihe.codegen.abi.writer import CHeaderWriter, CSourceWriter
26from taihe.semantics.declarations import (
27    GlobFuncDecl,
28    IfaceDecl,
29    PackageDecl,
30    PackageGroup,
31    StructDecl,
32    UnionDecl,
33)
34from taihe.utils.analyses import AnalysisManager
35from taihe.utils.outputs import FileKind, OutputManager
36
37
38class ABIHeadersGenerator:
39    def __init__(self, om: OutputManager, am: AnalysisManager):
40        self.om = om
41        self.am = am
42
43    def generate(self, pg: PackageGroup):
44        for pkg in pg.packages:
45            self.gen_package_files(pkg)
46
47    def gen_package_files(self, pkg: PackageDecl):
48        pkg_abi_info = PackageABIInfo.get(self.am, pkg)
49        with CHeaderWriter(
50            self.om,
51            f"include/{pkg_abi_info.header}",
52            FileKind.C_HEADER,
53        ) as pkg_abi_target:
54            for struct in pkg.structs:
55                struct_abi_info = StructABIInfo.get(self.am, struct)
56                self.gen_struct_decl_file(struct, struct_abi_info)
57                self.gen_struct_defn_file(struct, struct_abi_info)
58                self.gen_struct_impl_file(struct, struct_abi_info)
59                pkg_abi_target.add_include(struct_abi_info.impl_header)
60            for union in pkg.unions:
61                union_abi_info = UnionABIInfo.get(self.am, union)
62                self.gen_union_decl_file(union, union_abi_info)
63                self.gen_union_defn_file(union, union_abi_info)
64                self.gen_union_impl_file(union, union_abi_info)
65                pkg_abi_target.add_include(union_abi_info.impl_header)
66            for iface in pkg.interfaces:
67                iface_abi_info = IfaceABIInfo.get(self.am, iface)
68                self.gen_iface_decl_file(iface, iface_abi_info)
69                self.gen_iface_defn_file(iface, iface_abi_info)
70                self.gen_iface_impl_file(iface, iface_abi_info)
71                pkg_abi_target.add_include(iface_abi_info.impl_header)
72            pkg_abi_target.add_include("taihe/common.h")
73            for func in pkg.functions:
74                for param in func.params:
75                    type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty)
76                    pkg_abi_target.add_include(*type_abi_info.impl_headers)
77                if return_ty_ref := func.return_ty_ref:
78                    type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty)
79                    pkg_abi_target.add_include(*type_abi_info.impl_headers)
80                self.gen_func(func, pkg_abi_target)
81
82    def gen_func(
83        self,
84        func: GlobFuncDecl,
85        pkg_abi_target: CHeaderWriter,
86    ):
87        func_abi_info = GlobFuncABIInfo.get(self.am, func)
88        params = []
89        for param in func.params:
90            type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty)
91            params.append(f"{type_abi_info.as_param} {param.name}")
92        params_str = ", ".join(params)
93        if return_ty_ref := func.return_ty_ref:
94            type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty)
95            return_ty_name = type_abi_info.as_owner
96        else:
97            return_ty_name = "void"
98        pkg_abi_target.writelns(
99            f"TH_EXPORT {return_ty_name} {func_abi_info.mangled_name}({params_str});",
100        )
101
102    def gen_struct_decl_file(
103        self,
104        struct: StructDecl,
105        struct_abi_info: StructABIInfo,
106    ):
107        with CHeaderWriter(
108            self.om,
109            f"include/{struct_abi_info.decl_header}",
110            FileKind.C_HEADER,
111        ) as struct_abi_decl_target:
112            struct_abi_decl_target.add_include("taihe/common.h")
113            struct_abi_decl_target.writelns(
114                f"struct {struct_abi_info.mangled_name};",
115            )
116
117    def gen_struct_defn_file(
118        self,
119        struct: StructDecl,
120        struct_abi_info: StructABIInfo,
121    ):
122        with CHeaderWriter(
123            self.om,
124            f"include/{struct_abi_info.defn_header}",
125            FileKind.C_HEADER,
126        ) as struct_abi_defn_target:
127            struct_abi_defn_target.add_include(struct_abi_info.decl_header)
128            for field in struct.fields:
129                type_abi_info = TypeABIInfo.get(self.am, field.ty_ref.resolved_ty)
130                struct_abi_defn_target.add_include(*type_abi_info.defn_headers)
131            self.gen_struct_defn(struct, struct_abi_info, struct_abi_defn_target)
132
133    def gen_struct_defn(
134        self,
135        struct: StructDecl,
136        struct_abi_info: StructABIInfo,
137        struct_abi_defn_target: CHeaderWriter,
138    ):
139        with struct_abi_defn_target.indented(
140            f"struct {struct_abi_info.mangled_name} {{",
141            f"}};",
142        ):
143            for field in struct.fields:
144                type_abi_info = TypeABIInfo.get(self.am, field.ty_ref.resolved_ty)
145                struct_abi_defn_target.writelns(
146                    f"{type_abi_info.as_owner} {field.name};",
147                )
148
149    def gen_struct_impl_file(
150        self,
151        struct: StructDecl,
152        struct_abi_info: StructABIInfo,
153    ):
154        with CHeaderWriter(
155            self.om,
156            f"include/{struct_abi_info.impl_header}",
157            FileKind.C_HEADER,
158        ) as struct_abi_impl_target:
159            struct_abi_impl_target.add_include(struct_abi_info.defn_header)
160            for field in struct.fields:
161                type_abi_info = TypeABIInfo.get(self.am, field.ty_ref.resolved_ty)
162                struct_abi_impl_target.add_include(*type_abi_info.impl_headers)
163
164    def gen_union_decl_file(
165        self,
166        union: UnionDecl,
167        union_abi_info: UnionABIInfo,
168    ):
169        with CHeaderWriter(
170            self.om,
171            f"include/{union_abi_info.decl_header}",
172            FileKind.C_HEADER,
173        ) as union_abi_decl_target:
174            union_abi_decl_target.add_include("taihe/common.h")
175            union_abi_decl_target.writelns(
176                f"union {union_abi_info.union_name};",
177                f"struct {union_abi_info.mangled_name};",
178            )
179
180    def gen_union_defn_file(
181        self,
182        union: UnionDecl,
183        union_abi_info: UnionABIInfo,
184    ):
185        with CHeaderWriter(
186            self.om,
187            f"include/{union_abi_info.defn_header}",
188            FileKind.C_HEADER,
189        ) as union_abi_defn_target:
190            union_abi_defn_target.add_include(union_abi_info.decl_header)
191            self.gen_union_defn(union, union_abi_info, union_abi_defn_target)
192            for field in union.fields:
193                if field.ty_ref is None:
194                    continue
195                type_abi_info = TypeABIInfo.get(self.am, field.ty_ref.resolved_ty)
196                union_abi_defn_target.add_include(*type_abi_info.defn_headers)
197
198    def gen_union_defn(
199        self,
200        union: UnionDecl,
201        union_abi_info: UnionABIInfo,
202        union_abi_defn_target: CHeaderWriter,
203    ):
204        with union_abi_defn_target.indented(
205            f"union {union_abi_info.union_name} {{",
206            f"}};",
207        ):
208            for field in union.fields:
209                if field.ty_ref is None:
210                    union_abi_defn_target.writelns(
211                        f"// {field.name}",
212                    )
213                    continue
214                type_abi_info = TypeABIInfo.get(self.am, field.ty_ref.resolved_ty)
215                union_abi_defn_target.writelns(
216                    f"{type_abi_info.as_owner} {field.name};",
217                )
218        with union_abi_defn_target.indented(
219            f"struct {union_abi_info.mangled_name} {{",
220            f"}};",
221        ):
222            union_abi_defn_target.writelns(
223                f"{union_abi_info.tag_type} m_tag;",
224                f"union {union_abi_info.union_name} m_data;",
225            )
226
227    def gen_union_impl_file(
228        self,
229        union: UnionDecl,
230        union_abi_info: UnionABIInfo,
231    ):
232        with CHeaderWriter(
233            self.om,
234            f"include/{union_abi_info.impl_header}",
235            FileKind.C_HEADER,
236        ) as union_abi_impl_target:
237            union_abi_impl_target.add_include(union_abi_info.defn_header)
238            for field in union.fields:
239                if field.ty_ref is None:
240                    continue
241                type_abi_info = TypeABIInfo.get(self.am, field.ty_ref.resolved_ty)
242                union_abi_impl_target.add_include(*type_abi_info.impl_headers)
243
244    def gen_iface_decl_file(
245        self,
246        iface: IfaceDecl,
247        iface_abi_info: IfaceABIInfo,
248    ):
249        with CHeaderWriter(
250            self.om,
251            f"include/{iface_abi_info.decl_header}",
252            FileKind.C_HEADER,
253        ) as iface_abi_decl_target:
254            iface_abi_decl_target.add_include("taihe/object.abi.h")
255            iface_abi_decl_target.writelns(
256                f"struct {iface_abi_info.mangled_name};",
257            )
258
259    def gen_iface_defn_file(
260        self,
261        iface: IfaceDecl,
262        iface_abi_info: IfaceABIInfo,
263    ):
264        with CHeaderWriter(
265            self.om,
266            f"include/{iface_abi_info.defn_header}",
267            FileKind.C_HEADER,
268        ) as iface_abi_defn_target:
269            iface_abi_defn_target.add_include(iface_abi_info.decl_header)
270            for ancestor, info in iface_abi_info.ancestor_dict.items():
271                if ancestor is iface:
272                    continue
273                ancestor_abi_info = IfaceABIInfo.get(self.am, ancestor)
274                iface_abi_defn_target.add_include(ancestor_abi_info.defn_header)
275            self.gen_iface_vtable(iface, iface_abi_info, iface_abi_defn_target)
276            self.gen_iface_defn(iface, iface_abi_info, iface_abi_defn_target)
277            self.gen_iface_static_cast(iface, iface_abi_info, iface_abi_defn_target)
278            self.gen_iface_dynamic_cast(iface, iface_abi_info, iface_abi_defn_target)
279
280    def gen_iface_vtable(
281        self,
282        iface: IfaceDecl,
283        iface_abi_info: IfaceABIInfo,
284        iface_abi_defn_target: CHeaderWriter,
285    ):
286        iface_abi_defn_target.writelns(
287            f"struct {iface_abi_info.ftable};",
288        )
289        with iface_abi_defn_target.indented(
290            f"struct {iface_abi_info.vtable} {{",
291            f"}};",
292        ):
293            for ancestor_item_info in iface_abi_info.ancestor_list:
294                ancestor_abi_info = IfaceABIInfo.get(self.am, ancestor_item_info.iface)
295                iface_abi_defn_target.writelns(
296                    f"struct {ancestor_abi_info.ftable} const* {ancestor_item_info.ftbl_ptr};",
297                )
298
299    def gen_iface_defn(
300        self,
301        iface: IfaceDecl,
302        iface_abi_info: IfaceABIInfo,
303        iface_abi_defn_target: CHeaderWriter,
304    ):
305        iface_abi_defn_target.writelns(
306            f"TH_EXPORT void const* const {iface_abi_info.iid};",
307        )
308        with iface_abi_defn_target.indented(
309            f"struct {iface_abi_info.mangled_name} {{",
310            f"}};",
311        ):
312            iface_abi_defn_target.writelns(
313                f"struct {iface_abi_info.vtable} const* vtbl_ptr;",
314                f"struct DataBlockHead* data_ptr;",
315            )
316
317    def gen_iface_static_cast(
318        self,
319        iface: IfaceDecl,
320        iface_abi_info: IfaceABIInfo,
321        iface_abi_defn_target: CHeaderWriter,
322    ):
323        for ancestor, info in iface_abi_info.ancestor_dict.items():
324            if ancestor is iface:
325                continue
326            ancestor_abi_info = IfaceABIInfo.get(self.am, ancestor)
327            with iface_abi_defn_target.indented(
328                f"TH_INLINE struct {ancestor_abi_info.vtable} const* {info.static_cast}(struct {iface_abi_info.vtable} const* vtbl_ptr) {{",
329                f"}}",
330            ):
331                iface_abi_defn_target.writelns(
332                    f"return vtbl_ptr ? (struct {ancestor_abi_info.vtable} const*)((void* const*)vtbl_ptr + {info.offset}) : NULL;",
333                )
334
335    def gen_iface_dynamic_cast(
336        self,
337        iface: IfaceDecl,
338        iface_abi_info: IfaceABIInfo,
339        iface_abi_defn_target: CHeaderWriter,
340    ):
341        with iface_abi_defn_target.indented(
342            f"TH_INLINE struct {iface_abi_info.vtable} const* {iface_abi_info.dynamic_cast}(struct TypeInfo const* rtti_ptr) {{",
343            f"}}",
344        ):
345            with iface_abi_defn_target.indented(
346                f"for (size_t i = 0; i < rtti_ptr->len; i++) {{",
347                f"}}",
348            ):
349                with iface_abi_defn_target.indented(
350                    f"if (rtti_ptr->idmap[i].id == {iface_abi_info.iid}) {{",
351                    f"}}",
352                ):
353                    iface_abi_defn_target.writelns(
354                        f"return (struct {iface_abi_info.vtable} const*)rtti_ptr->idmap[i].vtbl_ptr;",
355                    )
356            iface_abi_defn_target.writelns(
357                f"return NULL;",
358            )
359
360    def gen_iface_impl_file(
361        self,
362        iface: IfaceDecl,
363        iface_abi_info: IfaceABIInfo,
364    ):
365        with CHeaderWriter(
366            self.om,
367            f"include/{iface_abi_info.impl_header}",
368            FileKind.C_HEADER,
369        ) as iface_abi_impl_target:
370            iface_abi_impl_target.add_include(iface_abi_info.defn_header)
371            for method in iface.methods:
372                for param in method.params:
373                    type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty)
374                    iface_abi_impl_target.add_include(*type_abi_info.defn_headers)
375                if return_ty_ref := method.return_ty_ref:
376                    type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty)
377                    iface_abi_impl_target.add_include(*type_abi_info.defn_headers)
378            self.gen_iface_ftable(iface, iface_abi_info, iface_abi_impl_target)
379            self.gen_iface_methods(iface, iface_abi_info, iface_abi_impl_target)
380            for ancestor, info in iface_abi_info.ancestor_dict.items():
381                if ancestor is iface:
382                    continue
383                ancestor_abi_info = IfaceABIInfo.get(self.am, ancestor)
384                iface_abi_impl_target.add_include(ancestor_abi_info.impl_header)
385            for method in iface.methods:
386                for param in method.params:
387                    type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty)
388                    iface_abi_impl_target.add_include(*type_abi_info.impl_headers)
389                if return_ty_ref := method.return_ty_ref:
390                    type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty)
391                    iface_abi_impl_target.add_include(*type_abi_info.impl_headers)
392
393    def gen_iface_ftable(
394        self,
395        iface: IfaceDecl,
396        iface_abi_info: IfaceABIInfo,
397        iface_abi_impl_target: CHeaderWriter,
398    ):
399        with iface_abi_impl_target.indented(
400            f"struct {iface_abi_info.ftable} {{",
401            f"}};",
402        ):
403            for method in iface.methods:
404                params = [f"{iface_abi_info.as_param} tobj"]
405                for param in method.params:
406                    type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty)
407                    params.append(f"{type_abi_info.as_param} {param.name}")
408                params_str = ", ".join(params)
409                if return_ty_ref := method.return_ty_ref:
410                    type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty)
411                    return_ty_name = type_abi_info.as_owner
412                else:
413                    return_ty_name = "void"
414                iface_abi_impl_target.writelns(
415                    f"{return_ty_name} (*{method.name})({params_str});",
416                )
417
418    def gen_iface_methods(
419        self,
420        iface: IfaceDecl,
421        iface_abi_info: IfaceABIInfo,
422        iface_abi_impl_target: CHeaderWriter,
423    ):
424        for method in iface.methods:
425            method_abi_info = IfaceMethodABIInfo.get(self.am, method)
426            params = [f"{iface_abi_info.as_param} tobj"]
427            args = ["tobj"]
428            for param in method.params:
429                type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty)
430                params.append(f"{type_abi_info.as_param} {param.name}")
431                args.append(param.name)
432            params_str = ", ".join(params)
433            args_str = ", ".join(args)
434            if return_ty_ref := method.return_ty_ref:
435                type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty)
436                return_ty_name = type_abi_info.as_owner
437            else:
438                return_ty_name = "void"
439            with iface_abi_impl_target.indented(
440                f"TH_INLINE {return_ty_name} {method_abi_info.mangled_name}({params_str}) {{",
441                f"}}",
442            ):
443                iface_abi_impl_target.writelns(
444                    f"return tobj.vtbl_ptr->{iface_abi_info.ancestor_dict[iface].ftbl_ptr}->{method.name}({args_str});",
445                )
446
447
448class ABISourcesGenerator:
449    def __init__(self, om: OutputManager, am: AnalysisManager):
450        self.om = om
451        self.am = am
452
453    def generate(self, pg: PackageGroup):
454        for pkg in pg.packages:
455            self.gen_package_file(pkg)
456
457    def gen_package_file(self, pkg: PackageDecl):
458        pkg_abi_info = PackageABIInfo.get(self.am, pkg)
459        with CSourceWriter(
460            self.om,
461            f"src/{pkg_abi_info.src}",
462            FileKind.C_SOURCE,
463        ) as pkg_abi_src_target:
464            for iface in pkg.interfaces:
465                iface_abi_info = IfaceABIInfo.get(self.am, iface)
466                pkg_abi_src_target.add_include(iface_abi_info.defn_header)
467                self.gen_iface_iid(iface, iface_abi_info, pkg_abi_src_target)
468
469    def gen_iface_iid(
470        self,
471        iface: IfaceDecl,
472        iface_abi_info: IfaceABIInfo,
473        pkg_abi_src_target: CSourceWriter,
474    ):
475        pkg_abi_src_target.writelns(
476            f"void const* const {iface_abi_info.iid} = &{iface_abi_info.iid};",
477        )