988 lines
44 KiB
Python
988 lines
44 KiB
Python
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import viperlib
|
||
import stdio
|
||
import stdlib
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesBody as HandlesBody
|
||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||
import lib.core.Handles.HandlesImports as HandlesImports
|
||
|
||
|
||
# ============================================================
|
||
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
|
||
#
|
||
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
|
||
# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式
|
||
#
|
||
# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None
|
||
# ============================================================
|
||
def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr,
|
||
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||
imported_modules: str) -> t.CChar | t.CPtr:
|
||
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
|
||
if decorator_list is None:
|
||
return None
|
||
dn: t.CSizeT = decorator_list.__len__()
|
||
if dn == 0:
|
||
return None
|
||
|
||
attrs_buf: t.CChar | t.CPtr = pool.alloc(256)
|
||
if attrs_buf is None:
|
||
return None
|
||
attrs_buf[0] = '\0'
|
||
found_any: int = 0
|
||
|
||
for di in range(dn):
|
||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||
if deco is None or deco.kind() != ast.ASTKind.Call:
|
||
continue
|
||
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
|
||
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
|
||
continue
|
||
|
||
# 检测 c.Attribute
|
||
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
|
||
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
|
||
continue
|
||
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
|
||
continue
|
||
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
|
||
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
|
||
continue
|
||
if HandlesImports.is_module_imported(imported_modules, "c") == 0:
|
||
continue
|
||
|
||
# 遍历参数提取属性
|
||
if call_node.args is None:
|
||
continue
|
||
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
|
||
an: t.CSizeT = args_list.__len__()
|
||
for ai in range(an):
|
||
arg_node: ast.AST | t.CPtr = args_list.get(ai)
|
||
if arg_node is None:
|
||
continue
|
||
|
||
# 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx)
|
||
attr_name: str = _get_attr_name_from_node(arg_node)
|
||
if attr_name is None:
|
||
continue
|
||
|
||
# 映射到 LLVM 属性名并追加
|
||
if _append_llvm_attr(attrs_buf, attr_name) != 0:
|
||
found_any = 1
|
||
# 追加成功后,如果不是最后一个属性,添加空格分隔
|
||
# 在下一次追加前由 _append_str 处理
|
||
|
||
if found_any == 0:
|
||
return None
|
||
return attrs_buf
|
||
|
||
|
||
def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str:
|
||
"""从 AST 节点提取属性名
|
||
|
||
支持:
|
||
- Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline"
|
||
- Attribute: t.attr.packed -> "packed"
|
||
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
|
||
"""
|
||
if node is None:
|
||
return None
|
||
k: int = node.kind()
|
||
|
||
# Call 节点: t.attr.always_inline()
|
||
if k == ast.ASTKind.Call:
|
||
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
|
||
return None
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func)
|
||
return at.attr
|
||
|
||
# Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind
|
||
if k == ast.ASTKind.Attribute:
|
||
at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||
return at2.attr
|
||
|
||
return None
|
||
|
||
|
||
def _append_llvm_attr(attrs_buf: t.CChar | t.CPtr, attr_name: str) -> int:
|
||
"""将属性名映射到 LLVM 属性名并追加到缓冲区
|
||
|
||
返回 1 表示已追加,0 表示不支持该属性
|
||
"""
|
||
if attrs_buf is None or attr_name is None:
|
||
return 0
|
||
|
||
# 先确定映射的 LLVM 属性名
|
||
llvm_name: str = None
|
||
if string.strcmp(attr_name, "always_inline") == 0:
|
||
llvm_name = "alwaysinline"
|
||
elif string.strcmp(attr_name, "noinline") == 0:
|
||
llvm_name = "noinline"
|
||
elif string.strcmp(attr_name, "noreturn") == 0:
|
||
llvm_name = "noreturn"
|
||
elif string.strcmp(attr_name, "pure") == 0:
|
||
llvm_name = "readonly"
|
||
elif string.strcmp(attr_name, "const") == 0:
|
||
llvm_name = "readnone"
|
||
elif string.strcmp(attr_name, "nounwind") == 0:
|
||
llvm_name = "nounwind"
|
||
elif string.strcmp(attr_name, "noredzone") == 0:
|
||
llvm_name = "noredzone"
|
||
elif string.strcmp(attr_name, "willreturn") == 0:
|
||
llvm_name = "willreturn"
|
||
elif string.strcmp(attr_name, "mustprogress") == 0:
|
||
llvm_name = "mustprogress"
|
||
else:
|
||
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
|
||
return 0
|
||
|
||
# 支持的属性:如果缓冲区非空,先追加空格分隔
|
||
if attrs_buf[0] != '\0':
|
||
_append_str(attrs_buf, " ")
|
||
_append_str(attrs_buf, llvm_name)
|
||
return 1
|
||
|
||
|
||
def _append_str(buf: t.CChar | t.CPtr, s: str) -> None:
|
||
"""将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)"""
|
||
if buf is None or s is None:
|
||
return
|
||
cur_len: t.CSizeT = string.strlen(buf)
|
||
string.strcpy(buf + cur_len, s)
|
||
|
||
|
||
# ============================================================
|
||
# HandlesFunctions - 函数定义处理(trans 单参模式)
|
||
#
|
||
# 参考 Python 版 TransPyC FunctionHandle
|
||
#
|
||
# 函数有自己的局部作用域,通过 HandlesVar.enter_scope/exit_scope
|
||
# 管理嵌套作用域链,翻译函数体前进入函数作用域,翻译完退出。
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# _mangle_name - 为名称添加 SHA1 前缀
|
||
#
|
||
# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带
|
||
# SHA1 前缀(16 hex + '.'),则原样返回。
|
||
# ============================================================
|
||
def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str:
|
||
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
|
||
if trans is None or name is None:
|
||
return name
|
||
if trans.ModuleSha1 is None:
|
||
return name
|
||
name_len: t.CSizeT = string.strlen(name)
|
||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||
if name_len > 17:
|
||
is_sha1: int = 1
|
||
for i in range(16):
|
||
c: t.CChar = name[i]
|
||
if not (('0' <= c <= '9') or ('a' <= c <= 'f')):
|
||
is_sha1 = 0
|
||
break
|
||
if is_sha1 != 0 and name[16] == '.':
|
||
return name
|
||
sha1: str = trans.ModuleSha1
|
||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||
if mangled is None:
|
||
return name
|
||
string.strcpy(mangled, sha1)
|
||
mangled[sha1_len] = '.'
|
||
string.strcpy(mangled + sha1_len + 1, name)
|
||
return mangled
|
||
|
||
|
||
# ============================================================
|
||
# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀
|
||
#
|
||
# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling,
|
||
# 而非当前模块的 SHA1。
|
||
# ============================================================
|
||
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
|
||
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
|
||
if sha1 is None or name is None:
|
||
return name
|
||
name_len: t.CSizeT = string.strlen(name)
|
||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||
if name_len > 17:
|
||
is_sha1: int = 1
|
||
for i in range(16):
|
||
c2: t.CChar = name[i]
|
||
if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')):
|
||
is_sha1 = 0
|
||
break
|
||
if is_sha1 != 0 and name[16] == '.':
|
||
return name
|
||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||
if mangled is None:
|
||
return name
|
||
string.strcpy(mangled, sha1)
|
||
mangled[sha1_len] = '.'
|
||
string.strcpy(mangled + sha1_len + 1, name)
|
||
return mangled
|
||
|
||
|
||
# ============================================================
|
||
# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查)
|
||
#
|
||
# 规则:
|
||
# - main 函数不加前缀(程序入口点)
|
||
# - has_export 非 0 时不加前缀(t.CExport 导出函数)
|
||
# - 已带 SHA1 前缀的不再加
|
||
# - ModuleSha1 为 None 时不加前缀
|
||
# ============================================================
|
||
def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str,
|
||
has_export: int) -> str:
|
||
"""为函数名添加 SHA1 前缀(检查 main/export)"""
|
||
if trans is None or name is None:
|
||
return name
|
||
if has_export != 0:
|
||
return name
|
||
if string.strcmp(name, "main") == 0:
|
||
return name
|
||
return _mangle_name(trans, name)
|
||
|
||
|
||
# ============================================================
|
||
# forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明
|
||
#
|
||
# 解决同模块内前向引用问题:如 viperlib.py 中 sprintf(行15) 调用
|
||
# vsnprintf(行41),但 vsnprintf 定义在后面。
|
||
#
|
||
# 对每个顶层 FunctionDef:
|
||
# 1. 推断返回类型和参数类型
|
||
# 2. 计算 mangled name(含 SHA1 前缀)
|
||
# 3. 创建 declare(IsDeclared=1)
|
||
# 4. 添加参数
|
||
# 5. 注册到函数表
|
||
#
|
||
# 后续 translate_function_def 会通过 find_func_in_module 找到已有的 declare,
|
||
# 复用之(清除 IsDeclared,跳过参数创建,直接添加函数体)。
|
||
# ============================================================
|
||
def forward_declare_functions(trans: HT.Translator | t.CPtr,
|
||
tree: ast.AST | t.CPtr) -> int:
|
||
"""预扫描所有顶层 FunctionDef,创建前向声明"""
|
||
if trans is None or tree is None:
|
||
return 0
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
if pool is None or mod is None:
|
||
return 0
|
||
|
||
imported_modules: str = trans._imported_modules
|
||
from_imports: str = trans._from_imports
|
||
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||
if ch is None:
|
||
return 0
|
||
cn_count: t.CSizeT = ch.__len__()
|
||
|
||
for ci in range(cn_count):
|
||
child: ast.AST | t.CPtr = ch.get(ci)
|
||
if child is None:
|
||
continue
|
||
if child.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||
if fd is None or fd.name is None:
|
||
continue
|
||
|
||
# 推断返回类型
|
||
ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||
if fd.returns is not None:
|
||
ret_ty = HandlesType.resolve_annotation_type(
|
||
pool, fd.returns, imported_modules, from_imports)
|
||
if ret_ty is None and fd.returns is not None:
|
||
if HandlesType.has_decorator_marker(fd.returns, "State") != 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
if ret_ty is None:
|
||
ret_ty = i32_ty
|
||
|
||
# 检测 CExtern/State/CExport
|
||
has_extern: int = 0
|
||
has_state: int = 0
|
||
has_export: int = 0
|
||
if fd.returns is not None:
|
||
has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern")
|
||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||
is_extern_decl: int = 0
|
||
if has_extern != 0 or has_state != 0:
|
||
is_extern_decl = 1
|
||
|
||
# 计算 mangled name
|
||
if has_extern != 0 or has_state != 0 or has_export != 0 or fd.name == "main":
|
||
mangled_name: str = fd.name
|
||
else:
|
||
mangled_name = _mangle_func_name(trans, fd.name, 0)
|
||
|
||
# 如果函数已存在(如重复定义),跳过
|
||
existing: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name)
|
||
if existing is not None:
|
||
continue
|
||
|
||
# 创建 declare
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||
pool, mod, mangled_name, ret_ty)
|
||
if func is None:
|
||
continue
|
||
|
||
# 注册到函数表(用裸名 fd.name,不是 mangled_name)
|
||
max_funcs: int = 256
|
||
cur_count: int = trans._func_count
|
||
if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs) == 0:
|
||
trans._func_count = cur_count + 1
|
||
|
||
# 注册 CExport 函数到全局表
|
||
if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None:
|
||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||
|
||
# 添加参数
|
||
args_node: ast.Arguments | t.CPtr = fd.args
|
||
if args_node is not None:
|
||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||
an: t.CSizeT = alist.__len__()
|
||
for ai in range(an):
|
||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||
if arg is None or arg.arg is None:
|
||
continue
|
||
# t.CVoid 表示空参:跳过
|
||
if arg.annotation is not None:
|
||
if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0:
|
||
continue
|
||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg.annotation, imported_modules, from_imports)
|
||
if resolved is not None:
|
||
param_ty = resolved
|
||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname is not None:
|
||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||
llvmlite.add_param(pool, func, param_ty, pname)
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# 翻译函数定义 FunctionDef(name, args, body, ...)
|
||
#
|
||
# trans 单参模式:所有共享状态从 trans 获取
|
||
# 函数局部作用域通过 enter_scope/exit_scope 管理
|
||
# ============================================================
|
||
def translate_function_def(trans: HT.Translator | t.CPtr,
|
||
node: ast.AST | t.CPtr) -> int:
|
||
"""翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)"""
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||
if fd is None or fd.name is None:
|
||
return 0
|
||
|
||
stdio.printf("[FD] enter name=%s\n", fd.name)
|
||
stdio.fflush(0)
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
imported_modules: str = trans._imported_modules
|
||
from_imports: str = trans._from_imports
|
||
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
|
||
func_count: int = trans._func_count
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
|
||
# 推断返回类型:优先使用返回类型注解
|
||
stdio.printf("[FD] %s 推断返回类型前\n", fd.name)
|
||
stdio.fflush(0)
|
||
ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||
if fd.returns is not None:
|
||
ret_ty = HandlesType.resolve_annotation_type(
|
||
pool, fd.returns, imported_modules, from_imports)
|
||
|
||
# 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void
|
||
# 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32
|
||
if ret_ty is None and fd.returns is not None:
|
||
if HandlesType.has_decorator_marker(fd.returns, "State") != 0:
|
||
ret_ty = llvmlite.Void(pool)
|
||
|
||
# 如果仍然为 None,扫描 return 语句推断(至少返回 i32)
|
||
if ret_ty is None:
|
||
param_types_str: str = HandlesType.build_param_types_str(pool, fd.args)
|
||
ret_ty = HandlesType.infer_return_type(
|
||
pool, fd.children, param_types_str)
|
||
stdio.printf("[FD] %s 推断返回类型后=%d\n", fd.name, ret_ty)
|
||
stdio.fflush(0)
|
||
|
||
# 检测是否为外部声明函数(t.CExtern 或 t.State)
|
||
# 语义:t.CExtern 忽略 body 体,仅生成 declare(由链接器解析符号)
|
||
# t.State = t.CExtern + t.CExport(既是声明又是导出)
|
||
# t.CExport 导出函数不加 SHA1 前缀
|
||
# t.CExtern/t.State/t.CExport 都不加 SHA1 前缀,直接映射到 C 标准库函数名
|
||
is_extern_decl: int = 0
|
||
has_export: int = 0
|
||
has_extern: int = 0
|
||
has_state: int = 0
|
||
if fd.returns is not None:
|
||
has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern")
|
||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||
# t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass)
|
||
if has_extern != 0 or has_state != 0:
|
||
is_extern_decl = 1
|
||
stdio.printf("[FD] %s extern=%d state=%d export=%d is_extern_decl=%d\n",
|
||
fd.name, has_extern, has_state, has_export, is_extern_decl)
|
||
stdio.fflush(0)
|
||
|
||
# SHA1 命名空间:t.CExtern/t.State/t.CExport 不加前缀,直接用裸名
|
||
# (裸名映射到 C 标准库符号,带 sha1 前缀会导致 undefined reference)
|
||
# main 函数也不加前缀(程序入口点)
|
||
if has_extern != 0 or has_state != 0 or has_export != 0 or fd.name == "main":
|
||
mangled_name: str = fd.name
|
||
else:
|
||
mangled_name: str = _mangle_func_name(trans, fd.name, 0)
|
||
stdio.printf("[FD] %s mangled_name=%s\n", fd.name, mangled_name)
|
||
stdio.fflush(0)
|
||
|
||
# 注册 CExport 函数到全局表(供跨模块调用查表)
|
||
# t.CExport 函数定义用裸名(@strlen),跨模块调用需查表确认用裸名而非 @{sha1}.func
|
||
if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None:
|
||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||
|
||
if is_extern_decl != 0:
|
||
# 外部声明函数:生成 declare(仅声明,不定义)
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||
pool, mod, mangled_name, ret_ty)
|
||
if func is None:
|
||
stdio.printf("[FUNC] create_declare %s failed\n", fd.name)
|
||
return 0
|
||
|
||
# 注册到函数表
|
||
max_funcs_extern: int = 256
|
||
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern) == 0:
|
||
trans._func_count = func_count + 1
|
||
|
||
# 添加参数(支持类型注解)
|
||
args_node_extern: ast.Arguments | t.CPtr = fd.args
|
||
if args_node_extern is not None:
|
||
ags_e: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node_extern)
|
||
if ags_e.args is not None:
|
||
alist_e: list[ast.AST | t.CPtr] | t.CPtr = ags_e.args
|
||
an_e: t.CSizeT = alist_e.__len__()
|
||
for ai_e in range(an_e):
|
||
arg_e: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist_e.get(ai_e))
|
||
if arg_e is not None and arg_e.arg is not None:
|
||
# t.CVoid 表示空参:跳过,不添加到函数签名
|
||
if arg_e.annotation is not None:
|
||
if HandlesType._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0:
|
||
continue
|
||
param_ty_e: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg_e.annotation is not None:
|
||
resolved_e: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg_e.annotation, imported_modules, from_imports)
|
||
if resolved_e is not None:
|
||
param_ty_e = resolved_e
|
||
pname_e: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname_e is not None:
|
||
viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg)
|
||
llvmlite.add_param(pool, func, param_ty_e, pname_e)
|
||
|
||
# 提取 @c.Attribute 装饰器属性并设置到函数
|
||
func_attrs_e: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules)
|
||
if func_attrs_e is not None:
|
||
llvmlite.function_set_attrs(func, func_attrs_e)
|
||
|
||
return 0
|
||
|
||
# args_node 用于后续 alloca 创建,提前赋值
|
||
args_node: ast.Arguments | t.CPtr = fd.args
|
||
|
||
# 检查是否已有前向声明(由 forward_declare_functions 创建)
|
||
stdio.printf("[FD] %s find_func_in_module 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name)
|
||
stdio.printf("[FD] %s find_func_in_module 后=%d\n", fd.name, func)
|
||
stdio.fflush(0)
|
||
if func is not None and llvmlite.function_is_declared(func) != 0:
|
||
# 复用前向声明:清除 IsDeclared 标记,转为 define
|
||
func.IsDeclared = 0
|
||
# 装饰器属性设置(前向声明时未设置)
|
||
func_attrs_reuse: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules)
|
||
if func_attrs_reuse is not None:
|
||
llvmlite.function_set_attrs(func, func_attrs_reuse)
|
||
stdio.printf("[FD] %s 复用前向声明\n", fd.name)
|
||
stdio.fflush(0)
|
||
else:
|
||
# 创建新的 LLVM 函数(使用 SHA1 混淆名)
|
||
stdio.printf("[FD] %s create_function 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
func = llvmlite.create_function(pool, mod, mangled_name, ret_ty)
|
||
stdio.printf("[FD] %s create_function 后=%d\n", fd.name, func)
|
||
stdio.fflush(0)
|
||
if func is None:
|
||
stdio.printf("[FUNC] create_function %s failed\n", fd.name)
|
||
return 0
|
||
|
||
# 提取 @c.Attribute 装饰器属性并设置到函数
|
||
func_attrs: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules)
|
||
if func_attrs is not None:
|
||
llvmlite.function_set_attrs(func, func_attrs)
|
||
|
||
# 注册到函数表
|
||
max_funcs: int = 256
|
||
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs) == 0:
|
||
trans._func_count = func_count + 1
|
||
|
||
# 添加参数(支持类型注解)
|
||
if args_node is not None:
|
||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||
an: t.CSizeT = alist.__len__()
|
||
for ai in range(an):
|
||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||
if arg is not None and arg.arg is not None:
|
||
# t.CVoid 表示空参:跳过,不添加到函数签名
|
||
if arg.annotation is not None:
|
||
if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0:
|
||
continue
|
||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg.annotation, imported_modules, from_imports)
|
||
if resolved is not None:
|
||
param_ty = resolved
|
||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname is not None:
|
||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||
llvmlite.add_param(pool, func, param_ty, pname)
|
||
stdio.printf("[FD] %s 新函数创建完成\n", fd.name)
|
||
stdio.fflush(0)
|
||
|
||
# 创建 entry 块
|
||
stdio.printf("[FD] %s create_block 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||
stdio.printf("[FD] %s create_block 后=%d\n", fd.name, entry_blk)
|
||
stdio.fflush(0)
|
||
if entry_blk is None:
|
||
return 0
|
||
|
||
# 创建函数专属 builder
|
||
stdio.printf("[FD] %s new_builder 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||
stdio.printf("[FD] %s new_builder 后=%d\n", fd.name, func_builder)
|
||
stdio.fflush(0)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# 进入函数作用域(嵌套符号表)
|
||
stdio.printf("[FD] %s enter_scope 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
HandlesVar.enter_scope(trans.SymTab, HandlesVar.SCOPE_FUNCTION)
|
||
stdio.printf("[FD] %s enter_scope 后\n", fd.name)
|
||
stdio.fflush(0)
|
||
|
||
# 为参数创建 alloca
|
||
stdio.printf("[FD] %s 参数 alloca 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
if args_node is not None:
|
||
ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags2.args is not None:
|
||
alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args
|
||
an2: t.CSizeT = alist2.__len__()
|
||
for ai2 in range(an2):
|
||
arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2))
|
||
if arg2 is not None and arg2.arg is not None:
|
||
# t.CVoid 表示空参:跳过,不创建 alloca
|
||
if arg2.annotation is not None:
|
||
if HandlesType._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0:
|
||
continue
|
||
param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg2.annotation is not None:
|
||
resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg2.annotation, imported_modules, from_imports)
|
||
if resolved2 is not None:
|
||
param_ty2 = resolved2
|
||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2)
|
||
if alloca is not None:
|
||
HandlesVar.define_var(trans.SymTab, arg2.arg, alloca)
|
||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||
if arg2.annotation is not None:
|
||
cls_nm: str = HandlesType.extract_class_name_from_annotation(
|
||
arg2.annotation, imported_modules)
|
||
if cls_nm is not None:
|
||
HandlesVar.set_var_annot_class_name(
|
||
trans.SymTab, arg2.arg, cls_nm)
|
||
pname2: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname2 is not None:
|
||
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
|
||
param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||
pool, param_ty2, pname2)
|
||
llvmlite.build_store(func_builder, param_val, alloca)
|
||
stdio.printf("[FD] %s 参数 alloca 后\n", fd.name)
|
||
stdio.fflush(0)
|
||
|
||
# 保存模块级作用域状态(仅非变量表相关)
|
||
old_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||
old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||
old_global_count: int = trans._global_name_count
|
||
old_nonlocal_count: int = trans._nonlocal_name_count
|
||
old_env_count: int = trans._closure_env_count
|
||
|
||
trans._cur_func = func
|
||
trans._cur_builder = func_builder
|
||
# 清空 global/nonlocal 名称集合(新函数作用域)
|
||
HT.clear_scope_names(trans)
|
||
|
||
# 预扫描函数体:为局部变量提前创建 alloca
|
||
stdio.printf("[FD] %s pre_scan_allocas 前\n", fd.name)
|
||
stdio.fflush(0)
|
||
body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||
if body is not None:
|
||
bn: t.CSizeT = body.__len__()
|
||
for bi in range(bn):
|
||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||
if stmt is not None:
|
||
HandlesBody.pre_scan_allocas(trans, stmt)
|
||
stdio.printf("[FD] %s pre_scan_allocas 后\n", fd.name)
|
||
stdio.fflush(0)
|
||
|
||
# 翻译函数体
|
||
stdio.printf("[FD] %s translate_stmt 前 body_len=%d\n", fd.name,
|
||
body.__len__() if body is not None else 0)
|
||
stdio.fflush(0)
|
||
if body is not None:
|
||
bn2: t.CSizeT = body.__len__()
|
||
for bi2 in range(bn2):
|
||
stmt2: ast.AST | t.CPtr = body.get(bi2)
|
||
if stmt2 is not None:
|
||
stdio.printf("[FD] %s translate_stmt bi2=%d kd=%d 前\n", fd.name, bi2, stmt2.kind())
|
||
stdio.fflush(0)
|
||
HandlesBody.translate_stmt(trans, stmt2)
|
||
stdio.printf("[FD] %s translate_stmt bi2=%d 后\n", fd.name, bi2)
|
||
stdio.fflush(0)
|
||
|
||
# 如果函数体最后一条语句不是 Return,添加隐式 ret
|
||
last_is_return: int = 0
|
||
if body is not None:
|
||
bn3: t.CSizeT = body.__len__()
|
||
if bn3 > 0:
|
||
last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
|
||
last_is_return = 1
|
||
if last_is_return == 0:
|
||
zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||
llvmlite.build_ret(func_builder, zero_val)
|
||
|
||
# 恢复模块级作用域(退出函数作用域)
|
||
HandlesVar.exit_scope(trans.SymTab)
|
||
trans._cur_func = old_func
|
||
trans._cur_builder = old_builder
|
||
trans._global_name_count = old_global_count
|
||
trans._nonlocal_name_count = old_nonlocal_count
|
||
trans._closure_env_count = old_env_count
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# translate_nested_function_def - 嵌套函数提升 + 闭包创建
|
||
#
|
||
# 将嵌套函数提升为顶层函数 @__closure_{name}(i8* %env) -> i32,
|
||
# 在父函数中创建闭包对象 {i8* fn_ptr, i8* env_ptr} 并存储到
|
||
# 以函数名命名的局部变量中。
|
||
#
|
||
# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节, malloc 分配)
|
||
# Env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量 8 字节)
|
||
# ============================================================
|
||
def translate_nested_function_def(trans: HT.Translator | t.CPtr,
|
||
node: ast.AST | t.CPtr) -> int:
|
||
"""翻译嵌套函数定义:提升为顶层函数 + 创建闭包"""
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||
if fd is None or fd.name is None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||
func_name: str = fd.name
|
||
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||
|
||
# 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突)
|
||
promoted_name: t.CChar | t.CPtr = pool.alloc(64)
|
||
if promoted_name is not None:
|
||
viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name)
|
||
mangled_promoted: str = _mangle_name(trans, promoted_name)
|
||
|
||
# 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env)
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||
pool, mod, mangled_promoted, i32_ty)
|
||
if func is None:
|
||
return 0
|
||
llvmlite.add_param(pool, func, i8_ptr_ty, "%env")
|
||
|
||
# 3. 创建 entry 块 + builder
|
||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||
if entry_blk is None:
|
||
return 0
|
||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||
if func_builder is None:
|
||
return 0
|
||
llvmlite.position_at_end(func_builder, entry_blk)
|
||
|
||
# 4. 进入嵌套函数作用域(嵌套符号表)
|
||
HandlesVar.enter_scope(trans.SymTab, HandlesVar.SCOPE_FUNCTION)
|
||
|
||
# 5. 创建 _env_ptr alloca 并存储 %env 参数
|
||
env_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, i8_ptr_ty)
|
||
if env_alloca is not None:
|
||
HandlesVar.define_var(trans.SymTab, "_env_ptr", env_alloca)
|
||
env_param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "%env")
|
||
llvmlite.build_store(func_builder, env_param_val, env_alloca)
|
||
|
||
# 6. 保存父函数作用域状态(仅非变量表相关)
|
||
old_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||
old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||
old_func_name: str = trans._cur_func_name
|
||
old_global_count: int = trans._global_name_count
|
||
old_nonlocal_count: int = trans._nonlocal_name_count
|
||
old_env_count: int = trans._closure_env_count
|
||
|
||
# 7. 切换到嵌套函数作用域 + 清空 scope names
|
||
trans._cur_func = func
|
||
trans._cur_builder = func_builder
|
||
trans._cur_func_name = func_name
|
||
HT.clear_scope_names(trans)
|
||
|
||
# 8. 预扫描函数体:为局部变量提前创建 alloca
|
||
body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||
if body is not None:
|
||
bn: t.CSizeT = body.__len__()
|
||
for bi in range(bn):
|
||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||
if stmt is not None:
|
||
HandlesBody.pre_scan_allocas(trans, stmt)
|
||
|
||
# 9. 翻译函数体(Nonlocal 语句会填充 _nonlocal_names)
|
||
if body is not None:
|
||
bn2: t.CSizeT = body.__len__()
|
||
for bi2 in range(bn2):
|
||
stmt2: ast.AST | t.CPtr = body.get(bi2)
|
||
if stmt2 is not None:
|
||
HandlesBody.translate_stmt(trans, stmt2)
|
||
|
||
# 10. 隐式 ret
|
||
last_is_return: int = 0
|
||
if body is not None:
|
||
bn3: t.CSizeT = body.__len__()
|
||
if bn3 > 0:
|
||
last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
|
||
last_is_return = 1
|
||
if last_is_return == 0:
|
||
zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||
llvmlite.build_ret(func_builder, zero_val)
|
||
|
||
# 11. 保存嵌套函数的 nonlocal 信息
|
||
nested_nonlocal_count: int = trans._nonlocal_name_count
|
||
|
||
# 12. 退出嵌套函数作用域,回到父函数作用域(保留 _nonlocal_names 用于 env 创建)
|
||
HandlesVar.exit_scope(trans.SymTab)
|
||
trans._cur_func = old_func
|
||
trans._cur_builder = old_builder
|
||
# NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值
|
||
|
||
# 13. 在父函数中创建闭包对象
|
||
parent_builder: llvmlite.IRBuilder | t.CPtr = old_builder
|
||
if parent_builder is None:
|
||
# 无 builder(模块级嵌套函数?)→ 无法创建闭包,仅恢复状态
|
||
trans._cur_func_name = old_func_name
|
||
trans._global_name_count = old_global_count
|
||
trans._nonlocal_name_count = old_nonlocal_count
|
||
trans._closure_env_count = old_env_count
|
||
return 0
|
||
|
||
# 13a. 创建 env: malloc(4 * nested_nonlocal_count) — env 直接存储 i32 值
|
||
env_ptr: llvmlite.Value | t.CPtr = None
|
||
if nested_nonlocal_count > 0:
|
||
env_size: t.CInt64T = nested_nonlocal_count * 4
|
||
env_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, env_size)
|
||
if env_size_val is not None:
|
||
env_size_val.Next = None
|
||
env_ptr = llvmlite.build_call(
|
||
parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
|
||
|
||
# 为每个 nonlocal 变量存储值到 env
|
||
if env_ptr is not None:
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty)
|
||
for ni in range(nested_nonlocal_count):
|
||
# 从 _nonlocal_names 缓冲区读取名称
|
||
name_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + ni * 8
|
||
nl_slot: str | t.CPtr = (t.CVoid | t.CPtr)(name_addr)
|
||
nl_name: str = nl_slot[0]
|
||
if nl_name is not None:
|
||
# 在父函数作用域中查找(Current 已回到父作用域)
|
||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||
trans.SymTab, nl_name)
|
||
if var_alloca is not None:
|
||
# 加载变量值
|
||
var_ty: llvmlite.LLVMType | t.CPtr = None
|
||
if var_alloca.Ty is not None:
|
||
var_ty = var_alloca.Ty.Pointee
|
||
if var_ty is None:
|
||
var_ty = i32_ty
|
||
var_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||
parent_builder, var_ty, var_alloca)
|
||
if var_val is not None:
|
||
# GEP to env[ni*4]
|
||
offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, ni * 4)
|
||
slot: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
parent_builder, i8_ty, env_ptr, offset_val)
|
||
if slot is not None:
|
||
# bitcast to i32* and store value
|
||
slot_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
parent_builder, slot, i32_ptr_ty)
|
||
if slot_typed is not None:
|
||
# 类型转换(确保 var_val 是 i32)
|
||
coerced_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
|
||
parent_builder, var_val, i32_ty)
|
||
if coerced_val is not None:
|
||
llvmlite.build_store(parent_builder, coerced_val, slot_typed)
|
||
|
||
# 13b. 创建闭包结构: malloc(16)
|
||
closure_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 16)
|
||
if closure_size_val is not None:
|
||
closure_size_val.Next = None
|
||
closure_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||
parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
|
||
if closure_ptr is None:
|
||
# malloc 失败,恢复状态
|
||
trans._cur_func_name = old_func_name
|
||
trans._global_name_count = old_global_count
|
||
trans._nonlocal_name_count = old_nonlocal_count
|
||
trans._closure_env_count = old_env_count
|
||
return 0
|
||
|
||
# 13c. 存储 fn_ptr 到 offset 0
|
||
# 创建函数指针类型 i32(i8*)*
|
||
fn_param_node: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
|
||
fn_func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, i32_ty, fn_param_node, 1)
|
||
fn_func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, fn_func_ty)
|
||
|
||
# 创建函数引用 Value(类型为 i32(i8*)*,使用 SHA1 混淆名)
|
||
fn_ptr_name: t.CChar | t.CPtr = pool.alloc(64)
|
||
if fn_ptr_name is not None:
|
||
# SHA1 前缀名含 '.' 需要加引号(如 @"sha1.__closure_func")
|
||
if string.strchr(mangled_promoted, '.') is not None:
|
||
viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted)
|
||
else:
|
||
viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted)
|
||
fn_ptr_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
|
||
|
||
# bitcast 函数指针到 i8*(闭包存储 i8* 类型)
|
||
fn_as_i8ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
parent_builder, fn_ptr_val, i8_ptr_ty)
|
||
fn_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
|
||
if fn_slot is not None and fn_as_i8ptr is not None:
|
||
llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot)
|
||
|
||
# 13d. 存储 env_ptr 到 offset 8
|
||
eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 8)
|
||
env_slot_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||
parent_builder, i8_ty, closure_ptr, eight_val)
|
||
if env_slot_addr is not None:
|
||
env_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||
parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
|
||
if env_slot is not None:
|
||
if env_ptr is not None:
|
||
llvmlite.build_store(parent_builder, env_ptr, env_slot)
|
||
else:
|
||
# 无 nonlocal 变量,存储 null
|
||
null_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "null")
|
||
llvmlite.build_store(parent_builder, null_val, env_slot)
|
||
|
||
# 13e. 将闭包指针存储到父函数的局部变量 {func_name}
|
||
closure_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(parent_builder, i8_ptr_ty)
|
||
if closure_alloca is not None:
|
||
llvmlite.build_store(parent_builder, closure_ptr, closure_alloca)
|
||
HandlesVar.define_var(trans.SymTab, func_name, closure_alloca)
|
||
|
||
# 14. 恢复 scope names
|
||
trans._cur_func_name = old_func_name
|
||
trans._global_name_count = old_global_count
|
||
trans._nonlocal_name_count = old_nonlocal_count
|
||
trans._closure_env_count = old_env_count
|
||
|
||
return 1
|
||
|
||
|
||
# ============================================================
|
||
# 创建 LLVM 函数(简单版本,仅声明)
|
||
# ============================================================
|
||
def create_function(pool: memhub.MemBuddy | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
name: str,
|
||
args_node: ast.AST | t.CPtr,
|
||
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
|
||
"""创建 LLVM 函数并添加参数"""
|
||
if name is None or mod is None:
|
||
return None
|
||
|
||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty)
|
||
if func is None:
|
||
return None
|
||
|
||
if args_node is not None:
|
||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||
if ags.args is not None:
|
||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||
an: t.CSizeT = alist.__len__()
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
for ai in range(an):
|
||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||
if arg is not None and arg.arg is not None:
|
||
# t.CVoid 表示空参:跳过
|
||
if arg.annotation is not None:
|
||
if arg.annotation.kind() == ast.ASTKind.Attribute:
|
||
at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
|
||
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
|
||
continue
|
||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
if arg.annotation is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, arg.annotation, None, None)
|
||
if resolved is not None:
|
||
param_ty = resolved
|
||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||
if pname is not None:
|
||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||
llvmlite.add_param(pool, func, param_ty, pname)
|
||
|
||
return func
|