snapshot before regression test
This commit is contained in:
504
includes/llvmlite/__module.py
Normal file
504
includes/llvmlite/__module.py
Normal file
@@ -0,0 +1,504 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import memhub
|
||||
from linkedlist import GSList, GSListNode
|
||||
from .__types import LLVMType, TypePrint, Array, PrintStructDefinition, get_struct_name, Struct
|
||||
from .__function import Function, FunctionPrint, _ll_name_needs_quote, Param
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GlobalVariable: LLVM IR 全局变量
|
||||
#
|
||||
# 持有名称 + 类型 + 初始化值 + 常量标志 + 链接类型。
|
||||
# 继承 GSListNode[GlobalVariable] 获取强类型 Next。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class GlobalVariable(GSListNode[GlobalVariable]):
|
||||
Name: t.CChar | t.CPtr # 全局变量名(如 ".str" / "my_global")
|
||||
Ty: LLVMType | t.CPtr # 变量类型
|
||||
Initializer: t.CVoid | t.CPtr # 初始化值 Value*(None = 无初始化)
|
||||
IsConstant: t.CInt # 1=constant, 0=variable
|
||||
Linkage: t.CChar | t.CPtr # 链接类型("private"/"internal"/"external"/...)
|
||||
Section: t.CChar | t.CPtr # 段名(None = 默认)
|
||||
UnnamedAddr: t.CInt # 1=unnamed_addr, 2=local_unnamed_addr, 0=none
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NamedTypeNode: 命名结构体类型链表节点
|
||||
#
|
||||
# 持有 LLVMType* 指针(必须是命名 Struct 类型)。
|
||||
# 继承 GSListNode[NamedTypeNode] 获取强类型 Next。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class NamedTypeNode(GSListNode[NamedTypeNode]):
|
||||
Ty: LLVMType | t.CPtr # 命名结构体类型指针
|
||||
|
||||
|
||||
# ============================================================
|
||||
# LLVMModule: LLVM IR 模块容器
|
||||
#
|
||||
# 使用嵌入式 Head/Tail/Count 字段代替 GSList 指针,
|
||||
# 避免泛型 GSList 的 __sizeof__ 返回 0 和 vtable 偏移不一致问题。
|
||||
# LLVMModulePrint 输出完整 .ll 文件内容。
|
||||
# 注意: 类名必须为 LLVMModule 而非 Module,避免与 ast.Module 命名冲突
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class LLVMModule:
|
||||
Name: t.CChar | t.CPtr # 模块名
|
||||
FuncHead: Function | t.CPtr # 函数链表头
|
||||
FuncTail: Function | t.CPtr # 函数链表尾
|
||||
FuncCount: t.CSizeT # 函数计数
|
||||
GlobalHead: GlobalVariable | t.CPtr # 全局变量链表头
|
||||
GlobalTail: GlobalVariable | t.CPtr # 全局变量链表尾
|
||||
GlobalCount: t.CSizeT # 全局变量计数
|
||||
TargetTriple: t.CChar | t.CPtr # 目标三元组(如 "x86_64-pc-linux-gnu")
|
||||
DataLayout: t.CChar | t.CPtr # 数据布局(如 "e-m:e-p270:32:32-...")
|
||||
NamedTypeHead: NamedTypeNode | t.CPtr # 命名结构体类型链表头
|
||||
NamedTypeTail: NamedTypeNode | t.CPtr # 命名结构体类型链表尾
|
||||
NamedTypeCount: t.CSizeT # 命名结构体类型计数
|
||||
# 总计: 12 字段 * 8 = 96 字节(无 vtable)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 工厂函数
|
||||
# ============================================================
|
||||
def new_module(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> LLVMModule | t.CPtr:
|
||||
"""创建一个模块"""
|
||||
# 硬编码 96 字节:12 字段 * 8 字节(无 vtable,@t.NoVTable)
|
||||
ptr: LLVMModule | t.CPtr = pool.alloc(96)
|
||||
if ptr is None: return None
|
||||
string.memset(ptr, 0, 96)
|
||||
ptr.Name = name
|
||||
ptr.FuncHead = None
|
||||
ptr.FuncTail = None
|
||||
ptr.FuncCount = 0
|
||||
ptr.GlobalHead = None
|
||||
ptr.GlobalTail = None
|
||||
ptr.GlobalCount = 0
|
||||
ptr.TargetTriple = None
|
||||
ptr.DataLayout = None
|
||||
ptr.NamedTypeHead = None
|
||||
ptr.NamedTypeTail = None
|
||||
ptr.NamedTypeCount = 0
|
||||
return ptr
|
||||
|
||||
|
||||
# GlobalVariable 硬编码大小: Next(8) + Name(8) + Ty(8) + Initializer(8) + IsConstant(4) + Linkage(8) + Section(8) + UnnamedAddr(4) = 64 字节
|
||||
GV_SIZE: t.CDefine = 64
|
||||
|
||||
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) = 16 字节
|
||||
NAMED_TYPE_NODE_SIZE: t.CDefine = 16
|
||||
|
||||
def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: t.CChar | t.CPtr, ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
|
||||
"""创建一个全局变量"""
|
||||
ptr: GlobalVariable | t.CPtr = pool.alloc(GV_SIZE)
|
||||
if ptr is None: return None
|
||||
string.memset(ptr, 0, GV_SIZE)
|
||||
ptr.Name = name
|
||||
ptr.Ty = ty
|
||||
ptr.Initializer = None
|
||||
ptr.IsConstant = 0
|
||||
ptr.Linkage = "external"
|
||||
ptr.Section = None
|
||||
ptr.UnnamedAddr = 0
|
||||
return ptr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 链表操作(嵌入式 Head/Tail/Count,O(1) 追加)
|
||||
# ============================================================
|
||||
def module_add_function(mod: LLVMModule | t.CPtr, func: Function | t.CPtr):
|
||||
"""将函数追加到模块函数链表(O(1))"""
|
||||
if mod is None or func is None: return
|
||||
func.Next = None
|
||||
if mod.FuncHead is None:
|
||||
mod.FuncHead = func
|
||||
else:
|
||||
mod.FuncTail.Next = func
|
||||
mod.FuncTail = func
|
||||
mod.FuncCount += 1
|
||||
|
||||
|
||||
def module_add_global(mod: LLVMModule | t.CPtr, gv: GlobalVariable | t.CPtr):
|
||||
"""将全局变量追加到模块全局变量链表(O(1))"""
|
||||
if mod is None or gv is None: return
|
||||
gv.Next = None
|
||||
if mod.GlobalHead is None:
|
||||
mod.GlobalHead = gv
|
||||
else:
|
||||
mod.GlobalTail.Next = gv
|
||||
mod.GlobalTail = gv
|
||||
mod.GlobalCount += 1
|
||||
|
||||
|
||||
def module_set_target(mod: LLVMModule | t.CPtr, triple: t.CChar | t.CPtr):
|
||||
"""设置目标三元组"""
|
||||
if mod is None: return
|
||||
mod.TargetTriple = triple
|
||||
|
||||
|
||||
def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
|
||||
"""设置数据布局"""
|
||||
if mod is None: return
|
||||
mod.DataLayout = layout
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 命名结构体类型管理
|
||||
# ============================================================
|
||||
def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
||||
ty: LLVMType | t.CPtr):
|
||||
"""将命名结构体类型添加到模块(用于输出 %"name" = type { ... } 定义行)
|
||||
|
||||
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
|
||||
按 Name 去重,相同名称的类型只保留第一个。
|
||||
"""
|
||||
if mod is None or pool is None or ty is None:
|
||||
return
|
||||
name: t.CChar | t.CPtr = get_struct_name(ty)
|
||||
if name is None:
|
||||
return
|
||||
# 去重检查
|
||||
cur: NamedTypeNode | t.CPtr = mod.NamedTypeHead
|
||||
while cur is not None:
|
||||
if cur.Ty is not None:
|
||||
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
|
||||
if existing_name is not None:
|
||||
if string.strcmp(existing_name, name) == 0:
|
||||
return
|
||||
cur = cur.Next
|
||||
# 创建新节点并追加到链表尾部
|
||||
node: NamedTypeNode | t.CPtr = pool.alloc(NAMED_TYPE_NODE_SIZE)
|
||||
if node is None:
|
||||
return
|
||||
string.memset(node, 0, NAMED_TYPE_NODE_SIZE)
|
||||
node.Ty = ty
|
||||
node.Next = None
|
||||
if mod.NamedTypeHead is None:
|
||||
mod.NamedTypeHead = node
|
||||
else:
|
||||
mod.NamedTypeTail.Next = node
|
||||
mod.NamedTypeTail = node
|
||||
mod.NamedTypeCount += 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# module_ensure_opaque_for_type - 为类型中的跨模块结构体引用添加 opaque 声明
|
||||
#
|
||||
# 递归扫描 LLVMType 树,当遇到 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
|
||||
# 如果该名称未在模块中定义,则添加 opaque 声明(%"name" = type opaque)。
|
||||
# 这解决了跨模块结构体引用导致的 llc "use of undefined type" 错误。
|
||||
# ============================================================
|
||||
def _is_type_defined_in_module(mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr) -> int:
|
||||
"""检查模块中是否已定义指定名称的结构体类型,返回 1=已定义 / 0=未定义"""
|
||||
if mod is None or name is None:
|
||||
return 0
|
||||
cur: NamedTypeNode | t.CPtr = mod.NamedTypeHead
|
||||
while cur is not None:
|
||||
if cur.Ty is not None:
|
||||
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
|
||||
if existing_name is not None:
|
||||
if string.strcmp(existing_name, name) == 0:
|
||||
return 1
|
||||
cur = cur.Next
|
||||
return 0
|
||||
|
||||
|
||||
def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: LLVMModule | t.CPtr,
|
||||
ty: LLVMType | t.CPtr):
|
||||
"""递归扫描类型树,为跨模块结构体引用添加 opaque 声明"""
|
||||
if ty is None or mod is None or pool is None:
|
||||
return
|
||||
match ty:
|
||||
case LLVMType.Ptr(pointee):
|
||||
if pointee is not None:
|
||||
match pointee:
|
||||
case LLVMType.Struct(sfields, sfcount, sname):
|
||||
if sname is not None:
|
||||
# 检查是否为跨模块引用(名称包含 '.')
|
||||
if string.strchr(sname, 46) is not None:
|
||||
# 检查是否已在模块中定义
|
||||
if _is_type_defined_in_module(mod, sname) == 0:
|
||||
# 创建 opaque 类型并添加到模块
|
||||
opaque_ty: LLVMType | t.CPtr = Struct(pool, None, 0, sname)
|
||||
if opaque_ty is not None:
|
||||
module_add_named_type(mod, pool, opaque_ty)
|
||||
case _:
|
||||
_scan_type_for_cross_module_refs(pool, mod, pointee)
|
||||
case LLVMType.Array(elem_ty, acount):
|
||||
if elem_ty is not None:
|
||||
_scan_type_for_cross_module_refs(pool, mod, elem_ty)
|
||||
case _:
|
||||
pass
|
||||
|
||||
|
||||
def module_ensure_opaque_for_type(mod: LLVMModule | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
ty: LLVMType | t.CPtr):
|
||||
"""为类型中的跨模块结构体引用添加 opaque 声明
|
||||
|
||||
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
|
||||
如果该名称未在模块中定义,则添加 opaque 声明。
|
||||
"""
|
||||
_scan_type_for_cross_module_refs(pool, mod, ty)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局变量属性设置
|
||||
# ============================================================
|
||||
def global_set_constant(gv: GlobalVariable | t.CPtr, is_const: t.CInt):
|
||||
"""设置全局变量是否为常量"""
|
||||
if gv is None: return
|
||||
gv.IsConstant = is_const
|
||||
|
||||
|
||||
def global_set_linkage(gv: GlobalVariable | t.CPtr, linkage: t.CChar | t.CPtr):
|
||||
"""设置链接类型 (private/internal/external/... )"""
|
||||
if gv is None: return
|
||||
gv.Linkage = linkage
|
||||
|
||||
|
||||
def global_set_unnamed_addr(gv: GlobalVariable | t.CPtr, level: t.CInt):
|
||||
"""设置 unnamed_addr 属性 (0=none, 1=unnamed_addr, 2=local_unnamed_addr)"""
|
||||
if gv is None: return
|
||||
gv.UnnamedAddr = level
|
||||
|
||||
|
||||
def global_set_section(gv: GlobalVariable | t.CPtr, section: t.CChar | t.CPtr):
|
||||
"""设置段名"""
|
||||
if gv is None: return
|
||||
gv.Section = section
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 输出模式常量
|
||||
# ============================================================
|
||||
OUTPUT_FULL: t.CDefine = 0 # 完整 IR(stub + text)
|
||||
OUTPUT_STUB: t.CDefine = 1 # 仅声明(header + 类型定义 + declare + external global)
|
||||
OUTPUT_TEXT: t.CDefine = 2 # 仅代码(define + global 带初值)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# LLVMModulePrint: 将模块序列化为 .ll 文本
|
||||
#
|
||||
# mode: OUTPUT_FULL=完整, OUTPUT_STUB=仅声明, OUTPUT_TEXT=仅代码
|
||||
# ============================================================
|
||||
def LLVMModulePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
||||
mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
||||
mode: t.CInt):
|
||||
"""将模块 mod 序列化为 .ll 文本写入 buf"""
|
||||
if mod is None or buf is None or size == 0: return
|
||||
|
||||
# 头部注释(stub 和 full 模式输出,text 模式不输出)
|
||||
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
|
||||
_append_cstr(buf, size, "; ModuleID = '")
|
||||
if mod.Name is not None:
|
||||
_append_cstr(buf, size, mod.Name)
|
||||
_append_cstr(buf, size, "'\n")
|
||||
|
||||
# 目标三元组
|
||||
if mod.TargetTriple is not None:
|
||||
_append_cstr(buf, size, "target triple = \"")
|
||||
_append_cstr(buf, size, mod.TargetTriple)
|
||||
_append_cstr(buf, size, "\"\n")
|
||||
|
||||
# 数据布局
|
||||
if mod.DataLayout is not None:
|
||||
_append_cstr(buf, size, "target datalayout = \"")
|
||||
_append_cstr(buf, size, mod.DataLayout)
|
||||
_append_cstr(buf, size, "\"\n")
|
||||
|
||||
# 空行
|
||||
_append_cstr(buf, size, "\n")
|
||||
|
||||
# 命名结构体类型定义(stub 和 full 模式输出,text 模式不输出)
|
||||
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
|
||||
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
|
||||
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
|
||||
# 修复:alloc_buf 返回 viperio.Buf,但 Buf 类型未在 NamedTypeHead 中注册
|
||||
func_scan: Function | t.CPtr = mod.FuncHead
|
||||
while func_scan is not None:
|
||||
if func_scan.RetTy is not None:
|
||||
module_ensure_opaque_for_type(mod, pool, func_scan.RetTy)
|
||||
if func_scan.Params is not None:
|
||||
param_scan: Param | t.CPtr = func_scan.Params.Head
|
||||
while param_scan is not None:
|
||||
if param_scan.Ty is not None:
|
||||
module_ensure_opaque_for_type(mod, pool, param_scan.Ty)
|
||||
param_scan = param_scan.Next
|
||||
func_scan = func_scan.Next
|
||||
nt: NamedTypeNode | t.CPtr = mod.NamedTypeHead
|
||||
while nt is not None:
|
||||
if nt.Ty is not None:
|
||||
ty_buf: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if ty_buf is not None:
|
||||
ty_buf[0] = '\0'
|
||||
PrintStructDefinition(ty_buf, 256, nt.Ty, pool)
|
||||
_append_cstr(buf, size, ty_buf)
|
||||
_append_cstr(buf, size, "\n")
|
||||
nt = nt.Next
|
||||
|
||||
if mod.NamedTypeHead is not None:
|
||||
_append_cstr(buf, size, "\n")
|
||||
|
||||
# 全局变量
|
||||
gv: GlobalVariable | t.CPtr = mod.GlobalHead
|
||||
if mode == OUTPUT_STUB:
|
||||
# stub 模式:输出 external global(无初值)
|
||||
while gv is not None:
|
||||
_print_global_stub(buf, size, gv, pool)
|
||||
_append_cstr(buf, size, "\n")
|
||||
gv = gv.Next
|
||||
else:
|
||||
# full 和 text 模式:输出完整全局变量
|
||||
# text 模式跳过无初值的全局变量(纯声明)
|
||||
gv_idx: t.CInt = 0
|
||||
while gv is not None:
|
||||
if mode == OUTPUT_TEXT and gv.Initializer is None:
|
||||
gv = gv.Next
|
||||
gv_idx += 1
|
||||
continue
|
||||
_print_global(buf, size, gv, pool)
|
||||
_append_cstr(buf, size, "\n")
|
||||
gv = gv.Next
|
||||
gv_idx += 1
|
||||
|
||||
if mod.GlobalHead is not None and (mode == OUTPUT_FULL or mode == OUTPUT_STUB):
|
||||
_append_cstr(buf, size, "\n")
|
||||
elif mod.GlobalHead is not None and mode == OUTPUT_TEXT:
|
||||
# text 模式下如果输出了全局变量,也加空行
|
||||
had_global: t.CInt = 0
|
||||
gv2: GlobalVariable | t.CPtr = mod.GlobalHead
|
||||
while gv2 is not None:
|
||||
if gv2.Initializer is not None:
|
||||
had_global = 1
|
||||
break
|
||||
gv2 = gv2.Next
|
||||
if had_global != 0:
|
||||
_append_cstr(buf, size, "\n")
|
||||
|
||||
# 遍历函数
|
||||
func: Function | t.CPtr = mod.FuncHead
|
||||
func_idx: t.CInt = 0
|
||||
while func is not None:
|
||||
if mode == OUTPUT_STUB:
|
||||
# stub 模式:仅输出 declare(IsDeclared==1)
|
||||
if func.IsDeclared == 1:
|
||||
FunctionPrint(buf, size, func, pool)
|
||||
_append_cstr(buf, size, "\n")
|
||||
elif mode == OUTPUT_TEXT:
|
||||
# text 模式:仅输出 define(IsDeclared==0)
|
||||
if func.IsDeclared == 0:
|
||||
FunctionPrint(buf, size, func, pool)
|
||||
_append_cstr(buf, size, "\n")
|
||||
else:
|
||||
# full 模式:输出所有函数
|
||||
FunctionPrint(buf, size, func, pool)
|
||||
_append_cstr(buf, size, "\n")
|
||||
func = func.Next
|
||||
func_idx += 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局变量打印
|
||||
# ============================================================
|
||||
def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
||||
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
||||
"""打印单个全局变量: @<name> = [linkage] [unnamed_addr] [constant] <ty> <init>"""
|
||||
if gv is None: return
|
||||
|
||||
_append_cstr(buf, size, "@")
|
||||
if gv.Name is not None:
|
||||
if _ll_name_needs_quote(gv.Name) != 0:
|
||||
_append_cstr(buf, size, "\"")
|
||||
_append_cstr(buf, size, gv.Name)
|
||||
_append_cstr(buf, size, "\"")
|
||||
else:
|
||||
_append_cstr(buf, size, gv.Name)
|
||||
_append_cstr(buf, size, " = ")
|
||||
|
||||
# 链接类型(有初始值时不输出 external,因为 external + 初始值是非法 IR)
|
||||
if gv.Linkage is not None:
|
||||
if gv.Initializer is not None and string.strcmp(gv.Linkage, "external") == 0:
|
||||
pass
|
||||
else:
|
||||
_append_cstr(buf, size, gv.Linkage)
|
||||
_append_cstr(buf, size, " ")
|
||||
|
||||
# unnamed_addr
|
||||
if gv.UnnamedAddr == 1:
|
||||
_append_cstr(buf, size, "unnamed_addr ")
|
||||
elif gv.UnnamedAddr == 2:
|
||||
_append_cstr(buf, size, "local_unnamed_addr ")
|
||||
|
||||
# constant / global
|
||||
if gv.IsConstant == 1:
|
||||
_append_cstr(buf, size, "constant ")
|
||||
else:
|
||||
_append_cstr(buf, size, "global ")
|
||||
|
||||
# 类型
|
||||
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if ty_buf is not None:
|
||||
ty_buf[0] = '\0'
|
||||
TypePrint(ty_buf, 128, gv.Ty, pool)
|
||||
_append_cstr(buf, size, ty_buf)
|
||||
|
||||
# 初始化值
|
||||
if gv.Initializer is not None:
|
||||
_append_cstr(buf, size, " ")
|
||||
_append_cstr(buf, size, gv.Initializer)
|
||||
|
||||
# 段名
|
||||
if gv.Section is not None:
|
||||
_append_cstr(buf, size, ", section \"")
|
||||
_append_cstr(buf, size, gv.Section)
|
||||
_append_cstr(buf, size, "\"")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _print_global_stub - 打印全局变量的声明形式(external global,无初值)
|
||||
# ============================================================
|
||||
def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
||||
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
||||
"""打印全局变量声明: @<name> = external global <ty>"""
|
||||
if gv is None: return
|
||||
|
||||
_append_cstr(buf, size, "@")
|
||||
if gv.Name is not None:
|
||||
if _ll_name_needs_quote(gv.Name) != 0:
|
||||
_append_cstr(buf, size, "\"")
|
||||
_append_cstr(buf, size, gv.Name)
|
||||
_append_cstr(buf, size, "\"")
|
||||
else:
|
||||
_append_cstr(buf, size, gv.Name)
|
||||
_append_cstr(buf, size, " = external global ")
|
||||
|
||||
# 类型
|
||||
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if ty_buf is not None:
|
||||
ty_buf[0] = '\0'
|
||||
TypePrint(ty_buf, 128, gv.Ty, pool)
|
||||
_append_cstr(buf, size, ty_buf)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 内部辅助
|
||||
# ============================================================
|
||||
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
|
||||
"""将 C 字符串 src 追加到 dst 末尾"""
|
||||
if dst is None or src is None: return
|
||||
dlen: t.CSizeT = string.strlen(dst)
|
||||
slen: t.CSizeT = string.strlen(src)
|
||||
remain: t.CSizeT = dst_size - dlen
|
||||
if remain <= 0: return
|
||||
i: t.CSizeT = 0
|
||||
while i < slen and i + 1 < remain:
|
||||
dst[dlen + i] = src[i]
|
||||
i += 1
|
||||
dst[dlen + i] = '\0'
|
||||
Reference in New Issue
Block a user