• 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    IfaceABIInfo,
18)
19from taihe.codegen.abi.writer import CHeaderWriter, CSourceWriter
20from taihe.codegen.ani.analyses import (
21    ANI_CLASS,
22    ANINativeFuncInfo,
23    ANIRegisterInfo,
24    GlobFuncANIInfo,
25    IfaceANIInfo,
26    IfaceMethodANIInfo,
27    PackageANIInfo,
28    StructANIInfo,
29    TypeANIInfo,
30    UnionANIInfo,
31    UnionFieldANIInfo,
32)
33from taihe.codegen.cpp.analyses import (
34    GlobFuncCppUserInfo,
35    IfaceCppInfo,
36    IfaceMethodCppInfo,
37    PackageCppUserInfo,
38    StructCppInfo,
39    TypeCppInfo,
40    UnionCppInfo,
41)
42from taihe.semantics.declarations import (
43    GlobFuncDecl,
44    IfaceDecl,
45    IfaceMethodDecl,
46    PackageDecl,
47    PackageGroup,
48    StructDecl,
49    UnionDecl,
50)
51from taihe.semantics.types import (
52    Type,
53)
54from taihe.utils.analyses import AnalysisManager
55from taihe.utils.outputs import FileKind, OutputManager
56
57
58class ANICodeGenerator:
59    def __init__(self, om: OutputManager, am: AnalysisManager):
60        self.om = om
61        self.am = am
62
63    def generate(self, pg: PackageGroup):
64        for pkg in pg.packages:
65            self.gen_package(pkg)
66        self.gen_constructor(pg)
67
68    def gen_constructor(self, pg: PackageGroup):
69        with CSourceWriter(
70            self.om,
71            f"temp/ani_constructor.cpp",
72            FileKind.TEMPLATE,
73        ) as constructor_target:
74            constructor_target.writelns(
75                f"#if __has_include(<ani.h>)",
76                f"#include <ani.h>",
77                f"#elif __has_include(<ani/ani.h>)",
78                f"#include <ani/ani.h>",
79                f"#else",
80                f'#error "ani.h not found. Please ensure the Ani SDK is correctly installed."',
81                f"#endif",
82            )
83            with constructor_target.indented(
84                f"ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) {{",
85                f"}}",
86            ):
87                constructor_target.writelns(
88                    # f"::taihe::set_vm(vm);",
89                    f"ani_env *env;",
90                )
91                with constructor_target.indented(
92                    f"if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {{",
93                    f"}}",
94                ):
95                    constructor_target.writelns(
96                        f"return ANI_ERROR;",
97                    )
98                for pkg in pg.packages:
99                    pkg_ani_info = PackageANIInfo.get(self.am, pkg)
100                    constructor_target.add_include(pkg_ani_info.header)
101                    with constructor_target.indented(
102                        f"if (ANI_OK != {pkg_ani_info.cpp_ns}::ANIRegister(env)) {{",
103                        f"}}",
104                    ):
105                        constructor_target.writelns(
106                            f'std::cerr << "Error from {pkg_ani_info.cpp_ns}::ANIRegister" << std::endl;',
107                            f"return ANI_ERROR;",
108                        )
109                constructor_target.writelns(
110                    f"*result = ANI_VERSION_1;",
111                    f"return ANI_OK;",
112                )
113
114    def gen_package(self, pkg: PackageDecl):
115        for iface in pkg.interfaces:
116            self.gen_iface_files(iface)
117        for struct in pkg.structs:
118            self.gen_struct_files(struct)
119        for union in pkg.unions:
120            self.gen_union_files(union)
121        pkg_ani_info = PackageANIInfo.get(self.am, pkg)
122        pkg_cpp_user_info = PackageCppUserInfo.get(self.am, pkg)
123        self.gen_package_header(pkg, pkg_ani_info, pkg_cpp_user_info)
124        self.gen_package_source(pkg, pkg_ani_info, pkg_cpp_user_info)
125
126    def gen_package_header(
127        self,
128        pkg: PackageDecl,
129        pkg_ani_info: PackageANIInfo,
130        pkg_cpp_user_info: PackageCppUserInfo,
131    ):
132        with CHeaderWriter(
133            self.om,
134            f"include/{pkg_ani_info.header}",
135            FileKind.CPP_HEADER,
136        ) as pkg_ani_header_target:
137            pkg_ani_header_target.add_include("taihe/platform/ani.hpp")
138            with pkg_ani_header_target.indented(
139                f"namespace {pkg_ani_info.cpp_ns} {{",
140                f"}}",
141                indent="",
142            ):
143                pkg_ani_header_target.writelns(
144                    f"ani_status ANIRegister(ani_env *env);",
145                )
146
147    def gen_package_source(
148        self,
149        pkg: PackageDecl,
150        pkg_ani_info: PackageANIInfo,
151        pkg_cpp_user_info: PackageCppUserInfo,
152    ):
153        with CSourceWriter(
154            self.om,
155            f"src/{pkg_ani_info.source}",
156            FileKind.CPP_SOURCE,
157        ) as pkg_ani_source_target:
158            pkg_ani_source_target.add_include(pkg_ani_info.header)
159            pkg_ani_source_target.add_include(pkg_cpp_user_info.header)
160
161            # generate functions
162            with pkg_ani_source_target.indented(
163                f"namespace local {{",
164                f"}}",
165                indent="",
166            ):
167                for iface in pkg.interfaces:
168                    with pkg_ani_source_target.indented(
169                        f"namespace {iface.name} {{",
170                        f"}}",
171                        indent="",
172                    ):
173                        iface_abi_info = IfaceABIInfo.get(self.am, iface)
174                        for ancestor in iface_abi_info.ancestor_dict:
175                            for method in ancestor.methods:
176                                self.gen_method(
177                                    iface,
178                                    method,
179                                    pkg_ani_source_target,
180                                    ancestor,
181                                    method.name,
182                                )
183                        self.gen_obj_drop(pkg_ani_source_target, "_obj_drop")
184                        self.gen_obj_dup(pkg_ani_source_target, "_obj_dup")
185                for func in pkg.functions:
186                    self.gen_func(func, pkg_ani_source_target, func.name)
187
188            # register infos
189            register_infos: list[ANIRegisterInfo] = []
190
191            pkg_register_info = ANIRegisterInfo(
192                parent_scope=pkg_ani_info.ns.scope,
193                impl_desc=pkg_ani_info.ns.impl_desc,
194                member_infos=[],
195            )
196            register_infos.append(pkg_register_info)
197            for func in pkg.functions:
198                func_ani_info = GlobFuncANIInfo.get(self.am, func)
199                func_info = ANINativeFuncInfo(
200                    sts_native_name=func_ani_info.sts_native_name,
201                    full_name=f"local::{func.name}",
202                )
203                pkg_register_info.member_infos.append(func_info)
204            for iface in pkg.interfaces:
205                iface_abi_info = IfaceABIInfo.get(self.am, iface)
206                iface_ani_info = IfaceANIInfo.get(self.am, iface)
207                iface_register_info = ANIRegisterInfo(
208                    parent_scope=ANI_CLASS,
209                    impl_desc=iface_ani_info.impl_desc,
210                    member_infos=[],
211                )
212                register_infos.append(iface_register_info)
213                for ancestor in iface_abi_info.ancestor_dict:
214                    for method in ancestor.methods:
215                        method_ani_info = IfaceMethodANIInfo.get(self.am, method)
216                        method_info = ANINativeFuncInfo(
217                            sts_native_name=method_ani_info.sts_native_name,
218                            full_name=f"local::{iface.name}::{method.name}",
219                        )
220                        iface_register_info.member_infos.append(method_info)
221                pkg_ani_source_target.add_include("taihe/object.hpp")
222                obj_drop_info = ANINativeFuncInfo(
223                    sts_native_name="_obj_drop",
224                    full_name=f"local::{iface.name}::_obj_drop",
225                )
226                iface_register_info.member_infos.append(obj_drop_info)
227                obj_dup_info = ANINativeFuncInfo(
228                    sts_native_name="_obj_dup",
229                    full_name=f"local::{iface.name}::_obj_dup",
230                )
231                iface_register_info.member_infos.append(obj_dup_info)
232
233            with pkg_ani_source_target.indented(
234                f"namespace {pkg_ani_info.cpp_ns} {{",
235                f"}}",
236                indent="",
237            ):
238                with pkg_ani_source_target.indented(
239                    f"ani_status ANIRegister(ani_env *env) {{",
240                    f"}}",
241                ):
242                    # TODO: set_vm in constructor
243                    with pkg_ani_source_target.indented(
244                        f"if (::taihe::get_vm() == nullptr) {{",
245                        f"}}",
246                    ):
247                        pkg_ani_source_target.writelns(
248                            f"ani_vm *vm;",
249                        )
250                        with pkg_ani_source_target.indented(
251                            f"if (ANI_OK != env->GetVM(&vm)) {{",
252                            f"}}",
253                        ):
254                            pkg_ani_source_target.writelns(
255                                f"return ANI_ERROR;",
256                            )
257                        pkg_ani_source_target.writelns(
258                            f"::taihe::set_vm(vm);",
259                        )
260                    for register_info in register_infos:
261                        parent_scope = register_info.parent_scope
262                        with pkg_ani_source_target.indented(
263                            f"{{",
264                            f"}}",
265                        ):
266                            pkg_ani_source_target.writelns(
267                                f"{parent_scope} ani_env;",
268                            )
269                            with pkg_ani_source_target.indented(
270                                f'if (ANI_OK != env->Find{parent_scope.suffix}("{register_info.impl_desc}", &ani_env)) {{',
271                                f"}}",
272                            ):
273                                pkg_ani_source_target.writelns(
274                                    f"return ANI_ERROR;",
275                                )
276                            with pkg_ani_source_target.indented(
277                                f"ani_native_function methods[] = {{",
278                                f"}};",
279                            ):
280                                for member_info in register_info.member_infos:
281                                    pkg_ani_source_target.writelns(
282                                        f'{{"{member_info.sts_native_name}", nullptr, reinterpret_cast<void*>({member_info.full_name})}},',
283                                    )
284                            with pkg_ani_source_target.indented(
285                                f"if (ANI_OK != env->{parent_scope.suffix}_BindNative{parent_scope.member.suffix}s(ani_env, methods, sizeof(methods) / sizeof(ani_native_function))) {{",
286                                f"}}",
287                            ):
288                                pkg_ani_source_target.writelns(
289                                    f"return ANI_ERROR;",
290                                )
291                    pkg_ani_source_target.writelns(
292                        f"return ANI_OK;",
293                    )
294
295    def gen_func(
296        self,
297        func: GlobFuncDecl,
298        pkg_ani_source_target: CSourceWriter,
299        name: str,
300    ):
301        func_cpp_user_info = GlobFuncCppUserInfo.get(self.am, func)
302        ani_params = []
303        ani_params.append("[[maybe_unused]] ani_env *env")
304        ani_args = []
305        cpp_args = []
306        for param in func.params:
307            type_ani_info = TypeANIInfo.get(self.am, param.ty_ref.resolved_ty)
308            ani_arg = f"ani_arg_{param.name}"
309            cpp_arg = f"cpp_arg_{param.name}"
310            ani_params.append(f"{type_ani_info.ani_type} {ani_arg}")
311            ani_args.append(ani_arg)
312            cpp_args.append(cpp_arg)
313        ani_params_str = ", ".join(ani_params)
314        if return_ty_ref := func.return_ty_ref:
315            type_ani_info = TypeANIInfo.get(self.am, return_ty_ref.resolved_ty)
316            ani_return_ty_name = type_ani_info.ani_type
317        else:
318            ani_return_ty_name = "void"
319        with pkg_ani_source_target.indented(
320            f"static {ani_return_ty_name} {name}({ani_params_str}) {{",
321            f"}}",
322        ):
323            for param, ani_arg, cpp_arg in zip(
324                func.params, ani_args, cpp_args, strict=True
325            ):
326                type_ani_info = TypeANIInfo.get(self.am, param.ty_ref.resolved_ty)
327                type_ani_info.from_ani(pkg_ani_source_target, "env", ani_arg, cpp_arg)
328            cpp_args_str = ", ".join(cpp_args)
329            if return_ty_ref := func.return_ty_ref:
330                type_cpp_info = TypeCppInfo.get(self.am, return_ty_ref.resolved_ty)
331                type_ani_info = TypeANIInfo.get(self.am, return_ty_ref.resolved_ty)
332                cpp_return_ty_name = type_cpp_info.as_owner
333                cpp_res = "cpp_result"
334                ani_res = "ani_result"
335                pkg_ani_source_target.writelns(
336                    f"{cpp_return_ty_name} {cpp_res} = {func_cpp_user_info.full_name}({cpp_args_str});",
337                    f"if (::taihe::has_error()) {{ return {type_ani_info.ani_type}{{}}; }}",
338                )
339                type_ani_info.into_ani(pkg_ani_source_target, "env", cpp_res, ani_res)
340                pkg_ani_source_target.writelns(
341                    f"return {ani_res};",
342                )
343            else:
344                pkg_ani_source_target.writelns(
345                    f"{func_cpp_user_info.full_name}({cpp_args_str});",
346                )
347
348    def gen_method(
349        self,
350        iface: IfaceDecl,
351        method: IfaceMethodDecl,
352        pkg_ani_source_target: CSourceWriter,
353        ancestor: IfaceDecl,
354        name: str,
355    ):
356        method_cpp_info = IfaceMethodCppInfo.get(self.am, method)
357        iface_cpp_info = IfaceCppInfo.get(self.am, iface)
358        iface_abi_info = IfaceABIInfo.get(self.am, iface)
359        iface_ani_info = IfaceANIInfo.get(self.am, iface)
360        ancestor_cpp_info = IfaceCppInfo.get(self.am, ancestor)
361        ani_params = []
362        ani_params.append("[[maybe_unused]] ani_env *env")
363        ani_params.append("[[maybe_unused]] ani_object object")
364        ani_args = []
365        cpp_args = []
366        for param in method.params:
367            type_ani_info = TypeANIInfo.get(self.am, param.ty_ref.resolved_ty)
368            ani_arg = f"ani_arg_{param.name}"
369            cpp_arg = f"cpp_arg_{param.name}"
370            ani_params.append(f"{type_ani_info.ani_type} {ani_arg}")
371            ani_args.append(ani_arg)
372            cpp_args.append(cpp_arg)
373        ani_params_str = ", ".join(ani_params)
374        if return_ty_ref := method.return_ty_ref:
375            type_ani_info = TypeANIInfo.get(self.am, return_ty_ref.resolved_ty)
376            ani_return_ty_name = type_ani_info.ani_type
377        else:
378            ani_return_ty_name = "void"
379        with pkg_ani_source_target.indented(
380            f"static {ani_return_ty_name} {name}({ani_params_str}) {{",
381            f"}}",
382        ):
383            pkg_ani_source_target.writelns(
384                f"ani_long ani_data_ptr;",
385                f'env->Object_GetField_Long(object, TH_ANI_FIND_CLASS_FIELD(env, "{iface_ani_info.impl_desc}", "_data_ptr"), reinterpret_cast<ani_long*>(&ani_data_ptr));',
386                f"ani_long ani_vtbl_ptr;",
387                f'env->Object_GetField_Long(object, TH_ANI_FIND_CLASS_FIELD(env, "{iface_ani_info.impl_desc}", "_vtbl_ptr"), reinterpret_cast<ani_long*>(&ani_vtbl_ptr));',
388                f"DataBlockHead* cpp_data_ptr = reinterpret_cast<DataBlockHead*>(ani_data_ptr);",
389                f"{iface_abi_info.vtable}* cpp_vtbl_ptr = reinterpret_cast<{iface_abi_info.vtable}*>(ani_vtbl_ptr);",
390                f"{iface_cpp_info.full_weak_name} cpp_iface = {iface_cpp_info.full_weak_name}({{cpp_vtbl_ptr, cpp_data_ptr}});",
391            )
392            for param, ani_arg, cpp_arg in zip(
393                method.params, ani_args, cpp_args, strict=True
394            ):
395                type_ani_info = TypeANIInfo.get(self.am, param.ty_ref.resolved_ty)
396                type_ani_info.from_ani(pkg_ani_source_target, "env", ani_arg, cpp_arg)
397            cpp_args_str = ", ".join(cpp_args)
398            if return_ty_ref := method.return_ty_ref:
399                type_cpp_info = TypeCppInfo.get(self.am, return_ty_ref.resolved_ty)
400                type_ani_info = TypeANIInfo.get(self.am, return_ty_ref.resolved_ty)
401                cpp_return_ty_name = type_cpp_info.as_owner
402                cpp_res = "cpp_result"
403                ani_res = "ani_result"
404                pkg_ani_source_target.writelns(
405                    f"{cpp_return_ty_name} {cpp_res} = {ancestor_cpp_info.as_param}(cpp_iface)->{method_cpp_info.call_name}({cpp_args_str});",
406                    f"if (::taihe::has_error()) {{ return {type_ani_info.ani_type}{{}}; }}",
407                )
408                type_ani_info.into_ani(pkg_ani_source_target, "env", cpp_res, ani_res)
409                pkg_ani_source_target.writelns(
410                    f"return {ani_res};",
411                )
412            else:
413                pkg_ani_source_target.writelns(
414                    f"{ancestor_cpp_info.as_param}(cpp_iface)->{method_cpp_info.call_name}({cpp_args_str});",
415                )
416
417    def gen_obj_drop(
418        self,
419        pkg_ani_source_target: CSourceWriter,
420        name: str,
421    ):
422        with pkg_ani_source_target.indented(
423            f"static void {name}([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class clazz, ani_long data_ptr) {{",
424            f"}}",
425        ):
426            pkg_ani_source_target.writelns(
427                f"tobj_drop(reinterpret_cast<DataBlockHead*>(data_ptr));",
428            )
429
430    def gen_obj_dup(
431        self,
432        pkg_ani_source_target: CSourceWriter,
433        name: str,
434    ):
435        with pkg_ani_source_target.indented(
436            f"static ani_long {name}([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class clazz, ani_long data_ptr) {{",
437            f"}}",
438        ):
439            pkg_ani_source_target.writelns(
440                f"return reinterpret_cast<ani_long>(tobj_dup(reinterpret_cast<DataBlockHead*>(data_ptr)));",
441            )
442
443    def gen_iface_files(
444        self,
445        iface: IfaceDecl,
446    ):
447        iface_abi_info = IfaceABIInfo.get(self.am, iface)
448        iface_cpp_info = IfaceCppInfo.get(self.am, iface)
449        iface_ani_info = IfaceANIInfo.get(self.am, iface)
450        self.gen_iface_conv_decl_file(
451            iface,
452            iface_abi_info,
453            iface_cpp_info,
454            iface_ani_info,
455        )
456        self.gen_iface_conv_impl_file(
457            iface,
458            iface_abi_info,
459            iface_cpp_info,
460            iface_ani_info,
461        )
462
463    def gen_iface_conv_decl_file(
464        self,
465        iface: IfaceDecl,
466        iface_abi_info: IfaceABIInfo,
467        iface_cpp_info: IfaceCppInfo,
468        iface_ani_info: IfaceANIInfo,
469    ):
470        with CHeaderWriter(
471            self.om,
472            f"include/{iface_ani_info.decl_header}",
473            FileKind.C_HEADER,
474        ) as iface_ani_decl_target:
475            iface_ani_decl_target.add_include("taihe/platform/ani.hpp")
476            iface_ani_decl_target.add_include(iface_cpp_info.defn_header)
477            with iface_ani_decl_target.indented(
478                f"template<> struct ::taihe::from_ani_t<{iface_cpp_info.as_owner}> {{",
479                f"}};",
480            ):
481                iface_ani_decl_target.writelns(
482                    f"inline {iface_cpp_info.as_owner} operator()(ani_env* env, ani_object ani_obj) const;",
483                )
484            with iface_ani_decl_target.indented(
485                f"template<> struct ::taihe::into_ani_t<{iface_cpp_info.as_owner}> {{",
486                f"}};",
487            ):
488                iface_ani_decl_target.writelns(
489                    f"inline ani_object operator()(ani_env* env, {iface_cpp_info.as_owner} cpp_obj) const;",
490                )
491
492    def gen_iface_conv_impl_file(
493        self,
494        iface: IfaceDecl,
495        iface_abi_info: IfaceABIInfo,
496        iface_cpp_info: IfaceCppInfo,
497        iface_ani_info: IfaceANIInfo,
498    ):
499        with CHeaderWriter(
500            self.om,
501            f"include/{iface_ani_info.impl_header}",
502            FileKind.C_HEADER,
503        ) as iface_ani_impl_target:
504            iface_ani_impl_target.add_include(iface_ani_info.decl_header)
505            iface_ani_impl_target.add_include(iface_cpp_info.impl_header)
506            self.gen_iface_from_ani_func(
507                iface,
508                iface_abi_info,
509                iface_cpp_info,
510                iface_ani_info,
511                iface_ani_impl_target,
512            )
513            self.gen_iface_into_ani_func(
514                iface,
515                iface_abi_info,
516                iface_cpp_info,
517                iface_ani_info,
518                iface_ani_impl_target,
519            )
520
521    def gen_iface_from_ani_func(
522        self,
523        iface: IfaceDecl,
524        iface_abi_info: IfaceABIInfo,
525        iface_cpp_info: IfaceCppInfo,
526        iface_ani_info: IfaceANIInfo,
527        iface_ani_impl_target: CHeaderWriter,
528    ):
529        with iface_ani_impl_target.indented(
530            f"inline {iface_cpp_info.as_owner} taihe::from_ani_t<{iface_cpp_info.as_owner}>::operator()(ani_env* env, ani_object ani_obj) const {{",
531            f"}}",
532        ):
533            with iface_ani_impl_target.indented(
534                f"struct cpp_impl_t : ::taihe::dref_guard {{",
535                f"}};",
536            ):
537                iface_ani_impl_target.writelns(
538                    f"cpp_impl_t(ani_env* env, ani_ref val) : ::taihe::dref_guard(env, val) {{}}",
539                )
540                for ancestor in iface_abi_info.ancestor_dict:
541                    for method in ancestor.methods:
542                        method_cpp_info = IfaceMethodCppInfo.get(self.am, method)
543                        method_ani_info = IfaceMethodANIInfo.get(self.am, method)
544                        inner_cpp_params = []
545                        inner_cpp_args = []
546                        inner_ani_args = []
547                        for param in method.params:
548                            inner_cpp_arg = f"cpp_arg_{param.name}"
549                            inner_ani_arg = f"ani_arg_{param.name}"
550                            type_cpp_info = TypeCppInfo.get(
551                                self.am, param.ty_ref.resolved_ty
552                            )
553                            inner_cpp_params.append(
554                                f"{type_cpp_info.as_param} {inner_cpp_arg}"
555                            )
556                            inner_cpp_args.append(inner_cpp_arg)
557                            inner_ani_args.append(inner_ani_arg)
558                        inner_cpp_params_str = ", ".join(inner_cpp_params)
559                        if return_ty_ref := method.return_ty_ref:
560                            type_cpp_info = TypeCppInfo.get(
561                                self.am, return_ty_ref.resolved_ty
562                            )
563                            cpp_return_ty_name = type_cpp_info.as_owner
564                        else:
565                            cpp_return_ty_name = "void"
566                        with iface_ani_impl_target.indented(
567                            f"{cpp_return_ty_name} {method_cpp_info.impl_name}({inner_cpp_params_str}) {{",
568                            f"}}",
569                        ):
570                            iface_ani_impl_target.writelns(
571                                f"::taihe::env_guard guard;",
572                                f"ani_env *env = guard.get_env();",
573                            )
574                            for param, inner_cpp_arg, inner_ani_arg in zip(
575                                method.params,
576                                inner_cpp_args,
577                                inner_ani_args,
578                                strict=True,
579                            ):
580                                type_ani_info = TypeANIInfo.get(
581                                    self.am, param.ty_ref.resolved_ty
582                                )
583                                type_ani_info.into_ani(
584                                    iface_ani_impl_target,
585                                    "env",
586                                    inner_cpp_arg,
587                                    inner_ani_arg,
588                                )
589                            inner_ani_args_trailing = "".join(
590                                ", " + inner_ani_arg for inner_ani_arg in inner_ani_args
591                            )
592                            if return_ty_ref := method.return_ty_ref:
593                                inner_ani_res = "ani_result"
594                                inner_cpp_res = "cpp_result"
595                                type_ani_info = TypeANIInfo.get(
596                                    self.am, return_ty_ref.resolved_ty
597                                )
598                                iface_ani_impl_target.writelns(
599                                    f"{type_ani_info.ani_type} {inner_ani_res};",
600                                    f'env->Object_CallMethod_{type_ani_info.ani_type.suffix}(static_cast<ani_object>(this->ref), TH_ANI_FIND_CLASS_METHOD(env, "{iface_ani_info.type_desc}", "{method_ani_info.ani_method_name}", nullptr), reinterpret_cast<{type_ani_info.ani_type.base}*>(&{inner_ani_res}){inner_ani_args_trailing});',
601                                )
602                                type_ani_info.from_ani(
603                                    iface_ani_impl_target,
604                                    "env",
605                                    inner_ani_res,
606                                    inner_cpp_res,
607                                )
608                                iface_ani_impl_target.writelns(
609                                    f"return {inner_cpp_res};",
610                                )
611                            else:
612                                iface_ani_impl_target.writelns(
613                                    f'env->Object_CallMethod_Void(static_cast<ani_object>(this->ref), TH_ANI_FIND_CLASS_METHOD(env, "{iface_ani_info.type_desc}", "{method_ani_info.ani_method_name}", nullptr){inner_ani_args_trailing});',
614                                )
615                with iface_ani_impl_target.indented(
616                    f"uintptr_t getGlobalReference() const {{",
617                    f"}}",
618                ):
619                    iface_ani_impl_target.writelns(
620                        f"return reinterpret_cast<uintptr_t>(this->ref);",
621                    )
622            iface_ani_impl_target.writelns(
623                f"return ::taihe::make_holder<cpp_impl_t, {iface_cpp_info.as_owner}, ::taihe::platform::ani::AniObject>(env, ani_obj);",
624            )
625
626    def gen_iface_into_ani_func(
627        self,
628        iface: IfaceDecl,
629        iface_abi_info: IfaceABIInfo,
630        iface_cpp_info: IfaceCppInfo,
631        iface_ani_info: IfaceANIInfo,
632        iface_ani_impl_target: CHeaderWriter,
633    ):
634        with iface_ani_impl_target.indented(
635            f"inline ani_object taihe::into_ani_t<{iface_cpp_info.as_owner}>::operator()(ani_env* env, {iface_cpp_info.as_owner} cpp_obj) const {{",
636            f"}}",
637        ):
638            iface_ani_impl_target.writelns(
639                f"ani_long ani_vtbl_ptr = reinterpret_cast<ani_long>(cpp_obj.m_handle.vtbl_ptr);",
640                f"ani_long ani_data_ptr = reinterpret_cast<ani_long>(cpp_obj.m_handle.data_ptr);",
641                f"cpp_obj.m_handle.data_ptr = nullptr;",
642                f"ani_object ani_obj;",
643                f'env->Object_New(TH_ANI_FIND_CLASS(env, "{iface_ani_info.impl_desc}"), TH_ANI_FIND_CLASS_METHOD(env, "{iface_ani_info.impl_desc}", "_initialize", "JJ:V"), &ani_obj, ani_vtbl_ptr, ani_data_ptr);',
644                f"return ani_obj;",
645            )
646
647    def gen_struct_files(
648        self,
649        struct: StructDecl,
650    ):
651        struct_cpp_info = StructCppInfo.get(self.am, struct)
652        struct_ani_info = StructANIInfo.get(self.am, struct)
653        self.gen_struct_conv_decl_file(
654            struct,
655            struct_cpp_info,
656            struct_ani_info,
657        )
658        self.gen_struct_conv_impl_file(
659            struct,
660            struct_cpp_info,
661            struct_ani_info,
662        )
663
664    def gen_struct_conv_decl_file(
665        self,
666        struct: StructDecl,
667        struct_cpp_info: StructCppInfo,
668        struct_ani_info: StructANIInfo,
669    ):
670        with CHeaderWriter(
671            self.om,
672            f"include/{struct_ani_info.decl_header}",
673            FileKind.C_HEADER,
674        ) as struct_ani_decl_target:
675            struct_ani_decl_target.add_include("taihe/platform/ani.hpp")
676            struct_ani_decl_target.add_include(struct_cpp_info.defn_header)
677            with struct_ani_decl_target.indented(
678                f"template<> struct ::taihe::from_ani_t<{struct_cpp_info.as_owner}> {{",
679                f"}};",
680            ):
681                struct_ani_decl_target.writelns(
682                    f"inline {struct_cpp_info.as_owner} operator()(ani_env* env, ani_object ani_obj) const;",
683                )
684            with struct_ani_decl_target.indented(
685                f"template<> struct ::taihe::into_ani_t<{struct_cpp_info.as_owner}> {{",
686                f"}};",
687            ):
688                struct_ani_decl_target.writelns(
689                    f"inline ani_object operator()(ani_env* env, {struct_cpp_info.as_owner} cpp_obj) const;",
690                )
691
692    def gen_struct_conv_impl_file(
693        self,
694        struct: StructDecl,
695        struct_cpp_info: StructCppInfo,
696        struct_ani_info: StructANIInfo,
697    ):
698        with CHeaderWriter(
699            self.om,
700            f"include/{struct_ani_info.impl_header}",
701            FileKind.C_HEADER,
702        ) as struct_ani_impl_target:
703            struct_ani_impl_target.add_include(struct_ani_info.decl_header)
704            struct_ani_impl_target.add_include(struct_cpp_info.impl_header)
705            self.gen_struct_from_ani_func(
706                struct,
707                struct_cpp_info,
708                struct_ani_info,
709                struct_ani_impl_target,
710            )
711            self.gen_struct_into_ani_func(
712                struct,
713                struct_cpp_info,
714                struct_ani_info,
715                struct_ani_impl_target,
716            )
717
718    def gen_struct_from_ani_func(
719        self,
720        struct: StructDecl,
721        struct_cpp_info: StructCppInfo,
722        struct_ani_info: StructANIInfo,
723        struct_ani_impl_target: CHeaderWriter,
724    ):
725        with struct_ani_impl_target.indented(
726            f"inline {struct_cpp_info.as_owner} taihe::from_ani_t<{struct_cpp_info.as_owner}>::operator()(ani_env* env, ani_object ani_obj) const {{",
727            f"}}",
728        ):
729            cpp_field_results = []
730            for parts in struct_ani_info.sts_final_fields:
731                final = parts[-1]
732                type_ani_info = TypeANIInfo.get(self.am, final.ty_ref.resolved_ty)
733                ani_field_value = f"ani_field_{final.name}"
734                cpp_field_result = f"cpp_field_{final.name}"
735                struct_ani_impl_target.writelns(
736                    f"{type_ani_info.ani_type} {ani_field_value};",
737                )
738                if struct_ani_info.is_class():
739                    struct_ani_impl_target.writelns(
740                        f'env->Object_GetField_{type_ani_info.ani_type.suffix}(ani_obj, TH_ANI_FIND_CLASS_FIELD(env, "{struct_ani_info.type_desc}", "{final.name}"), reinterpret_cast<{type_ani_info.ani_type.base}*>(&{ani_field_value}));',
741                    )
742                else:
743                    struct_ani_impl_target.writelns(
744                        f'env->Object_CallMethod_{type_ani_info.ani_type.suffix}(ani_obj, TH_ANI_FIND_CLASS_METHOD(env, "{struct_ani_info.type_desc}", "<get>{final.name}", nullptr), reinterpret_cast<{type_ani_info.ani_type.base}*>(&{ani_field_value}));',
745                    )
746                type_ani_info.from_ani(
747                    struct_ani_impl_target, "env", ani_field_value, cpp_field_result
748                )
749                cpp_field_results.append(cpp_field_result)
750            cpp_moved_fields_str = ", ".join(
751                f"std::move({cpp_field_result})"
752                for cpp_field_result in cpp_field_results
753            )
754            struct_ani_impl_target.writelns(
755                f"return {struct_cpp_info.as_owner}{{{cpp_moved_fields_str}}};",
756            )
757
758    def gen_struct_into_ani_func(
759        self,
760        struct: StructDecl,
761        struct_cpp_info: StructCppInfo,
762        struct_ani_info: StructANIInfo,
763        struct_ani_impl_target: CHeaderWriter,
764    ):
765        ani_field_results = []
766        with struct_ani_impl_target.indented(
767            f"inline ani_object taihe::into_ani_t<{struct_cpp_info.as_owner}>::operator()(ani_env* env, {struct_cpp_info.as_owner} cpp_obj) const {{",
768            f"}}",
769        ):
770            for parts in struct_ani_info.sts_final_fields:
771                final = parts[-1]
772                ani_field_result = f"ani_field_{final.name}"
773                type_ani_info = TypeANIInfo.get(self.am, final.ty_ref.resolved_ty)
774                type_ani_info.into_ani(
775                    struct_ani_impl_target,
776                    "env",
777                    ".".join(("cpp_obj", *(part.name for part in parts))),
778                    ani_field_result,
779                )
780                ani_field_results.append(ani_field_result)
781            ani_field_results_trailing = "".join(
782                ", " + ani_field_result for ani_field_result in ani_field_results
783            )
784            struct_ani_impl_target.writelns(
785                f"ani_object ani_obj;",
786                f'env->Object_New(TH_ANI_FIND_CLASS(env, "{struct_ani_info.impl_desc}"), TH_ANI_FIND_CLASS_METHOD(env, "{struct_ani_info.impl_desc}", "<ctor>", nullptr), &ani_obj{ani_field_results_trailing});',
787                f"return ani_obj;",
788            )
789
790    def gen_union_files(
791        self,
792        union: UnionDecl,
793    ):
794        union_cpp_info = UnionCppInfo.get(self.am, union)
795        union_ani_info = UnionANIInfo.get(self.am, union)
796        self.gen_union_conv_decl_file(
797            union,
798            union_cpp_info,
799            union_ani_info,
800        )
801        self.gen_union_conv_impl_file(
802            union,
803            union_cpp_info,
804            union_ani_info,
805        )
806
807    def gen_union_conv_decl_file(
808        self,
809        union: UnionDecl,
810        union_cpp_info: UnionCppInfo,
811        union_ani_info: UnionANIInfo,
812    ):
813        with CHeaderWriter(
814            self.om,
815            f"include/{union_ani_info.decl_header}",
816            FileKind.C_HEADER,
817        ) as union_ani_decl_target:
818            union_ani_decl_target.add_include("taihe/platform/ani.hpp")
819            union_ani_decl_target.add_include(union_cpp_info.defn_header)
820            with union_ani_decl_target.indented(
821                f"template<> struct ::taihe::from_ani_t<{union_cpp_info.as_owner}> {{",
822                f"}};",
823            ):
824                union_ani_decl_target.writelns(
825                    f"inline {union_cpp_info.as_owner} operator()(ani_env* env, ani_ref ani_value) const;",
826                )
827            with union_ani_decl_target.indented(
828                f"template<> struct ::taihe::into_ani_t<{union_cpp_info.as_owner}> {{",
829                f"}};",
830            ):
831                union_ani_decl_target.writelns(
832                    f"inline ani_ref operator()(ani_env* env, {union_cpp_info.as_owner} cpp_value) const;",
833                )
834
835    def gen_union_conv_impl_file(
836        self,
837        union: UnionDecl,
838        union_cpp_info: UnionCppInfo,
839        union_ani_info: UnionANIInfo,
840    ):
841        with CHeaderWriter(
842            self.om,
843            f"include/{union_ani_info.impl_header}",
844            FileKind.C_HEADER,
845        ) as union_ani_impl_target:
846            union_ani_impl_target.add_include(union_ani_info.decl_header)
847            union_ani_impl_target.add_include(union_cpp_info.impl_header)
848            self.gen_union_from_ani_func(
849                union,
850                union_cpp_info,
851                union_ani_info,
852                union_ani_impl_target,
853            )
854            self.gen_union_into_ani_func(
855                union,
856                union_cpp_info,
857                union_ani_info,
858                union_ani_impl_target,
859            )
860
861    def gen_union_from_ani_func(
862        self,
863        union: UnionDecl,
864        union_cpp_info: UnionCppInfo,
865        union_ani_info: UnionANIInfo,
866        union_ani_impl_target: CHeaderWriter,
867    ):
868        with union_ani_impl_target.indented(
869            f"inline {union_cpp_info.as_owner} taihe::from_ani_t<{union_cpp_info.as_owner}>::operator()(ani_env* env, ani_ref ani_value) const {{",
870            f"}}",
871        ):
872            for parts in union_ani_info.sts_final_fields:
873                final = parts[-1]
874                static_tags = []
875                for part in parts:
876                    path_cpp_info = UnionCppInfo.get(self.am, part.parent_union)
877                    static_tags.append(
878                        f"::taihe::static_tag<{path_cpp_info.full_name}::tag_t::{part.name}>"
879                    )
880                static_tags_str = ", ".join(static_tags)
881                full_name = "_".join(part.name for part in parts)
882                is_field = f"ani_is_{full_name}"
883                final_ani_info = UnionFieldANIInfo.get(self.am, final)
884                if final_ani_info.field_ty == "null":
885                    union_ani_impl_target.writelns(
886                        f"ani_boolean {is_field};",
887                        f"env->Reference_IsNull(ani_value, &{is_field});",
888                    )
889                    with union_ani_impl_target.indented(
890                        f"if ({is_field}) {{",
891                        f"}}",
892                    ):
893                        union_ani_impl_target.writelns(
894                            f"return {union_cpp_info.full_name}({static_tags_str});",
895                        )
896                if final_ani_info.field_ty == "undefined":
897                    union_ani_impl_target.writelns(
898                        f"ani_boolean {is_field};",
899                        f"env->Reference_IsUndefined(ani_value, &{is_field});",
900                    )
901                    with union_ani_impl_target.indented(
902                        f"if ({is_field}) {{",
903                        f"}}",
904                    ):
905                        union_ani_impl_target.writelns(
906                            f"return {union_cpp_info.full_name}({static_tags_str});",
907                        )
908            for parts in union_ani_info.sts_final_fields:
909                final = parts[-1]
910                static_tags = []
911                for part in parts:
912                    path_cpp_info = UnionCppInfo.get(self.am, part.parent_union)
913                    static_tags.append(
914                        f"::taihe::static_tag<{path_cpp_info.full_name}::tag_t::{part.name}>"
915                    )
916                static_tags_str = ", ".join(static_tags)
917                full_name = "_".join(part.name for part in parts)
918                is_field = f"ani_is_{full_name}"
919                final_ani_info = UnionFieldANIInfo.get(self.am, final)
920                if isinstance(final_ty := final_ani_info.field_ty, Type):
921                    type_ani_info = TypeANIInfo.get(self.am, final_ty)
922                    union_ani_impl_target.writelns(
923                        f"ani_boolean {is_field};",
924                        f'env->Object_InstanceOf(static_cast<ani_object>(ani_value), TH_ANI_FIND_CLASS(env, "{type_ani_info.type_desc_boxed}"), &{is_field});',
925                    )
926                    with union_ani_impl_target.indented(
927                        f"if ({is_field}) {{",
928                        f"}}",
929                    ):
930                        cpp_result_spec = f"cpp_field_{full_name}"
931                        type_ani_info.from_ani_boxed(
932                            union_ani_impl_target,
933                            "env",
934                            "ani_value",
935                            cpp_result_spec,
936                        )
937                        union_ani_impl_target.writelns(
938                            f"return {union_cpp_info.full_name}({static_tags_str}, std::move({cpp_result_spec}));",
939                        )
940            union_ani_impl_target.writelns(
941                f"__builtin_unreachable();",
942            )
943
944    def gen_union_into_ani_func(
945        self,
946        union: UnionDecl,
947        union_cpp_info: UnionCppInfo,
948        union_ani_info: UnionANIInfo,
949        union_ani_impl_target: CHeaderWriter,
950    ):
951        with union_ani_impl_target.indented(
952            f"inline ani_ref taihe::into_ani_t<{union_cpp_info.as_owner}>::operator()(ani_env* env, {union_cpp_info.as_owner} cpp_value) const {{",
953            f"}}",
954        ):
955            union_ani_impl_target.writelns(
956                f"ani_ref ani_value;",
957            )
958            with union_ani_impl_target.indented(
959                f"switch (cpp_value.get_tag()) {{",
960                f"}}",
961                indent="",
962            ):
963                for field in union.fields:
964                    field_ani_info = UnionFieldANIInfo.get(self.am, field)
965                    with union_ani_impl_target.indented(
966                        f"case {union_cpp_info.full_name}::tag_t::{field.name}: {{",
967                        f"}}",
968                    ):
969                        match field_ani_info.field_ty:
970                            case "null":
971                                union_ani_impl_target.writelns(
972                                    f"env->GetNull(&ani_value);",
973                                )
974                            case "undefined":
975                                union_ani_impl_target.writelns(
976                                    f"env->GetUndefined(&ani_value);",
977                                )
978                            case field_ty if isinstance(field_ty, Type):
979                                ani_result_spec = f"ani_field_{field.name}"
980                                type_ani_info = TypeANIInfo.get(self.am, field_ty)
981                                type_ani_info.into_ani_boxed(
982                                    union_ani_impl_target,
983                                    "env",
984                                    f"cpp_value.get_{field.name}_ref()",
985                                    ani_result_spec,
986                                )
987                                union_ani_impl_target.writelns(
988                                    f"ani_value = {ani_result_spec};",
989                                )
990                        union_ani_impl_target.writelns(
991                            f"break;",
992                        )
993            union_ani_impl_target.writelns(
994                f"return ani_value;",
995            )