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 )