feat(types): rowptr/REnum 迁移工作区快照 + GSList/PrintModule 临时 DBGCHAIN 护栏

把此前未提交的 rowptr 迁移整体入库(42 文件,含 ast/llvmlite/hashlib/json/zlib 等签名 rowptr 化)。临时诊断(用后移除):linkedlist.vp GSList[T].append 链完整性四检、__module.vp PrintModule Function.Params/param 指针野值护栏([DBGCHAIN] 前缀 + fflush + exit)。
This commit is contained in:
TermiNexus committed 2026-09-05 14:51:40 +08:00
1 parent e2dd0fb18f
commit 2992674783
42 files changed
+3506 -2941

No files matched your search

+6 -12
View File
@@ -18,15 +18,11 @@ def pause():
def inb(port: t.CUInt16T) -> t.CUInt8T:
value: t.CUInt32T
# 显式 mov 到输出寄存器:EAX 作临时(CLOBBER_RAX 声明),避免
# AsmOut 分配到非 RAX 时读到 asm 前残留(加 CLOBBER_RAX 后 LLVM
# 不再把 value 绑到 RAX,需 asm 内显式存值)。
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
in al, dx
movzx eax, al
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
movzx eax, al""",
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
op =[t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
op =[t.ASM_DESCR.CLOBBER_RDX])
return t.CUInt8T(value)
def outb(port: t.CUInt16T, value: t.CUInt8T):
@@ -40,10 +36,9 @@ def inw(port: t.CUInt16T) -> t.CUInt16T:
value: t.CUInt32T
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
in ax, dx
movzx eax, ax
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
movzx eax, ax""",
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
op =[t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
op =[t.ASM_DESCR.CLOBBER_RDX])
return t.CUInt16T(value)
def outw(port: t.CUInt16T, value: t.CUInt16T):
@@ -55,10 +50,9 @@ def outw(port: t.CUInt16T, value: t.CUInt16T):
def inl(port: t.CUInt16T) -> t.CUInt32T:
value: t.CUInt32T
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
in eax, dx
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
in eax, dx""",
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
op =[t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
op =[t.ASM_DESCR.CLOBBER_RDX])
return value
def outl(port: t.CUInt16T, value: t.CUInt32T):
+12 -14
View File
@@ -37,9 +37,7 @@ from .exprs import (
Constant, NamedExpr, Attribute, Subscript, Starred, Name,
List, Tuple, Slice,
Call, Compare, OpNode,
# 字段访问辅助函数(TPV TypeGen 以 ast.<helper> 跨模块调用;未 re-export
# 时跨模块函数返回类型解析在 ast 包 text.ll 找不到定义(定义在 ast.exprs)
# → fail-fast "返回类型无法精确获取",如 attribute_get_attr/attribute_get_value)
name_get_id, constant_get_str_val,
binop_get_left, binop_get_right,
attribute_get_attr, attribute_get_value,
@@ -65,14 +63,14 @@ from .parser import get_parse_err_line, get_parse_err_col, get_parse_err_msg
# Global Memory Pool Pointer (follows project rules: declare _mbuddy)
# User initializes in main: ast._mbuddy = memhub.MemBuddy(arena, size)
# ============================================================
_mbuddy: memhub.MemBuddy | t.CPtr
_mbuddy: rowptr[memhub.MemBuddy]
# ============================================================
# Common API: parse
# ============================================================
def parse(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr:
def parse(src: str, pool: rowptr[memhub.MemManager]) -> rowptr[AST]:
"""Parse Python source code, return the AST Module node.
Parameters:
@@ -85,18 +83,18 @@ def parse(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr:
if src is None or pool is None:
return None
_init_tables(pool)
lx: Lexer | t.CPtr = new_lexer(pool)
lx: rowptr[Lexer] = new_lexer(pool)
if lx is None:
return None
_lexer_init(lx, src, pool)
tokens: Token | t.CPtr = tokenize(lx)
tokens: rowptr[Token] = tokenize(lx)
if tokens is None:
return None
tree: AST | t.CPtr = parse_tokens(pool, tokens)
tree: rowptr[AST] = parse_tokens(pool, tokens)
return tree
def parse_expression(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr:
def parse_expression(src: str, pool: rowptr[memhub.MemManager]) -> rowptr[Expression]:
"""Parse a single expression, return the Expression node.
Parameters:
@@ -104,18 +102,18 @@ def parse_expression(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr
pool: memhub.MemManager instance, to allocate AST nodes
Returns:
Expression node, or None
Expression node (包装节点,body 字段为实际表达式), or None
"""
if src is None or pool is None:
return None
_init_tables(pool)
lx: Lexer | t.CPtr = new_lexer(pool)
lx: rowptr[Lexer] = new_lexer(pool)
if lx is None: return None
_lexer_init(lx, src, pool)
tokens: Token | t.CPtr = tokenize(lx)
tokens: rowptr[Token] = tokenize(lx)
if tokens is None: return None
ps: Parser | t.CPtr = new_parser(pool)
ps: rowptr[Parser] = new_parser(pool)
if ps is None: return None
_parser_init(ps, tokens, pool)
body: AST | t.CPtr = _parse_test(ps)
body: rowptr[AST] = _parse_test(ps)
return Expression(pool, body)
+63 -63
View File
@@ -15,23 +15,23 @@ from .base import (
class ExceptHandler(AST):
"""ExceptHandler(type: AST, name: str)"""
type: AST | t.CPtr
type: rowptr[AST]
name: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
type: AST | t.CPtr, name: str):
ptr: ExceptHandler | t.CPtr = pool.alloc(ExceptHandler.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
type: rowptr[AST], name: str):
ptr: rowptr[ExceptHandler] = pool.alloc(ExceptHandler.__sizeof__())
if ptr:
string.memset(ptr, 0, ExceptHandler.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
type: AST | t.CPtr, name: str):
def __init__(self, pool: rowptr[memhub.MemManager],
type: rowptr[AST], name: str):
_init_ast(self, pool, 0, 0)
self.type = type
self.name = _copy_str(pool, name)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.ExceptHandler
def type_name(self) -> str:
@@ -59,27 +59,27 @@ class ExceptHandler(AST):
class Arguments(AST):
"""Arguments(args: list[AST | CPtr], vararg: AST, kwarg: AST,
defaults: list[AST | CPtr], kw_defaults: list[AST | CPtr])"""
args: list[AST | t.CPtr] | t.CPtr
vararg: AST | t.CPtr
kwarg: AST | t.CPtr
defaults: list[AST | t.CPtr] | t.CPtr
kw_defaults: list[AST | t.CPtr] | t.CPtr
args: rowptr[list[rowptr[AST]]]
vararg: rowptr[AST]
kwarg: rowptr[AST]
defaults: rowptr[list[rowptr[AST]]]
kw_defaults: rowptr[list[rowptr[AST]]]
def __new__(self, pool: memhub.MemManager | t.CPtr,
args: list[AST | t.CPtr] | t.CPtr,
vararg: AST | t.CPtr, kwarg: AST | t.CPtr,
defaults: list[AST | t.CPtr] | t.CPtr,
kw_defaults: list[AST | t.CPtr] | t.CPtr):
ptr: Arguments | t.CPtr = pool.alloc(Arguments.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
args: rowptr[list[rowptr[AST]]],
vararg: rowptr[AST], kwarg: rowptr[AST],
defaults: rowptr[list[rowptr[AST]]],
kw_defaults: rowptr[list[rowptr[AST]]]):
ptr: rowptr[Arguments] = pool.alloc(Arguments.__sizeof__())
if ptr:
string.memset(ptr, 0, Arguments.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
args: list[AST | t.CPtr] | t.CPtr,
vararg: AST | t.CPtr, kwarg: AST | t.CPtr,
defaults: list[AST | t.CPtr] | t.CPtr,
kw_defaults: list[AST | t.CPtr] | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
args: rowptr[list[rowptr[AST]]],
vararg: rowptr[AST], kwarg: rowptr[AST],
defaults: rowptr[list[rowptr[AST]]],
kw_defaults: rowptr[list[rowptr[AST]]]):
_init_ast(self, pool, 0, 0)
self.args = args
self.vararg = vararg
@@ -90,7 +90,7 @@ class Arguments(AST):
_set_parent_list(defaults, self)
_set_parent_list(kw_defaults, self)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.Arguments
def type_name(self) -> str:
@@ -125,22 +125,22 @@ class Arguments(AST):
class Arg(AST):
"""Arg(arg: str, annotation: AST)"""
arg: str
annotation: AST | t.CPtr
annotation: rowptr[AST]
def __new__(self, pool: memhub.MemManager | t.CPtr,
arg: str, annotation: AST | t.CPtr):
ptr: Arg | t.CPtr = pool.alloc(Arg.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
arg: str, annotation: rowptr[AST]):
ptr: rowptr[Arg] = pool.alloc(Arg.__sizeof__())
if ptr:
string.memset(ptr, 0, Arg.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
arg: str, annotation: AST | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
arg: str, annotation: rowptr[AST]):
_init_ast(self, pool, 0, 0)
self.arg = _copy_str(pool, arg)
self.annotation = annotation
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.Arg
def type_name(self) -> str:
@@ -166,22 +166,22 @@ class Arg(AST):
class Keyword(AST):
"""Keyword(arg: str, value: AST)"""
arg: str
value: AST | t.CPtr
value: rowptr[AST]
def __new__(self, pool: memhub.MemManager | t.CPtr,
arg: str, value: AST | t.CPtr):
ptr: Keyword | t.CPtr = pool.alloc(Keyword.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
arg: str, value: rowptr[AST]):
ptr: rowptr[Keyword] = pool.alloc(Keyword.__sizeof__())
if ptr:
string.memset(ptr, 0, Keyword.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
arg: str, value: AST | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
arg: str, value: rowptr[AST]):
_init_ast(self, pool, 0, 0)
self.arg = _copy_str(pool, arg)
self.value = value
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.Keyword
def type_name(self) -> str:
@@ -209,20 +209,20 @@ class Alias(AST):
name: str
asname: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
def __new__(self, pool: rowptr[memhub.MemManager],
name: str, asname: str):
ptr: Alias | t.CPtr = pool.alloc(Alias.__sizeof__())
ptr: rowptr[Alias] = pool.alloc(Alias.__sizeof__())
if ptr:
string.memset(ptr, 0, Alias.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
def __init__(self, pool: rowptr[memhub.MemManager],
name: str, asname: str):
_init_ast(self, pool, 0, 0)
self.name = _copy_str(pool, name)
self.asname = _copy_str(pool, asname)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.Alias
def type_name(self) -> str:
@@ -244,23 +244,23 @@ class Alias(AST):
class WithItem(AST):
"""WithItem(context_expr: AST, optional_vars: AST)"""
context_expr: AST | t.CPtr
optional_vars: AST | t.CPtr
context_expr: rowptr[AST]
optional_vars: rowptr[AST]
def __new__(self, pool: memhub.MemManager | t.CPtr,
context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr):
ptr: WithItem | t.CPtr = pool.alloc(WithItem.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
context_expr: rowptr[AST], optional_vars: rowptr[AST]):
ptr: rowptr[WithItem] = pool.alloc(WithItem.__sizeof__())
if ptr:
string.memset(ptr, 0, WithItem.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
context_expr: rowptr[AST], optional_vars: rowptr[AST]):
_init_ast(self, pool, 0, 0)
self.context_expr = context_expr
self.optional_vars = optional_vars
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.WithItem
def type_name(self) -> str:
@@ -288,22 +288,22 @@ class WithItem(AST):
class Comprehension(AST):
"""Comprehension(target: AST, iter: AST, ifs: list[AST | CPtr], is_async: CInt)"""
target: AST | t.CPtr
iter: AST | t.CPtr
ifs: list[AST | t.CPtr] | t.CPtr
is_async: t.CInt
target: rowptr[AST]
iter: rowptr[AST]
ifs: rowptr[list[rowptr[AST]]]
is_async: int
def __new__(self, pool: memhub.MemManager | t.CPtr,
target: AST | t.CPtr, iter: AST | t.CPtr,
ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt):
ptr: Comprehension | t.CPtr = pool.alloc(Comprehension.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
target: rowptr[AST], iter: rowptr[AST],
ifs: rowptr[list[rowptr[AST]]], is_async: int):
ptr: rowptr[Comprehension] = pool.alloc(Comprehension.__sizeof__())
if ptr:
string.memset(ptr, 0, Comprehension.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
target: AST | t.CPtr, iter: AST | t.CPtr,
ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt):
def __init__(self, pool: rowptr[memhub.MemManager],
target: rowptr[AST], iter: rowptr[AST],
ifs: rowptr[list[rowptr[AST]]], is_async: int):
_init_ast(self, pool, 0, 0)
self.target = target
self.iter = iter
@@ -311,7 +311,7 @@ class Comprehension(AST):
self.is_async = is_async
_set_parent_list(ifs, self)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.Comprehension
def type_name(self) -> str:
@@ -332,6 +332,6 @@ class Comprehension(AST):
pos = _emit(buf, size, pos, ", ifs=")
pos = _dump_list(self.ifs, buf, size, pos)
pos = _emit(buf, size, pos, ", is_async=")
pos = _emit_int(buf, size, pos, t.CInt64T(self.is_async))
pos = _emit_int(buf, size, pos, int64(self.is_async))
pos = _emit(buf, size, pos, ")")
return pos
+46 -41
View File
@@ -138,6 +138,8 @@ class OpKind(t.CEnum):
UAdd: t.State
USub: t.State
Invert: t.State
Deref: t.State
AddrOf: t.State
# None
NoneOp: t.State
@@ -156,6 +158,7 @@ FLAG_SIMPLE: t.CDefine = 2
FLAG_HAS_STAR: t.CDefine = 4
FLAG_IS_EXTERN: t.CDefine = 8
FLAG_IS_EXPORT: t.CDefine = 16
FLAG_IS_DEFINE: t.CDefine = 32
# ============================================================
@@ -172,7 +175,7 @@ class ASTFlag(t.CEnum):
# Helper Functions
# ============================================================
def _copy_str(pool: memhub.MemManager | t.CPtr, src: str) -> str:
def _copy_str(pool: rowptr[memhub.MemManager], src: str) -> str:
"""Allocate and copy a C string from pool."""
if src is None: return None
slen: t.CSizeT = string.strlen(src)
@@ -182,8 +185,8 @@ def _copy_str(pool: memhub.MemManager | t.CPtr, src: str) -> str:
return buf
def _set_pos(node: AST | t.CPtr, lineno: t.CInt, col_offset: t.CInt,
end_lineno: t.CInt, end_col_offset: t.CInt):
def _set_pos(node: rowptr[AST], lineno: int, col_offset: int,
end_lineno: int, end_col_offset: int):
if node is None: return
node.lineno = lineno
node.col_offset = col_offset
@@ -191,7 +194,7 @@ def _set_pos(node: AST | t.CPtr, lineno: t.CInt, col_offset: t.CInt,
node.end_col_offset = end_col_offset
def _inherit_pos(node: AST | t.CPtr, ref: AST | t.CPtr):
def _inherit_pos(node: rowptr[AST], ref: rowptr[AST]):
if node is None or ref is None: return
node.lineno = ref.lineno
node.col_offset = ref.col_offset
@@ -199,8 +202,8 @@ def _inherit_pos(node: AST | t.CPtr, ref: AST | t.CPtr):
node.end_col_offset = ref.end_col_offset
def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr,
lineno: t.CInt, col: t.CInt):
def _init_ast(node: rowptr[AST], pool: rowptr[memhub.MemManager],
lineno: int, col: int):
"""Initialize AST base fields."""
node.parent = None
node.pool = pool
@@ -211,20 +214,20 @@ def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr,
node.children = None
def _set_parent_list(lst: list[AST | t.CPtr] | t.CPtr, parent: AST | t.CPtr):
def _set_parent_list(lst: list[rowptr[AST]] | t.CPtr, parent: rowptr[AST]):
"""Set list children parent pointers."""
if lst is None: return
n: t.CSizeT = lst.__len__()
i: t.CSizeT = 0
while i < n:
child: AST | t.CPtr = lst.get(i)
child: rowptr[AST] = lst.get(i)
if child is not None:
child.parent = parent
i += 1
def _append_child(lst: list[AST | t.CPtr] | t.CPtr, node: AST | t.CPtr,
pool: memhub.MemManager | t.CPtr):
def _append_child(lst: list[rowptr[AST]] | t.CPtr, node: rowptr[AST],
pool: rowptr[memhub.MemManager]):
"""Append child nodes to a list (module-level function, to avoid conflicts with the AST.append method name).
Call this function within the AST.append method to bypass the compiler mistaking list.append for a virtual function call to AST.append when doing type inference."""
@@ -237,7 +240,7 @@ def _append_child(lst: list[AST | t.CPtr] | t.CPtr, node: AST | t.CPtr,
# Operator Mapping: TokOp -> OpKind
# ============================================================
def _binop_from_op(op_id: t.CInt) -> t.CInt:
def _binop_from_op(op_id: int) -> int:
if op_id == TokOp.Plus: return OpKind.Add
if op_id == TokOp.Minus: return OpKind.Sub
if op_id == TokOp.Star: return OpKind.Mult
@@ -254,7 +257,7 @@ def _binop_from_op(op_id: t.CInt) -> t.CInt:
return OpKind.NoneOp
def _augop_from_op(op_id: t.CInt) -> t.CInt:
def _augop_from_op(op_id: int) -> int:
if op_id == TokOp.PlusEq: return OpKind.Add
if op_id == TokOp.MinusEq: return OpKind.Sub
if op_id == TokOp.StarEq: return OpKind.Mult
@@ -271,7 +274,7 @@ def _augop_from_op(op_id: t.CInt) -> t.CInt:
return OpKind.NoneOp
def _cmpop_from_op(op_id: t.CInt) -> t.CInt:
def _cmpop_from_op(op_id: int) -> int:
if op_id == TokOp.EqEq: return OpKind.Eq
if op_id == TokOp.ExclaimEq: return OpKind.Ne
if op_id == TokOp.Less: return OpKind.Lt
@@ -285,46 +288,46 @@ def _cmpop_from_op(op_id: t.CInt) -> t.CInt:
# dump Helper Functions
# ============================================================
def _emit(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
def _emit(buf: str, size: t.CSizeT, pos: t.CSizeT,
text: str) -> t.CSizeT:
"""Append literal to buf+pos."""
if buf is None or pos >= size:
return pos
cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos)
cur: str = str(uint64(buf) + pos)
rem: t.CSizeT = size - pos
n: t.CInt = viperlib.snprintf(cur, rem, "%s", text)
n: int = viperlib.snprintf(cur, rem, "%s", text)
if n < 0:
return pos
return pos + t.CSizeT(n)
def _emit_str(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
def _emit_str(buf: str, size: t.CSizeT, pos: t.CSizeT,
text: str) -> t.CSizeT:
"""Append a string value to buf pos (using %s format)"""
if buf is None or pos >= size:
return pos
cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos)
cur: str = str(uint64(buf) + pos)
rem: t.CSizeT = size - pos
n: t.CInt = viperlib.snprintf(cur, rem, "%s", text)
n: int = viperlib.snprintf(cur, rem, "%s", text)
if n < 0:
return pos
return pos + t.CSizeT(n)
def _emit_int(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
val: t.CInt64T) -> t.CSizeT:
def _emit_int(buf: str, size: t.CSizeT, pos: t.CSizeT,
val: int64) -> t.CSizeT:
"""Append an integer value to buf pos (using %lld format)."""
if buf is None or pos >= size:
return pos
cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos)
cur: str = str(uint64(buf) + pos)
rem: t.CSizeT = size - pos
n: t.CInt = viperlib.snprintf(cur, rem, "%lld", val)
n: int = viperlib.snprintf(cur, rem, "%lld", val)
if n < 0:
return pos
return pos + t.CSizeT(n)
def _op_name(op: t.CInt) -> str:
def _op_name(op: int) -> str:
"""Return the string name of an OpKind."""
if op == OpKind.Add: return "Add"
if op == OpKind.Sub: return "Sub"
@@ -355,10 +358,12 @@ def _op_name(op: t.CInt) -> str:
if op == OpKind.UAdd: return "UAdd"
if op == OpKind.USub: return "USub"
if op == OpKind.Invert: return "Invert"
if op == OpKind.Deref: return "Deref"
if op == OpKind.AddrOf: return "AddrOf"
return "NoneOp"
def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr,
def _dump_list(lst: list[rowptr[AST]] | t.CPtr, buf: str,
size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT:
"""Traverse a list[AST | CPtr] container, polymorphically dump each element."""
if lst is None:
@@ -370,7 +375,7 @@ def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr,
while i < n:
if i > 0:
pos = _emit(buf, size, pos, ", ")
child: AST | t.CPtr = lst.get(i)
child: rowptr[AST] = lst.get(i)
if child is not None:
pos = child.dump(buf, size, pos)
i += 1
@@ -378,20 +383,20 @@ def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr,
return pos
def _dump_op_list(lst: t.CPtr, buf: t.CChar | t.CPtr,
def _dump_op_list(lst: t.CPtr, buf: str,
size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT:
"""Traverse a list[CInt] (OpKind values), output a list of op names."""
if lst is None:
pos = _emit(buf, size, pos, "[]")
return pos
ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(lst)
ops_list: rowptr[list[int]] = (rowptr[list[int]])(lst)
pos = _emit(buf, size, pos, "[")
n: t.CSizeT = ops_list.__len__()
i: t.CSizeT = 0
while i < n:
if i > 0:
pos = _emit(buf, size, pos, ", ")
op: t.CInt = ops_list.get(i)
op: int = ops_list.get(i)
pos = _emit(buf, size, pos, _op_name(op))
i += 1
pos = _emit(buf, size, pos, "]")
@@ -417,15 +422,15 @@ class AST:
end_lineno/end_col_offset: Ending position
children: List of child nodes (body block, added via append)
"""
parent: AST | t.CPtr
pool: memhub.MemManager | t.CPtr
lineno: t.CInt
col_offset: t.CInt
end_lineno: t.CInt
end_col_offset: t.CInt
children: list[AST | t.CPtr] | t.CPtr
parent: rowptr[AST]
pool: rowptr[memhub.MemManager]
lineno: int
col_offset: int
end_lineno: int
end_col_offset: int
children: list[rowptr[AST]] | t.CPtr
def kind(self) -> t.CInt:
def kind(self) -> int:
"""Returns the node type (ASTKind value), overridden by subclasses"""
return 0
@@ -433,7 +438,7 @@ class AST:
"""Return the node type name, subclasses override"""
return "AST"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
"""Polymorphic dump: subclasses override to define custom format. Returns the written pos"""
return pos
@@ -443,7 +448,7 @@ class AST:
Current implementation is empty. override this method to dispatch to visitor.visit_X(self)"""
pass
def append(self, node: AST | t.CPtr):
def append(self, node: rowptr[AST]):
"""Append node to the children list.
Used for parser to build statement blocks: module.append(stmt), if_node.append(stmt), etc.
@@ -454,7 +459,7 @@ class AST:
if self is None or node is None:
return
if self.children is None:
self.children = list[AST | t.CPtr](self.pool, 8)
self.children = list[rowptr[AST]](self.pool, 8)
node.parent = self
_append_child(self.children, node, self.pool)
@@ -492,7 +497,7 @@ class ExprNode(AST):
# Module dump function (for ast.dump(node, buf, size))
# ============================================================
def dump(node: AST | t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT):
def dump(node: rowptr[AST], buf: str, size: t.CSizeT):
"""Serialize AST node to buf (with capacity size)"""
if node is None or buf is None or size == 0:
return
+285 -285
View File
File diff suppressed because it is too large. Load diff
+79 -79
View File
@@ -19,31 +19,31 @@ class Lexer:
src: str # Source code (NUL-terminated)
pos: t.CSizeT # Current position
len: t.CSizeT # Source code length
lineno: t.CInt # Current line number (1-based)
col: t.CInt # Current column number (0-based)
pool: memhub.MemManager | t.CPtr # Memory pool
indent_stack: t.CInt | t.CPtr # Indent stack (int array, allocated from pool)
indent_top: t.CInt # Stack top (-1 for empty stack)
paren_depth: t.CInt # Paren depth (>0 for no TokenType.NewLine)
tokens_head: Token | t.CPtr # token list head
tokens_tail: Token | t.CPtr # token list tail
at_line_start: t.CInt # 1=line start (need indent)
error_count: t.CInt # Error count
lineno: int # Current line number (1-based)
col: int # Current column number (0-based)
pool: rowptr[memhub.MemManager] # Memory pool
indent_stack: rowptr[int] # Indent stack (int array, allocated from pool)
indent_top: int # Stack top (-1 for empty stack)
paren_depth: int # Paren depth (>0 for no TokenType.NewLine)
tokens_head: rowptr[Token] # token list head
tokens_tail: rowptr[Token] # token list tail
at_line_start: int # 1=line start (need indent)
error_count: int # Error count
def __new__(self, pool: memhub.MemManager | t.CPtr):
ptr: Lexer | t.CPtr = pool.alloc(Lexer.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager]):
ptr: rowptr[Lexer] = pool.alloc(Lexer.__sizeof__())
if ptr:
string.memset(ptr, 0, Lexer.__sizeof__())
return ptr
def new_lexer(pool: memhub.MemManager | t.CPtr) -> Lexer | t.CPtr:
def new_lexer(pool: rowptr[memhub.MemManager]) -> rowptr[Lexer]:
"""Allocate from the pool and return a Lexer (cross-module safe wrapper)"""
return Lexer(pool)
def _lexer_init(lx: Lexer | t.CPtr, src: str,
pool: memhub.MemManager | t.CPtr):
def _lexer_init(lx: rowptr[Lexer], src: str,
pool: rowptr[memhub.MemManager]):
"""Initialize Lexer"""
if lx == None: return
lx.src = src
@@ -73,7 +73,7 @@ def _lexer_init(lx: Lexer | t.CPtr, src: str,
# Auxiliary Functions
# ============================================================
def _peek(lx: Lexer | t.CPtr, offset: t.CSizeT) -> t.CChar:
def _peek(lx: rowptr[Lexer], offset: t.CSizeT) -> t.CChar:
"""Peek character at position pos+offset, return '\0' if out of bounds"""
p: t.CSizeT = lx.pos + offset
if p >= lx.len:
@@ -81,13 +81,13 @@ def _peek(lx: Lexer | t.CPtr, offset: t.CSizeT) -> t.CChar:
return lx.src[p]
def _peek_cur(lx: Lexer | t.CPtr) -> t.CChar:
def _peek_cur(lx: rowptr[Lexer]) -> t.CChar:
if lx.pos >= lx.len:
return '\0'
return lx.src[lx.pos]
def _advance(lx: Lexer | t.CPtr) -> t.CChar:
def _advance(lx: rowptr[Lexer]) -> t.CChar:
"""Advance one character, return the character"""
if lx.pos >= lx.len:
return '\0'
@@ -101,40 +101,40 @@ def _advance(lx: Lexer | t.CPtr) -> t.CChar:
return ch
def _is_alpha(ch: t.CChar) -> t.CInt:
def _is_alpha(ch: t.CChar) -> int:
if ch >= 'a' and ch <= 'z': return 1
if ch >= 'A' and ch <= 'Z': return 1
if ch == '_': return 1
return 0
def _is_digit(ch: t.CChar) -> t.CInt:
def _is_digit(ch: t.CChar) -> int:
if ch >= '0' and ch <= '9': return 1
return 0
def _is_alnum(ch: t.CChar) -> t.CInt:
def _is_alnum(ch: t.CChar) -> int:
if _is_alpha(ch): return 1
if _is_digit(ch): return 1
return 0
def _is_hex(ch: t.CChar) -> t.CInt:
def _is_hex(ch: t.CChar) -> int:
if ch >= '0' and ch <= '9': return 1
if ch >= 'a' and ch <= 'f': return 1
if ch >= 'A' and ch <= 'F': return 1
return 0
def _hex_val(ch: t.CChar) -> t.CInt:
def _hex_val(ch: t.CChar) -> int:
"""十六进制字符转数值 0-15(供 \xNN 转义解析)"""
if ch >= '0' and ch <= '9': return t.CInt(ch) - 48
if ch >= 'a' and ch <= 'f': return t.CInt(ch) - 87
if ch >= 'A' and ch <= 'F': return t.CInt(ch) - 55
if ch >= '0' and ch <= '9': return int(ch) - 48
if ch >= 'a' and ch <= 'f': return int(ch) - 87
if ch >= 'A' and ch <= 'F': return int(ch) - 55
return 0
def _is_space(ch: t.CChar) -> t.CInt:
def _is_space(ch: t.CChar) -> int:
if ch == ' ': return 1
if ch == '\t': return 1
if ch == '\f': return 1
@@ -143,7 +143,7 @@ def _is_space(ch: t.CChar) -> t.CInt:
return 0
def _emit(lx: Lexer | t.CPtr, tok: Token | t.CPtr):
def _emit(lx: rowptr[Lexer], tok: rowptr[Token]):
"""Append token to token list"""
if tok == None: return
if lx.tokens_head == None:
@@ -154,9 +154,9 @@ def _emit(lx: Lexer | t.CPtr, tok: Token | t.CPtr):
lx.tokens_tail = tok
def _make_op_token(lx: Lexer | t.CPtr, op_id: t.CInt, length: t.CInt,
lineno: t.CInt, col: t.CInt) -> Token | t.CPtr:
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Op, lineno, col)
def _make_op_token(lx: rowptr[Lexer], op_id: int, length: int,
lineno: int, col: int) -> rowptr[Token]:
tok: rowptr[Token] = new_token(lx.pool, TokenType.Op, lineno, col)
if tok == None: return None
tok.op_subtype = op_id
tok.end_col_offset = col + length
@@ -167,14 +167,14 @@ def _make_op_token(lx: Lexer | t.CPtr, op_id: t.CInt, length: t.CInt,
# Indent Handling
# ============================================================
def _handle_indent(lx: Lexer | t.CPtr):
def _handle_indent(lx: rowptr[Lexer]):
"""Handle line start indent, generate TokenType.Indent/TokenType.Dedent.
Skip empty lines and comment lines."""
# Skip empty lines and comment lines
while lx.pos < lx.len:
# Save line start position for non-empty lines
line_start_pos: t.CSizeT = lx.pos
line_start_col: t.CInt = lx.col
line_start_col: int = lx.col
# Skip whitespace, not across lines
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
@@ -219,9 +219,9 @@ def _handle_indent(lx: Lexer | t.CPtr):
return
# Calculate current line indent
indent: t.CInt = 0
indent: int = 0
save_pos: t.CSizeT = lx.pos
save_col: t.CInt = lx.col
save_col: int = lx.col
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == ' ':
@@ -246,7 +246,7 @@ def _handle_indent(lx: Lexer | t.CPtr):
return
# Compare indent with top of indent stack
top_indent: t.CInt = lx.indent_stack[lx.indent_top]
top_indent: int = lx.indent_stack[lx.indent_top]
if indent > top_indent:
# TokenType.Indent
if lx.indent_top + 1 >= LEXER_MAX_INDENT:
@@ -254,12 +254,12 @@ def _handle_indent(lx: Lexer | t.CPtr):
return
lx.indent_top += 1
lx.indent_stack[lx.indent_top] = indent
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Indent, lx.lineno, 0)
tok: rowptr[Token] = new_token(lx.pool, TokenType.Indent, lx.lineno, 0)
_emit(lx, tok)
else:
while indent < lx.indent_stack[lx.indent_top] and lx.indent_top > 0:
lx.indent_top -= 1
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0)
tok: rowptr[Token] = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0)
_emit(lx, tok)
lx.at_line_start = 0
@@ -268,10 +268,10 @@ def _handle_indent(lx: Lexer | t.CPtr):
# Identifier/Keyword Handling
# ============================================================
def _read_name(lx: Lexer | t.CPtr):
def _read_name(lx: rowptr[Lexer]):
start: t.CSizeT = lx.pos
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
start_lineno: int = lx.lineno
start_col: int = lx.col
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if _is_alnum(ch):
@@ -280,13 +280,13 @@ def _read_name(lx: Lexer | t.CPtr):
else:
break
length: t.CSizeT = lx.pos - start
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Name, start_lineno, start_col)
tok: rowptr[Token] = new_token(lx.pool, TokenType.Name, start_lineno, start_col)
if tok == None: return
token_set_str(lx.pool, tok, lx.src, start, length)
tok.end_lineno = lx.lineno
tok.end_col_offset = start_col + t.CInt(length)
tok.end_col_offset = start_col + int(length)
# Look up keyword if any
kw_id: t.CInt = _kw_lookup(tok.str_val)
kw_id: int = _kw_lookup(tok.str_val)
if kw_id:
tok.kw_subtype = kw_id
_emit(lx, tok)
@@ -296,12 +296,12 @@ def _read_name(lx: Lexer | t.CPtr):
# Number Handling
# ============================================================
def _read_number(lx: Lexer | t.CPtr):
def _read_number(lx: rowptr[Lexer]):
start: t.CSizeT = lx.pos
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
is_float: t.CInt = 0
is_complex: t.CInt = 0
start_lineno: int = lx.lineno
start_col: int = lx.col
is_float: int = 0
is_complex: int = 0
ch0: t.CChar = lx.src[lx.pos]
# Handle 0x/0o/0b prefix
@@ -399,17 +399,17 @@ def _read_number(lx: Lexer | t.CPtr):
_emit_number(lx, start, start_lineno, start_col, is_float, is_complex, 0)
def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT,
start_lineno: t.CInt, start_col: t.CInt,
is_float: t.CInt, is_complex: t.CInt, is_hex: t.CInt):
def _emit_number(lx: rowptr[Lexer], start: t.CSizeT,
start_lineno: int, start_col: int,
is_float: int, is_complex: int, is_hex: int):
length: t.CSizeT = lx.pos - start
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Number, start_lineno, start_col)
tok: rowptr[Token] = new_token(lx.pool, TokenType.Number, start_lineno, start_col)
if tok == None: return
token_set_str(lx.pool, tok, lx.src, start, length)
tok.is_float = is_float
tok.is_complex = is_complex
tok.end_lineno = lx.lineno
tok.end_col_offset = start_col + t.CInt(length)
tok.end_col_offset = start_col + int(length)
# Parse number
if is_float:
tok.float_val = string.atof(tok.str_val)
@@ -422,19 +422,19 @@ def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT,
# String Handling
# ============================================================
def _read_string(lx: Lexer | t.CPtr):
def _read_string(lx: rowptr[Lexer]):
"""Read string literal.
Supports prefixes: r, b, u, f, rb, br, rf, fr (case insensitive)
Supports quotes: ', ", ''',
Later we need to support string prefixes like i16/i24"""
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
start_lineno: int = lx.lineno
start_col: int = lx.col
prefix_start: t.CSizeT = lx.pos
# Read prefix (r/b/u/f)
is_raw: t.CInt = 0
is_bytes: t.CInt = 0
is_fstring: t.CInt = 0
is_raw: int = 0
is_bytes: int = 0
is_fstring: int = 0
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == 'r' or ch == 'R':
@@ -466,7 +466,7 @@ def _read_string(lx: Lexer | t.CPtr):
return
# Check triple quote
is_triple: t.CInt = 0
is_triple: int = 0
if lx.pos + 2 < lx.len:
if lx.src[lx.pos] == quote and lx.src[lx.pos + 1] == quote and lx.src[lx.pos + 2] == quote:
is_triple = 1
@@ -482,7 +482,7 @@ def _read_string(lx: Lexer | t.CPtr):
# Read string content
content_buf_start: t.CSizeT = lx.pos
# f-string {} 表达式块嵌套深度(PEP 701 同引号嵌套字符串支持用)
fstr_depth: t.CInt = 0
fstr_depth: int = 0
while lx.pos < lx.len:
ch = lx.src[lx.pos]
if is_triple:
@@ -582,7 +582,7 @@ def _read_string(lx: Lexer | t.CPtr):
lx.col += 1
# Create token
tok: Token | t.CPtr = new_token(lx.pool, TokenType.String, start_lineno, start_col)
tok: rowptr[Token] = new_token(lx.pool, TokenType.String, start_lineno, start_col)
if tok == None: return
content_len: t.CSizeT = content_end - content_buf_start
# esc_len: Actual bytes after escaping (used to check single character)
@@ -632,7 +632,7 @@ def _read_string(lx: Lexer | t.CPtr):
h1: t.CChar = lx.src[content_buf_start + rpos + 1]
h2: t.CChar = lx.src[content_buf_start + rpos + 2]
if _is_hex(h1) != 0 and _is_hex(h2) != 0:
hex_v: t.CInt = (_hex_val(h1) << 4) | _hex_val(h2)
hex_v: int = (_hex_val(h1) << 4) | _hex_val(h2)
conv_buf[wpos] = t.CChar(hex_v)
wpos += 1
rpos += 3
@@ -677,20 +677,20 @@ def _read_string(lx: Lexer | t.CPtr):
# Operator Matching
# ============================================================
def _read_operator(lx: Lexer | t.CPtr):
def _read_operator(lx: rowptr[Lexer]):
"""Greedy match operator"""
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
start_lineno: int = lx.lineno
start_col: int = lx.col
remaining: t.CSizeT = lx.len - lx.pos
# Traverse operator table, find longest match
best_entry: OpEntry | t.CPtr = None
best_len: t.CInt = 0
cur: OpEntry | t.CPtr = _op_head
best_entry: rowptr[OpEntry] = None
best_len: int = 0
cur: rowptr[OpEntry] = _op_head
while cur != None:
if cur.length <= t.CInt(remaining):
if cur.length <= int(remaining):
# Compare cur.name with src[pos:pos+cur.length]
match: t.CInt = 1
match: int = 1
i: t.CSizeT = 0
while i < t.CSizeT(cur.length):
if lx.src[lx.pos + i] != cur.name[i]:
@@ -717,7 +717,7 @@ def _read_operator(lx: Lexer | t.CPtr):
if lx.paren_depth > 0:
lx.paren_depth -= 1
tok: Token | t.CPtr = _make_op_token(lx, best_entry.op_id, best_entry.length,
tok: rowptr[Token] = _make_op_token(lx, best_entry.op_id, best_entry.length,
start_lineno, start_col)
if tok == None: return
token_set_str(lx.pool, tok, lx.src, lx.pos, t.CSizeT(best_len))
@@ -730,7 +730,7 @@ def _read_operator(lx: Lexer | t.CPtr):
# Main Lexical Analysis Entry Point
# ============================================================
def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr:
def tokenize(lx: rowptr[Lexer]) -> rowptr[Token]:
"""Execute tokenization, return token list head"""
if lx == None: return None
while lx.pos < lx.len:
@@ -748,11 +748,11 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr:
if ch == '\n':
if lx.paren_depth > 0:
# # In bi brackets, generates TokenType.Nl
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Nl, lx.lineno, lx.col)
tok: rowptr[Token] = new_token(lx.pool, TokenType.Nl, lx.lineno, lx.col)
_emit(lx, tok)
else:
# Logical new line
tok: Token | t.CPtr = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col)
tok: rowptr[Token] = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col)
_emit(lx, tok)
lx.at_line_start = 1
lx.pos += 1
@@ -828,17 +828,17 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr:
# End of file: generate TokenType.NewLine (if there's content)
if lx.tokens_tail != None:
if lx.tokens_tail.type != TokenType.NewLine and lx.tokens_tail.type != TokenType.Nl:
tok: Token | t.CPtr = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col)
tok: rowptr[Token] = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col)
_emit(lx, tok)
# Generate remaining remaining TokenType.Dedent
while lx.indent_top > 0:
lx.indent_top -= 1
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0)
tok: rowptr[Token] = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0)
_emit(lx, tok)
# TokenType.EndMarker
tok: Token | t.CPtr = new_token(lx.pool, TokenType.EndMarker, lx.lineno, 0)
tok: rowptr[Token] = new_token(lx.pool, TokenType.EndMarker, lx.lineno, 0)
_emit(lx, tok)
return lx.tokens_head
+83 -83
View File
@@ -15,29 +15,29 @@ from .base import (
class MatchCase(AST):
"""MatchCase(pattern: AST, guard: AST)"""
pattern: AST | t.CPtr
guard: AST | t.CPtr
pattern: rowptr[AST]
guard: rowptr[AST]
def __new__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, guard: AST | t.CPtr):
ptr: MatchCase | t.CPtr = pool.alloc(MatchCase.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
pattern: rowptr[AST], guard: rowptr[AST]):
ptr: rowptr[MatchCase] = pool.alloc(MatchCase.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchCase.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, guard: AST | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
pattern: rowptr[AST], guard: rowptr[AST]):
_init_ast(self, pool, 0, 0)
self.pattern = pattern
self.guard = guard
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchCase
def type_name(self) -> str:
return "MatchCase"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchCase(pattern=")
if self.pattern is not None:
@@ -57,25 +57,25 @@ class MatchCase(AST):
class MatchValue(AST):
"""MatchValue(value: AST)"""
value: AST | t.CPtr
value: rowptr[AST]
def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
ptr: MatchValue | t.CPtr = pool.alloc(MatchValue.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager], value: rowptr[AST]):
ptr: rowptr[MatchValue] = pool.alloc(MatchValue.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchValue.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager], value: rowptr[AST]):
_init_ast(self, pool, 0, 0)
self.value = value
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchValue
def type_name(self) -> str:
return "MatchValue"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchValue(value=")
if self.value is not None:
@@ -90,25 +90,25 @@ class MatchValue(AST):
class MatchSingleton(AST):
"""MatchSingleton(value: AST)"""
value: AST | t.CPtr
value: rowptr[AST]
def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
ptr: MatchSingleton | t.CPtr = pool.alloc(MatchSingleton.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager], value: rowptr[AST]):
ptr: rowptr[MatchSingleton] = pool.alloc(MatchSingleton.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchSingleton.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager], value: rowptr[AST]):
_init_ast(self, pool, 0, 0)
self.value = value
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchSingleton
def type_name(self) -> str:
return "MatchSingleton"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchSingleton(value=")
if self.value is not None:
@@ -122,29 +122,29 @@ class MatchSingleton(AST):
# ============================================================
class MatchSequence(AST):
"""MatchSequence(patterns: list[AST | t.CPtr])"""
patterns: list[AST | t.CPtr] | t.CPtr
"""MatchSequence(patterns: list[rowptr[AST]])"""
patterns: rowptr[list[rowptr[AST]]]
def __new__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
ptr: MatchSequence | t.CPtr = pool.alloc(MatchSequence.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
patterns: rowptr[list[rowptr[AST]]]):
ptr: rowptr[MatchSequence] = pool.alloc(MatchSequence.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchSequence.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
patterns: rowptr[list[rowptr[AST]]]):
_init_ast(self, pool, 0, 0)
self.patterns = patterns
_set_parent_list(patterns, self)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchSequence
def type_name(self) -> str:
return "MatchSequence"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchSequence(patterns=")
pos = _dump_list(self.patterns, buf, size, pos)
@@ -157,23 +157,23 @@ class MatchSequence(AST):
# ============================================================
class MatchMapping(AST):
"""MatchMapping(keys: list[AST | t.CPtr], patterns: list[AST | t.CPtr], rest: str)"""
keys: list[AST | t.CPtr] | t.CPtr
patterns: list[AST | t.CPtr] | t.CPtr
"""MatchMapping(keys: list[rowptr[AST]], patterns: list[rowptr[AST]], rest: str)"""
keys: rowptr[list[rowptr[AST]]]
patterns: rowptr[list[rowptr[AST]]]
rest: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
keys: list[AST | t.CPtr] | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
def __new__(self, pool: rowptr[memhub.MemManager],
keys: rowptr[list[rowptr[AST]]],
patterns: rowptr[list[rowptr[AST]]],
rest: str):
ptr: MatchMapping | t.CPtr = pool.alloc(MatchMapping.__sizeof__())
ptr: rowptr[MatchMapping] = pool.alloc(MatchMapping.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchMapping.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
keys: list[AST | t.CPtr] | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
def __init__(self, pool: rowptr[memhub.MemManager],
keys: rowptr[list[rowptr[AST]]],
patterns: rowptr[list[rowptr[AST]]],
rest: str):
_init_ast(self, pool, 0, 0)
self.keys = keys
@@ -182,13 +182,13 @@ class MatchMapping(AST):
_set_parent_list(keys, self)
_set_parent_list(patterns, self)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchMapping
def type_name(self) -> str:
return "MatchMapping"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchMapping(keys=")
pos = _dump_list(self.keys, buf, size, pos)
@@ -205,28 +205,28 @@ class MatchMapping(AST):
# ============================================================
class MatchClass(AST):
"""MatchClass(cls: AST, patterns: list[AST | t.CPtr],
kwd_attrs: list[AST | t.CPtr], kwd_patterns: list[AST | t.CPtr])"""
cls: AST | t.CPtr
patterns: list[AST | t.CPtr] | t.CPtr
kwd_attrs: list[AST | t.CPtr] | t.CPtr
kwd_patterns: list[AST | t.CPtr] | t.CPtr
"""MatchClass(cls: AST, patterns: list[rowptr[AST]],
kwd_attrs: list[rowptr[AST]], kwd_patterns: list[rowptr[AST]])"""
cls: rowptr[AST]
patterns: rowptr[list[rowptr[AST]]]
kwd_attrs: rowptr[list[rowptr[AST]]]
kwd_patterns: rowptr[list[rowptr[AST]]]
def __new__(self, pool: memhub.MemManager | t.CPtr,
cls: AST | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
kwd_attrs: list[AST | t.CPtr] | t.CPtr,
kwd_patterns: list[AST | t.CPtr] | t.CPtr):
ptr: MatchClass | t.CPtr = pool.alloc(MatchClass.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
cls: rowptr[AST],
patterns: rowptr[list[rowptr[AST]]],
kwd_attrs: rowptr[list[rowptr[AST]]],
kwd_patterns: rowptr[list[rowptr[AST]]]):
ptr: rowptr[MatchClass] = pool.alloc(MatchClass.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchClass.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
cls: AST | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
kwd_attrs: list[AST | t.CPtr] | t.CPtr,
kwd_patterns: list[AST | t.CPtr] | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
cls: rowptr[AST],
patterns: rowptr[list[rowptr[AST]]],
kwd_attrs: rowptr[list[rowptr[AST]]],
kwd_patterns: rowptr[list[rowptr[AST]]]):
_init_ast(self, pool, 0, 0)
self.cls = cls
self.patterns = patterns
@@ -236,13 +236,13 @@ class MatchClass(AST):
_set_parent_list(kwd_attrs, self)
_set_parent_list(kwd_patterns, self)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchClass
def type_name(self) -> str:
return "MatchClass"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchClass(cls=")
if self.cls is not None:
@@ -265,23 +265,23 @@ class MatchStar(AST):
"""MatchStar(name: str)"""
name: str
def __new__(self, pool: memhub.MemManager | t.CPtr, name: str):
ptr: MatchStar | t.CPtr = pool.alloc(MatchStar.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager], name: str):
ptr: rowptr[MatchStar] = pool.alloc(MatchStar.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchStar.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr, name: str):
def __init__(self, pool: rowptr[memhub.MemManager], name: str):
_init_ast(self, pool, 0, 0)
self.name = _copy_str(pool, name)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchStar
def type_name(self) -> str:
return "MatchStar"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchStar(name='")
pos = _emit_str(buf, size, pos, self.name)
@@ -295,29 +295,29 @@ class MatchStar(AST):
class MatchAs(AST):
"""MatchAs(pattern: AST, name: str)"""
pattern: AST | t.CPtr
pattern: rowptr[AST]
name: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, name: str):
ptr: MatchAs | t.CPtr = pool.alloc(MatchAs.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
pattern: rowptr[AST], name: str):
ptr: rowptr[MatchAs] = pool.alloc(MatchAs.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchAs.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, name: str):
def __init__(self, pool: rowptr[memhub.MemManager],
pattern: rowptr[AST], name: str):
_init_ast(self, pool, 0, 0)
self.pattern = pattern
self.name = _copy_str(pool, name)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchAs
def type_name(self) -> str:
return "MatchAs"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchAs(pattern=")
if self.pattern is not None:
@@ -333,29 +333,29 @@ class MatchAs(AST):
# ============================================================
class MatchOr(AST):
"""MatchOr(patterns: list[AST | t.CPtr])"""
patterns: list[AST | t.CPtr] | t.CPtr
"""MatchOr(patterns: list[rowptr[AST]])"""
patterns: rowptr[list[rowptr[AST]]]
def __new__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
ptr: MatchOr | t.CPtr = pool.alloc(MatchOr.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager],
patterns: rowptr[list[rowptr[AST]]]):
ptr: rowptr[MatchOr] = pool.alloc(MatchOr.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchOr.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemManager],
patterns: rowptr[list[rowptr[AST]]]):
_init_ast(self, pool, 0, 0)
self.patterns = patterns
_set_parent_list(patterns, self)
def kind(self) -> t.CInt:
def kind(self) -> int:
return ASTKind.MatchOr
def type_name(self) -> str:
return "MatchOr"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
def dump(self, buf: str, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchOr(patterns=")
pos = _dump_list(self.patterns, buf, size, pos)
+691 -594
View File
File diff suppressed because it is too large. Load diff
+280 -280
View File
File diff suppressed because it is too large. Load diff
+47 -43
View File
@@ -81,6 +81,9 @@ class Keyword(t.CEnum):
Extern: t.State
# export 函数声明关键字(等价 t.CExport,裸名导出不加 SHA1 头;软判定见 _is_funcdef_kw)
Export: t.State
# define 宏函数关键字(与 def 语义一致,返回注解自动追加 t.CDefine 标记
# 为宏函数;软判定见 _is_funcdef_kw)
Define: t.State
# ============================================================
@@ -144,23 +147,23 @@ class TokOp(t.CEnum):
# Token stucture
# ============================================================
class Token:
type: t.CInt # Token type (TokenType.EndMarker / TokenType.NewLine / TokenType.Name / ...)
op_subtype: t.CInt # Operator subtype (OP_*). Only valid when type == TokenType.Op
kw_subtype: t.CInt # Keyword subtype (KW_*). Only valid when type == TokenType.Name and it is a keyword
type: int # Token type (TokenType.EndMarker / TokenType.NewLine / TokenType.Name / ...)
op_subtype: int # Operator subtype (OP_*). Only valid when type == TokenType.Op
kw_subtype: int # Keyword subtype (KW_*). Only valid when type == TokenType.Name and it is a keyword
str_val: str # Token text (NUL‑terminated, allocated from pool)
int_val: t.CInt64T # Integer value (used by TokenType.Number)
float_val: t.CDouble # Floating‑point value (used by TokenType.Number)
is_float: t.CInt # 1 = floating‑point number, 0 = integer
is_complex: t.CInt # 1 = complex number, 0 = real number
lineno: t.CInt # Starting line number
col_offset: t.CInt # Starting column offset
end_lineno: t.CInt # Ending line number
end_col_offset: t.CInt # Ending column offset
next: Token | t.CPtr # Next token in linked list
int_val: int64 # Integer value (used by TokenType.Number)
float_val: double # Floating‑point value (used by TokenType.Number)
is_float: int # 1 = floating‑point number, 0 = integer
is_complex: int # 1 = complex number, 0 = real number
lineno: int # Starting line number
col_offset: int # Starting column offset
end_lineno: int # Ending line number
end_col_offset: int # Ending column offset
next: rowptr[Token] # Next token in linked list
def __new__(self, pool: memhub.MemManager | t.CPtr):
def __new__(self, pool: rowptr[memhub.MemManager]):
"""Allocate zero‑initialized Token struct memory from mpool"""
ptr: Token | t.CPtr = pool.alloc(Token.__sizeof__())
ptr: rowptr[Token] = pool.alloc(Token.__sizeof__())
if ptr:
string.memset(ptr, 0, Token.__sizeof__())
return ptr
@@ -172,25 +175,25 @@ class Token:
# ============================================================
class KwEntry:
name: str
kw_id: t.CInt
next: KwEntry | t.CPtr
kw_id: int
next: rowptr[KwEntry]
def __new__(self, pool: memhub.MemManager | t.CPtr):
ptr: KwEntry | t.CPtr = pool.alloc(KwEntry.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager]):
ptr: rowptr[KwEntry] = pool.alloc(KwEntry.__sizeof__())
if ptr:
string.memset(ptr, 0, KwEntry.__sizeof__())
return ptr
# Global keyword linked list head (lazy initialization)
_kw_head: KwEntry | t.CPtr = None
_kw_pool: memhub.MemManager | t.CPtr = None
_kw_head: rowptr[KwEntry] = None
_kw_pool: rowptr[memhub.MemManager] = None
def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt):
def _kw_intern(pool: rowptr[memhub.MemManager], name: str, kw_id: int):
"""Register keyword name in the linked list"""
global _kw_head
entry: KwEntry | t.CPtr = KwEntry(pool)
entry: rowptr[KwEntry] = KwEntry(pool)
if entry == None: return
slen: t.CSizeT = string.strlen(name)
buf: str = pool.alloc(slen + 1)
@@ -202,9 +205,9 @@ def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt):
_kw_head = entry
def _kw_lookup(name: str) -> t.CInt:
def _kw_lookup(name: str) -> int:
"""Look up keyword name in the linked list, return the kw_id (0 if not keyword)"""
cur: KwEntry | t.CPtr = _kw_head
cur: rowptr[KwEntry] = _kw_head
while cur != None:
if string.strcmp(cur.name, name) == 0:
return cur.kw_id
@@ -212,7 +215,7 @@ def _kw_lookup(name: str) -> t.CInt:
return 0
def _init_keywords(pool: memhub.MemManager | t.CPtr):
def _init_keywords(pool: rowptr[memhub.MemManager]):
"""Initialize keyword linked list (only once)"""
global _kw_head, _kw_pool
if _kw_head != None: return
@@ -259,9 +262,10 @@ def _init_keywords(pool: memhub.MemManager | t.CPtr):
_kw_intern(pool, "fn", Keyword.Fn)
_kw_intern(pool, "fun", Keyword.Fun)
_kw_intern(pool, "func", Keyword.Func)
_kw_intern(pool, "function", Keyword.Function)
_kw_intern(pool, "extern", Keyword.Extern)
_kw_intern(pool, "function", Keyword.Function)
_kw_intern(pool, "extern", Keyword.Extern)
_kw_intern(pool, "export", Keyword.Export)
_kw_intern(pool, "define", Keyword.Define)
# ============================================================
@@ -271,36 +275,36 @@ def _init_keywords(pool: memhub.MemManager | t.CPtr):
# ============================================================
class OpEntry:
name: str # Operator text (e.g. "==", "+=")
op_id: t.CInt
length: t.CInt
next: OpEntry | t.CPtr
op_id: int
length: int
next: rowptr[OpEntry]
def __new__(self, pool: memhub.MemManager | t.CPtr):
ptr: OpEntry | t.CPtr = pool.alloc(OpEntry.__sizeof__())
def __new__(self, pool: rowptr[memhub.MemManager]):
ptr: rowptr[OpEntry] = pool.alloc(OpEntry.__sizeof__())
if ptr:
string.memset(ptr, 0, OpEntry.__sizeof__())
return ptr
_op_head: OpEntry | t.CPtr = None
_op_head: rowptr[OpEntry] = None
def _op_intern(pool: memhub.MemManager | t.CPtr, name: str, op_id: t.CInt):
def _op_intern(pool: rowptr[memhub.MemManager], name: str, op_id: int):
global _op_head
slen: t.CSizeT = string.strlen(name)
entry: OpEntry | t.CPtr = OpEntry(pool)
entry: rowptr[OpEntry] = OpEntry(pool)
if entry == None: return
buf: str = pool.alloc(slen + 1)
if buf == None: return
string.memcpy(buf, name, slen + 1)
entry.name = buf
entry.op_id = op_id
entry.length = t.CInt(slen)
entry.length = int(slen)
entry.next = _op_head
_op_head = entry
def _init_operators(pool: memhub.MemManager | t.CPtr):
def _init_operators(pool: rowptr[memhub.MemManager]):
"""Initialize the operator table (register in descending length order for easy greedy matching)"""
global _op_head
if _op_head != None: return
@@ -356,7 +360,7 @@ def _init_operators(pool: memhub.MemManager | t.CPtr):
_op_intern(pool, "~", TokOp.Tilde)
def _init_tables(pool: memhub.MemManager | t.CPtr):
def _init_tables(pool: rowptr[memhub.MemManager]):
"""Initialize all lookup tables (idempotent)"""
_init_keywords(pool)
_init_operators(pool)
@@ -366,10 +370,10 @@ def _init_tables(pool: memhub.MemManager | t.CPtr):
# Token creation helper functions
# ============================================================
def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt,
col_offset: t.CInt) -> Token | t.CPtr:
def new_token(pool: rowptr[memhub.MemManager], ttype: int, lineno: int,
col_offset: int) -> rowptr[Token]:
"""Create a new empty Token and fill in fields later"""
tok: Token | t.CPtr = Token(pool)
tok: rowptr[Token] = Token(pool)
if tok == None: return None
tok.type = ttype
tok.lineno = lineno
@@ -379,7 +383,7 @@ def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt,
return tok
def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
def token_set_str(pool: rowptr[memhub.MemManager], tok: rowptr[Token],
src: str, start: t.CSizeT, length: t.CSizeT):
"""Copy text from src[start:start + length] to token.str_val
@@ -396,7 +400,7 @@ def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
tok.str_val = buf
def token_set_str_literal(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
def token_set_str_literal(pool: rowptr[memhub.MemManager], tok: rowptr[Token],
text: str):
"""Copy a C string to token.str_val"""
if tok == None or text == None: return
+31
View File
@@ -1,3 +1,4 @@
import stdint as __stdint
import t
# ============================================================
@@ -23,3 +24,33 @@ def max(a: double, b: double) -> double:
if a > b:
return a
return b
# rowptr 已内置于编译器(TPC/TPV 双端),作为语法保留字,不可重定义:
# rowptr[T] 固定表示"裸指针,指向原始类型 T"(等价 t.CPtr[T])。
size_t: t.CTypedef = t.CSizeT
int8: t.CTypedef = t.CInt8T
int16: t.CTypedef = t.CInt16T
int32: t.CTypedef = t.CInt32T
int64: t.CTypedef = t.CInt64T
uint8: t.CTypedef = t.CUInt8T
uint16: t.CTypedef = t.CUInt16T
uint32: t.CTypedef = t.CUInt32T
uint64: t.CTypedef = t.CUInt64T
intfast8: t.CTypedef = t.CIntFast8T
intfast16: t.CTypedef = t.CIntFast16T
intfast32: t.CTypedef = t.CIntFast32T
intfast64: t.CTypedef = t.CIntFast64T
uintfast8: t.CTypedef = t.CUIntFast8T
uintfast16: t.CTypedef = t.CUIntFast16T
uintfast32: t.CTypedef = t.CUIntFast32T
uintfast64: t.CTypedef = t.CUIntFast64T
intleast8: t.CTypedef = t.CIntLeast8T
intleast16: t.CTypedef = t.CIntLeast16T
intleast32: t.CTypedef = t.CIntLeast32T
intleast64: t.CTypedef = t.CIntLeast64T
uintleast8: t.CTypedef = t.CUIntLeast8T
uintleast16: t.CTypedef = t.CUIntLeast16T
uintleast32: t.CTypedef = t.CUIntLeast32T
uintleast64: t.CTypedef = t.CUIntLeast64T
+2 -2
View File
@@ -1,4 +1,4 @@
from .__md5 import md5, MD5_DIGEST_LEN
from .__sha1 import sha1, SHA1_DIGEST_LEN
from .__md5 import md5, MD5_DIGEST_LEN
from .__sha1 import sha1, SHA1_DIGEST_LEN
from .__sha256 import sha256, SHA256_DIGEST_LEN
from .__sha512 import sha512, SHA512_DIGEST_LEN
+26 -26
View File
@@ -9,15 +9,15 @@ MD5_BLOCK_LEN: t.CDefine = 64 # Group block size
MD5_DIGEST_LEN: t.CDefine = 16 # Digest output length
# MD5 four-round nonlinear functions
def md5_F(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & y) | (~x & z)
def md5_G(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & z) | (y & ~z)
def md5_H(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return x ^ y ^ z
def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return y ^ (x | ~z)
def md5_F(x: uint32, y: uint32, z: uint32) -> uint32: return (x & y) | (~x & z)
def md5_G(x: uint32, y: uint32, z: uint32) -> uint32: return (x & z) | (y & ~z)
def md5_H(x: uint32, y: uint32, z: uint32) -> uint32: return x ^ y ^ z
def md5_I(x: uint32, y: uint32, z: uint32) -> uint32: return y ^ (x | ~z)
# Circular left shift
def md5_rotl(x: t.CUInt32T, n: int) -> t.CUInt32T: return (x << n) | (x >> (32 - n))
def md5_rotl(x: uint32, n: int) -> uint32: return (x << n) | (x >> (32 - n))
# MD5 constant table
md5_T: t.CArray[t.CUInt32T, 64] = [
md5_T: t.CArray[uint32, 64] = [
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
@@ -39,9 +39,9 @@ md5_S: t.CArray[int, 64] = [
# ============================================================
@t.Object
class md5:
state: t.CArray[t.CUInt32T, 4] # 4 32-bit state registers
count: t.CUInt64T # processed bits
buf: t.CArray[t.CUInt8T, MD5_BLOCK_LEN] # Group buffer
state: t.CArray[uint32, 4] # 4 32-bit state registers
count: uint64 # processed bits
buf: t.CArray[uint8, MD5_BLOCK_LEN] # Group buffer
# Initialize MD5 context
def __init__(self):
string.memset(self.buf, 0, MD5_BLOCK_LEN)
@@ -51,34 +51,34 @@ class md5:
self.state[3] = 0x10325476
self.count = 0
# MD5 single-group compression transform
def transform(self, block: t.CUInt8T | t.CPtr):
a: t.CUInt32T = self.state[0]
b: t.CUInt32T = self.state[1]
c: t.CUInt32T = self.state[2]
d: t.CUInt32T = self.state[3]
w: t.CArray[t.CUInt32T, 16]
def transform(self, block: rowptr[uint8]):
a: uint32 = self.state[0]
b: uint32 = self.state[1]
c: uint32 = self.state[2]
d: uint32 = self.state[3]
w: t.CArray[uint32, 16]
# Byte order 32-bit words
for i in range(16):
w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 0) |
(t.CUInt32T(block[i * 4 + 1]) << 8) |
(t.CUInt32T(block[i * 4 + 2]) << 16) |
(t.CUInt32T(block[i * 4 + 3]) << 24))
w[i] = ((uint32(block[i * 4 + 0]) << 0) |
(uint32(block[i * 4 + 1]) << 8) |
(uint32(block[i * 4 + 2]) << 16) |
(uint32(block[i * 4 + 3]) << 24))
# 4-round 51 iterations
for i in range(16):
tmp: t.CUInt32T = md5_F(b, c, d) + a + md5_T[i] + w[i]
tmp: uint32 = md5_F(b, c, d) + a + md5_T[i] + w[i]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
# 4-round 51 iterations
for i in range(16, 32):
tmp: t.CUInt32T = md5_G(b, c, d) + a + md5_T[i] + w[(5 * i + 1) % 16]
tmp: uint32 = md5_G(b, c, d) + a + md5_T[i] + w[(5 * i + 1) % 16]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
for i in range(32, 48):
tmp: t.CUInt32T = md5_H(b, c, d) + a + md5_T[i] + w[(3 * i + 5) % 16]
tmp: uint32 = md5_H(b, c, d) + a + md5_T[i] + w[(3 * i + 5) % 16]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
for i in range(48, 64):
tmp: t.CUInt32T = md5_I(b, c, d) + a + md5_T[i] + w[(7 * i + 0) % 16]
tmp: uint32 = md5_I(b, c, d) + a + md5_T[i] + w[(7 * i + 0) % 16]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
# Accumulate to state registers
@@ -88,7 +88,7 @@ class md5:
self.state[3] += d
# Batch input data
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
data: rowptr[uint8] = uint8(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
self.count += length
@@ -107,7 +107,7 @@ class md5:
if length > 0:
string.memcpy(self.buf + idx, data, length)
# End calculation, output 16-byte digest
def final(self, out: t.CArray[t.CUInt8T, MD5_DIGEST_LEN]):
def final(self, out: t.CArray[uint8, MD5_DIGEST_LEN]):
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
# Pad 0x80 end
self.buf[idx] = 0x80
@@ -120,7 +120,7 @@ class md5:
# Pad 0 to end 8 bytes
string.memset(self.buf + idx, 0, MD5_BLOCK_LEN - 8 - idx)
# Write total bit count
bits: t.CUInt64T = self.count << 3
bits: uint64 = self.count << 3
for i in range(8):
self.buf[MD5_BLOCK_LEN - 8 + i] = (bits >> (i * 8)) & 0xFF
self.transform(self.buf)
+24 -24
View File
@@ -9,18 +9,18 @@ import t, c
SHA1_BLOCK_LEN: t.CDefine = 64
SHA1_DIGEST_LEN: t.CDefine = 20
def sha1_rotl(x: t.CUInt32T, n: int) -> t.CUInt32T: return (x << n) | (x >> (32 - n))
def sha1_rotl(x: uint32, n: int) -> uint32: return (x << n) | (x >> (32 - n))
# 3-round logical functions
def sha1_f1(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (~b & d)
def sha1_f2(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return b ^ c ^ d
def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (b & d) | (c & d)
def sha1_f1(b: uint32, c: uint32, d: uint32) -> uint32: return (b & c) | (~b & d)
def sha1_f2(b: uint32, c: uint32, d: uint32) -> uint32: return b ^ c ^ d
def sha1_f3(b: uint32, c: uint32, d: uint32) -> uint32: return (b & c) | (b & d) | (c & d)
# SHA1 Context
@t.Object
class sha1:
state: t.CArray[t.CUInt32T, 5]
count: t.CUInt64T
buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN]
state: t.CArray[uint32, 5]
count: uint64
buf: t.CArray[uint8, SHA1_BLOCK_LEN]
def __init__(self):
string.memset(self.buf, 0, SHA1_BLOCK_LEN)
self.state[0] = 0x67452301
@@ -30,25 +30,25 @@ class sha1:
self.state[4] = 0xc3d2e1f0
self.count = 0
# Single-group compression transform
def transform(self, block: t.CUInt8T | t.CPtr):
w: t.CArray[t.CUInt32T, 80]
data: t.CUInt8T | t.CPtr = block
def transform(self, block: rowptr[uint8]):
w: t.CArray[uint32, 80]
data: rowptr[uint8] = block
# First 16 words
for i in range(16):
w[i] = (((t.CUInt32T(data[i * 4 + 0])) << 24) |
((t.CUInt32T(data[i * 4 + 1])) << 16) |
((t.CUInt32T(data[i * 4 + 2])) << 8) |
((t.CUInt32T(data[i * 4 + 3])) << 0))
w[i] = (((uint32(data[i * 4 + 0])) << 24) |
((uint32(data[i * 4 + 1])) << 16) |
((uint32(data[i * 4 + 2])) << 8) |
((uint32(data[i * 4 + 3])) << 0))
# Extend to 80 words
for i in range(16, 80):
w[i] = sha1_rotl(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16],1)
a: t.CUInt32T = self.state[0]
b: t.CUInt32T = self.state[1]
c: t.CUInt32T = self.state[2]
d: t.CUInt32T = self.state[3]
e: t.CUInt32T = self.state[4]
k: t.CUInt32T
tmp: t.CUInt32T
a: uint32 = self.state[0]
b: uint32 = self.state[1]
c: uint32 = self.state[2]
d: uint32 = self.state[3]
e: uint32 = self.state[4]
k: uint32
tmp: uint32
# 4-round iterations
for i in range(0, 20):
k = 0x5a827999
@@ -80,7 +80,7 @@ class sha1:
self.state[3] += d
self.state[4] += e
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
data: rowptr[uint8] = uint8(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
self.count += length
@@ -98,7 +98,7 @@ class sha1:
length -= SHA1_BLOCK_LEN
if length > 0:
string.memcpy(self.buf + idx, data, length)
def final(self, out: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]):
def final(self, out: t.CArray[uint8, SHA1_DIGEST_LEN]):
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
self.buf[idx] = 0x80
idx += 1
@@ -107,7 +107,7 @@ class sha1:
self.transform(self.buf)
idx = 0
string.memset(self.buf + idx,0,SHA1_BLOCK_LEN-8-idx)
bits: t.CUInt64T = self.count << 3
bits: uint64 = self.count << 3
# SHA1 big-endian write length
for i in range(8):
self.buf[SHA1_BLOCK_LEN - 8 + i] = (bits >> (56 - i * 8)) & 0xFF
+29 -29
View File
@@ -9,7 +9,7 @@ SHA256_BLOCK_LEN: t.CDefine = 64
SHA256_DIGEST_LEN: t.CDefine = 32
# SHA256 Constants K
sha256_K: t.CArray[t.CUInt32T, 64] = [
sha256_K: t.CArray[uint32, 64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
@@ -21,19 +21,19 @@ sha256_K: t.CArray[t.CUInt32T, 64] = [
]
# SHA256 Auxiliary Functions
def s0(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ ((x >> 3))
def s1(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ ((x >> 10))
def S0(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
def S1(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
def Ch(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & y) ^ (~x & z)
def Maj(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & y) ^ (x & z) ^ (y & z)
def s0(x: uint32) -> uint32: return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ ((x >> 3))
def s1(x: uint32) -> uint32: return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ ((x >> 10))
def S0(x: uint32) -> uint32: return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
def S1(x: uint32) -> uint32: return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
def Ch(x: uint32, y: uint32, z: uint32) -> uint32: return (x & y) ^ (~x & z)
def Maj(x: uint32, y: uint32, z: uint32) -> uint32: return (x & y) ^ (x & z) ^ (y & z)
# SHA256 Context
@t.Object
class sha256:
state: t.CArray[t.CUInt32T, 8]
count: t.CUInt64T
buf: t.CArray[t.CUInt8T, SHA256_BLOCK_LEN]
state: t.CArray[uint32, 8]
count: uint64
buf: t.CArray[uint8, SHA256_BLOCK_LEN]
def __init__(self):
string.memset(self, 0, sha256.__sizeof__())
self.state[0] = 0x6a09e667
@@ -47,26 +47,26 @@ class sha256:
self.count = 0
# string.memset(self.buf, 0, SHA256_BLOCK_LEN)
# SHA256 single-group compression transform
def transform(self, block: t.CUInt8T | t.CPtr):
w: t.CArray[t.CUInt32T, 64]
def transform(self, block: rowptr[uint8]):
w: t.CArray[uint32, 64]
for i in range(16):
w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 24) |
(t.CUInt32T(block[i * 4 + 1]) << 16) |
(t.CUInt32T(block[i * 4 + 2]) << 8 ) |
(t.CUInt32T(block[i * 4 + 3]) << 0 ))
w[i] = ((uint32(block[i * 4 + 0]) << 24) |
(uint32(block[i * 4 + 1]) << 16) |
(uint32(block[i * 4 + 2]) << 8 ) |
(uint32(block[i * 4 + 3]) << 0 ))
# Extend to 64 words
for i in range(16, 64):
w[i] = w[i-16] + s0(w[i-15]) + w[i-7] + s1(w[i-2])
a: t.CUInt32T = self.state[0]
b: t.CUInt32T = self.state[1]
c: t.CUInt32T = self.state[2]
d: t.CUInt32T = self.state[3]
e: t.CUInt32T = self.state[4]
f: t.CUInt32T = self.state[5]
g: t.CUInt32T = self.state[6]
h: t.CUInt32T = self.state[7]
t1: t.CUInt32T
t2: t.CUInt32T
a: uint32 = self.state[0]
b: uint32 = self.state[1]
c: uint32 = self.state[2]
d: uint32 = self.state[3]
e: uint32 = self.state[4]
f: uint32 = self.state[5]
g: uint32 = self.state[6]
h: uint32 = self.state[7]
t1: uint32
t2: uint32
# 64-round iterations
for i in range(64):
t1 = h + S1(e) + Ch(e,f,g) + sha256_K[i] + w[i]
@@ -85,7 +85,7 @@ class sha256:
self.state[6] += g
self.state[7] += h
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
data: rowptr[uint8] = uint8(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
self.count += length
@@ -103,7 +103,7 @@ class sha256:
length -= SHA256_BLOCK_LEN
if length > 0:
string.memcpy(self.buf + idx, data, length)
def final(self, out: t.CArray[t.CUInt8T, SHA256_DIGEST_LEN]):
def final(self, out: t.CArray[uint8, SHA256_DIGEST_LEN]):
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
self.buf[idx] = 0x80
idx += 1
@@ -112,7 +112,7 @@ class sha256:
self.transform(self.buf)
idx = 0
string.memset(self.buf + idx, 0, SHA256_BLOCK_LEN - 8 - idx)
bits: t.CUInt64T = self.count << 3
bits: uint64 = self.count << 3
for i in range(8):
self.buf[SHA256_BLOCK_LEN-8+i] = (bits >> (56 - i*8)) & 0xFF
self.transform(self.buf)
+49 -49
View File
@@ -1,4 +1,4 @@
import t, c
import t, c
import string
@@ -8,16 +8,16 @@ import string
SHA512_BLOCK_LEN: t.CDefine = 128
SHA512_DIGEST_LEN: t.CDefine = 64
def sha512_ror(x: t.CUInt64T, n: int) -> t.CUInt64T: return (x >> n) | (x << (64 - n))
def sha512_shr(x: t.CUInt64T, n: int) -> t.CUInt64T: return x >> n
def sha512_Ch (x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: return (x & y) ^ (~x & z)
def sha512_Maj(x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: return (x & y) ^ (x & z) ^ (y & z)
def sha512_BigSigma0(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 28) ^ sha512_ror(x, 34) ^ sha512_ror(x, 39)
def sha512_BigSigma1(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 14) ^ sha512_ror(x, 18) ^ sha512_ror(x, 41)
def sha512_Sigma0(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 1) ^ sha512_ror(x, 8) ^ sha512_shr(x, 7)
def sha512_Sigma1(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 19) ^ sha512_ror(x, 61) ^ sha512_shr(x, 6)
def sha512_ror(x: uint64, n: int) -> uint64: return (x >> n) | (x << (64 - n))
def sha512_shr(x: uint64, n: int) -> uint64: return x >> n
def sha512_Ch (x: uint64, y: uint64, z: uint64) -> uint64: return (x & y) ^ (~x & z)
def sha512_Maj(x: uint64, y: uint64, z: uint64) -> uint64: return (x & y) ^ (x & z) ^ (y & z)
def sha512_BigSigma0(x: uint64) -> uint64: return sha512_ror(x, 28) ^ sha512_ror(x, 34) ^ sha512_ror(x, 39)
def sha512_BigSigma1(x: uint64) -> uint64: return sha512_ror(x, 14) ^ sha512_ror(x, 18) ^ sha512_ror(x, 41)
def sha512_Sigma0(x: uint64) -> uint64: return sha512_ror(x, 1) ^ sha512_ror(x, 8) ^ sha512_shr(x, 7)
def sha512_Sigma1(x: uint64) -> uint64: return sha512_ror(x, 19) ^ sha512_ror(x, 61) ^ sha512_shr(x, 6)
sha512_K: t.CArray[t.CUInt64T, 80] = [
sha512_K: t.CArray[uint64, 80] = [
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
@@ -42,9 +42,9 @@ sha512_K: t.CArray[t.CUInt64T, 80] = [
@t.Object
class sha512:
state: t.CArray[t.CUInt64T, 8]
count: t.CArray[t.CUInt64T, 2]
buf: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]
state: t.CArray[uint64, 8]
count: t.CArray[uint64, 2]
buf: t.CArray[uint8, SHA512_BLOCK_LEN]
def __init__(self):
string.memset(self, 0, sha512.__sizeof__())
self.state[0] = 0x6a09e667f3bcc908
@@ -55,27 +55,27 @@ class sha512:
self.state[5] = 0x9b05688c2b3e6c1f
self.state[6] = 0x1f83d9abfb41bd6b
self.state[7] = 0x5be0cd19137e2179
def transform(self, block: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]):
w: t.CArray[t.CUInt64T, 80]
a: t.CUInt64T
b: t.CUInt64T
c: t.CUInt64T
d: t.CUInt64T
e: t.CUInt64T
f: t.CUInt64T
g: t.CUInt64T
h: t.CUInt64T
t1: t.CUInt64T
t2: t.CUInt64T
def transform(self, block: t.CArray[uint8, SHA512_BLOCK_LEN]):
w: t.CArray[uint64, 80]
a: uint64
b: uint64
c: uint64
d: uint64
e: uint64
f: uint64
g: uint64
h: uint64
t1: uint64
t2: uint64
for i in range(16):
w[i] = t.CUInt64T(block[i * 8 + 0]) << 56
w[i] |= t.CUInt64T(block[i * 8 + 1]) << 48
w[i] |= t.CUInt64T(block[i * 8 + 2]) << 40
w[i] |= t.CUInt64T(block[i * 8 + 3]) << 32
w[i] |= t.CUInt64T(block[i * 8 + 4]) << 24
w[i] |= t.CUInt64T(block[i * 8 + 5]) << 16
w[i] |= t.CUInt64T(block[i * 8 + 6]) << 8
w[i] |= t.CUInt64T(block[i * 8 + 7]) << 0
w[i] = uint64(block[i * 8 + 0]) << 56
w[i] |= uint64(block[i * 8 + 1]) << 48
w[i] |= uint64(block[i * 8 + 2]) << 40
w[i] |= uint64(block[i * 8 + 3]) << 32
w[i] |= uint64(block[i * 8 + 4]) << 24
w[i] |= uint64(block[i * 8 + 5]) << 16
w[i] |= uint64(block[i * 8 + 6]) << 8
w[i] |= uint64(block[i * 8 + 7]) << 0
for i in range(16, 80):
w[i] = sha512_Sigma1(w[i-2]) + w[i-7] + sha512_Sigma0(w[i-15]) + w[i-16]
a = self.state[0]
@@ -102,9 +102,9 @@ class sha512:
self.state[6] += g
self.state[7] += h
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
data: rowptr[uint8] = uint8(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CUInt32T = t.CUInt32T(self.count[0] % SHA512_BLOCK_LEN)
idx: uint32 = uint32(self.count[0] % SHA512_BLOCK_LEN)
self.count[0] += length
if self.count[0] < length:
self.count[1] += 1
@@ -122,10 +122,10 @@ class sha512:
length -= SHA512_BLOCK_LEN
if length > 0:
string.memcpy(self.buf + idx, data, length)
def final(self, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]):
bits_lo: t.CUInt64T = self.count[0] << 3
bits_hi: t.CUInt64T = (self.count[1] << 3) | (self.count[0] >> 61)
idx: t.CUInt32T = t.CUInt32T(self.count[0] % SHA512_BLOCK_LEN)
def final(self, out: t.CArray[uint8, SHA512_DIGEST_LEN]):
bits_lo: uint64 = self.count[0] << 3
bits_hi: uint64 = (self.count[1] << 3) | (self.count[0] >> 61)
idx: uint32 = uint32(self.count[0] % SHA512_BLOCK_LEN)
self.buf[idx] = 0x80
idx += 1
if idx > SHA512_BLOCK_LEN - 16:
@@ -134,16 +134,16 @@ class sha512:
idx = 0
string.memset(self.buf + idx, 0, SHA512_BLOCK_LEN - 16 - idx)
for i in range(8):
self.buf[SHA512_BLOCK_LEN - 16 + i] = t.CUInt8T(bits_hi >> (56 - i * 8))
self.buf[SHA512_BLOCK_LEN - 16 + i] = uint8(bits_hi >> (56 - i * 8))
for i in range(8):
self.buf[SHA512_BLOCK_LEN - 8 + i] = t.CUInt8T(bits_lo >> (56 - i * 8))
self.buf[SHA512_BLOCK_LEN - 8 + i] = uint8(bits_lo >> (56 - i * 8))
self.transform(self.buf)
for i in range(8):
out[i * 8 + 0] = t.CUInt8T(self.state[i] >> 56)
out[i * 8 + 1] = t.CUInt8T(self.state[i] >> 48)
out[i * 8 + 2] = t.CUInt8T(self.state[i] >> 40)
out[i * 8 + 3] = t.CUInt8T(self.state[i] >> 32)
out[i * 8 + 4] = t.CUInt8T(self.state[i] >> 24)
out[i * 8 + 5] = t.CUInt8T(self.state[i] >> 16)
out[i * 8 + 6] = t.CUInt8T(self.state[i] >> 8)
out[i * 8 + 7] = t.CUInt8T(self.state[i] >> 0)
out[i * 8 + 0] = uint8(self.state[i] >> 56)
out[i * 8 + 1] = uint8(self.state[i] >> 48)
out[i * 8 + 2] = uint8(self.state[i] >> 40)
out[i * 8 + 3] = uint8(self.state[i] >> 32)
out[i * 8 + 4] = uint8(self.state[i] >> 24)
out[i * 8 + 5] = uint8(self.state[i] >> 16)
out[i * 8 + 6] = uint8(self.state[i] >> 8)
out[i * 8 + 7] = uint8(self.state[i] >> 0)
+27 -27
View File
@@ -23,17 +23,17 @@ JSON_OBJECT: t.CDefine = 6
class JsonValue:
vtype: int
bool_val: int
int_val: t.CInt64T
float_val: t.CDouble
int_val: int64
float_val: double
str_val: str
next: 'JsonValue' | t.CPtr
key: str
child: 'JsonValue' | t.CPtr
child_count: t.CSizeT
def __new__(self, pool: memhub.MemManager | t.CPtr):
def __new__(self, pool: rowptr[memhub.MemManager]):
"""从 mpool 分配 JsonValue 结构体内存并零初始化"""
ptr: JsonValue | t.CPtr = pool.alloc(JsonValue.__sizeof__())
ptr: rowptr[JsonValue] = pool.alloc(JsonValue.__sizeof__())
if ptr:
string.memset(ptr, 0, JsonValue.__sizeof__())
return ptr
@@ -65,10 +65,10 @@ class JsonValue:
def as_bool(self) -> bool:
return self.bool_val != 0
def as_int(self) -> t.CInt64T:
def as_int(self) -> int64:
return self.int_val
def as_float(self) -> t.CDouble:
def as_float(self) -> double:
return self.float_val
def as_string(self) -> str:
@@ -83,7 +83,7 @@ class JsonValue:
return None
if key == None:
return None
cur: JsonValue | t.CPtr = self.child
cur: rowptr[JsonValue] = self.child
while cur != None:
if cur.key != None:
if string.strcmp(cur.key, key) == 0:
@@ -95,7 +95,7 @@ class JsonValue:
"""Python风格赋值:v["key"] = val"""
if self.vtype != JSON_OBJECT or key == None or val == None:
return
cur: JsonValue | t.CPtr = self.child
cur: rowptr[JsonValue] = self.child
while cur != None:
if cur.key != None:
if string.strcmp(cur.key, key) == 0:
@@ -120,7 +120,7 @@ class JsonValue:
"""按索引取数组元素:v.get_item(0)"""
if self.vtype != JSON_ARRAY and self.vtype != JSON_OBJECT:
return None
cur: JsonValue | t.CPtr = self.child
cur: rowptr[JsonValue] = self.child
i: t.CSizeT = 0
while cur != None:
if i == index:
@@ -137,7 +137,7 @@ class JsonValue:
if self.child == None:
self.child = child
else:
cur: JsonValue | t.CPtr = self.child
cur: rowptr[JsonValue] = self.child
while cur.next != None:
cur = cur.next
cur.next = child
@@ -148,35 +148,35 @@ class JsonValue:
# 构造函数:创建各类 JsonValue(从 mpool 分配)
# ============================================================
def null(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def null(pool: rowptr[memhub.MemManager]) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_NULL
return v
def bool_val(pool: memhub.MemManager | t.CPtr, val: bool) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def bool_val(pool: rowptr[memhub.MemManager], val: bool) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_BOOL
v.bool_val = 1 if val else 0
return v
def int_val(pool: memhub.MemManager | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def int_val(pool: rowptr[memhub.MemManager], val: int64) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_INT
v.int_val = val
return v
def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def float_val(pool: rowptr[memhub.MemManager], val: double) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_FLOAT
v.float_val = val
return v
def string_val(pool: memhub.MemManager | t.CPtr, val: str) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def string_val(pool: rowptr[memhub.MemManager], val: str) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_STRING
if val != None:
@@ -187,29 +187,29 @@ def string_val(pool: memhub.MemManager | t.CPtr, val: str) -> JsonValue | t.CPtr
v.str_val = buf
return v
def array(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def array(pool: rowptr[memhub.MemManager]) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_ARRAY
return v
def object(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
def object(pool: rowptr[memhub.MemManager]) -> rowptr[JsonValue]:
v: rowptr[JsonValue] = JsonValue(pool)
if v == None: return None
v.vtype = JSON_OBJECT
return v
# 向数组追加元素
def array_append(pool: memhub.MemManager | t.CPtr, arr: JsonValue | t.CPtr, item: JsonValue | t.CPtr):
def array_append(pool: rowptr[memhub.MemManager], arr: rowptr[JsonValue], item: rowptr[JsonValue]):
if arr == None or item == None: return
if arr.vtype != JSON_ARRAY: return
arr._append_child(item)
# 向对象设置键值对
def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: str, val: JsonValue | t.CPtr):
def object_set(pool: rowptr[memhub.MemManager], obj: rowptr[JsonValue], key: str, val: rowptr[JsonValue]):
if obj == None or key == None or val == None: return
if obj.vtype != JSON_OBJECT: return
cur: JsonValue | t.CPtr = obj.child
cur: rowptr[JsonValue] = obj.child
while cur != None:
if cur.key != None:
if string.strcmp(cur.key, key) == 0:
+19 -19
View File
@@ -13,28 +13,28 @@ class ParseState:
src: str
pos: t.CSizeT
len: t.CSizeT
pool: memhub.MemManager | t.CPtr
pool: rowptr[memhub.MemManager]
def __init__(self, src: str, pool: memhub.MemManager | t.CPtr):
def __init__(self, src: str, pool: rowptr[memhub.MemManager]):
self.src = src
self.pos = 0
self.len = string.strlen(src) if src != None else 0
self.pool = pool
def _peek(s: ParseState | t.CPtr) -> t.CChar:
def _peek(s: rowptr[ParseState]) -> t.CChar:
if s.pos >= s.len:
return '\0'
return s.src[s.pos]
def _advance(s: ParseState | t.CPtr) -> t.CChar:
def _advance(s: rowptr[ParseState]) -> t.CChar:
if s.pos >= s.len:
return '\0'
ch: t.CChar = s.src[s.pos]
s.pos += 1
return ch
def _skip_whitespace(s: ParseState | t.CPtr):
def _skip_whitespace(s: rowptr[ParseState]):
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch == ' ' or ch == '\t' or ch == '\n' or ch == '\r':
@@ -42,7 +42,7 @@ def _skip_whitespace(s: ParseState | t.CPtr):
else:
break
def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool:
def _expect(s: rowptr[ParseState], ch: t.CChar) -> bool:
_skip_whitespace(s)
if s.pos >= s.len:
return False
@@ -52,7 +52,7 @@ def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool:
return True
def _parse_string(s: ParseState | t.CPtr) -> str:
def _parse_string(s: rowptr[ParseState]) -> str:
if _peek(s) != '"':
return None
_advance(s)
@@ -109,7 +109,7 @@ def _parse_string(s: ParseState | t.CPtr) -> str:
return buf
def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
def _parse_number(s: rowptr[ParseState]) -> rowptr[JsonValue]:
_skip_whitespace(s)
is_float: bool = False
start: t.CSizeT = s.pos
@@ -158,14 +158,14 @@ def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
buf[num_len] = '\0'
if is_float:
val: t.CDouble = string.atof(buf)
val: double = string.atof(buf)
return float_val(s.pool, val)
else:
ival: t.CInt64T = string.atoll(buf)
ival: int64 = string.atoll(buf)
return int_val(s.pool, ival)
def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
def _parse_value(s: rowptr[ParseState]) -> rowptr[JsonValue]:
_skip_whitespace(s)
if s.pos >= s.len:
return null(s.pool)
@@ -209,18 +209,18 @@ def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
return null(s.pool)
def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
def _parse_array(s: rowptr[ParseState]) -> rowptr[JsonValue]:
if not _expect(s, '['):
return null(s.pool)
arr: JsonValue | t.CPtr = array(s.pool)
arr: rowptr[JsonValue] = array(s.pool)
_skip_whitespace(s)
if s.pos < s.len and _peek(s) == ']':
_advance(s)
return arr
item: JsonValue | t.CPtr = _parse_value(s)
item: rowptr[JsonValue] = _parse_value(s)
arr._append_child(item)
while True:
@@ -237,11 +237,11 @@ def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
return arr
def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
def _parse_object(s: rowptr[ParseState]) -> rowptr[JsonValue]:
if not _expect(s, '{'):
return null(s.pool)
obj: JsonValue | t.CPtr = object(s.pool)
obj: rowptr[JsonValue] = object(s.pool)
_skip_whitespace(s)
if s.pos < s.len and _peek(s) == '}':
@@ -251,7 +251,7 @@ def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
_skip_whitespace(s)
key: str = _parse_string(s)
_expect(s, ':')
val: JsonValue | t.CPtr = _parse_value(s)
val: rowptr[JsonValue] = _parse_value(s)
if key != None and val != None:
klen: t.CSizeT = string.strlen(key)
kbuf: str = s.pool.alloc(klen + 1)
@@ -283,9 +283,9 @@ def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
return obj
def parse(pool: memhub.MemManager | t.CPtr, src: str) -> JsonValue | t.CPtr:
def parse(pool: rowptr[memhub.MemManager], src: str) -> rowptr[JsonValue]:
"""解析 JSON 字符串,返回 JsonValue 树"""
if src == None:
return null(pool)
s: ParseState | t.CPtr = ParseState(src, pool)
s: rowptr[ParseState] = ParseState(src, pool)
return _parse_value(s)
+4 -4
View File
@@ -45,7 +45,7 @@ def _write_string_escaped(buf: str, pos: t.CSizeT, s: str) -> t.CSizeT:
return pos
def _write_value(buf: str, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CSizeT:
def _write_value(buf: str, pos: t.CSizeT, val: rowptr[JsonValue], pool: rowptr[memhub.MemManager]) -> t.CSizeT:
if val == None:
pos = _write_str(buf, pos, "null")
return pos
@@ -79,7 +79,7 @@ def _write_value(buf: str, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.
pos = _write_str(buf, pos, "[]")
return pos
pos = _write_char(buf, pos, '[')
cur: JsonValue | t.CPtr = val.child
cur: rowptr[JsonValue] = val.child
first: bool = True
while cur != None:
if not first:
@@ -94,7 +94,7 @@ def _write_value(buf: str, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.
pos = _write_str(buf, pos, "{}")
return pos
pos = _write_char(buf, pos, '{')
cur2: JsonValue | t.CPtr = val.child
cur2: rowptr[JsonValue] = val.child
first2: bool = True
while cur2 != None:
if not first2:
@@ -109,7 +109,7 @@ def _write_value(buf: str, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.
return pos
def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> str:
def write(pool: rowptr[memhub.MemManager], val: rowptr[JsonValue], pretty: bool) -> str:
"""将 JsonValue 序列化为 JSON 字符串"""
buf: str = pool.alloc(4096)
if buf == None:
+33
View File
@@ -1,5 +1,7 @@
import t, c
from stdint import *
import stdio
import stdlib
# ============================================================
@@ -334,6 +336,37 @@ class GSList[T]:
"""Append node to the end of the list (O(1))."""
if node is None:
return
# [DBGCHAIN] 链完整性护栏(临时诊断,用后移除):抓"第一笔"写坏
self_n: t.CUInt64T = t.CUInt64T(self)
node_n: t.CUInt64T = t.CUInt64T(node)
head_n: t.CUInt64T = 0
if self.Head is not None:
head_n = t.CUInt64T(self.Head)
tail_n: t.CUInt64T = 0
if self.Tail is not None:
tail_n = t.CUInt64T(self.Tail)
if self.Count == 0 and (head_n != 0 or tail_n != 0):
stdio.printf("[DBGCHAIN] 空表但 Head/Tail 非空: self=%llx head=%llx tail=%llx count=%llu node=%llx\n",
self_n, head_n, tail_n, t.CUInt64T(self.Count), node_n)
stdio.fflush(None)
stdlib.exit(1)
if self.Count > 0 and (head_n == 0 or tail_n == 0):
stdio.printf("[DBGCHAIN] 非空表但 Head/Tail 为空: self=%llx head=%llx tail=%llx count=%llu node=%llx\n",
self_n, head_n, tail_n, t.CUInt64T(self.Count), node_n)
stdio.fflush(None)
stdlib.exit(1)
if node_n != 0 and (node_n == head_n or node_n == tail_n):
stdio.printf("[DBGCHAIN] 重复 append 同一节点: self=%llx head=%llx tail=%llx count=%llu node=%llx\n",
self_n, head_n, tail_n, t.CUInt64T(self.Count), node_n)
stdio.fflush(None)
stdlib.exit(1)
if tail_n != 0:
tail_nx: T | t.CPtr = self.Tail.Next
if tail_nx is not None:
stdio.printf("[DBGCHAIN] Tail.Next 非空(尾被写过/双归属): self=%llx tail=%llx tail.Next=%llx count=%llu node=%llx\n",
self_n, tail_n, t.CUInt64T(tail_nx), t.CUInt64T(self.Count), node_n)
stdio.fflush(None)
stdlib.exit(1)
node.Next = None
if self.Head is None:
self.Head = node
+476 -476
View File
File diff suppressed because it is too large. Load diff
+157 -119
View File
@@ -27,7 +27,7 @@ IR_DUMP_CHAIN_LIMIT: t.CDefine = 100000
# ============================================================
@t.NoVTable
class Line(GSListNode[Line]):
Buf: t.CChar | t.CPtr # 行文本(NUL 结尾)
Buf: str # 行文本(NUL 结尾)
Len: t.CSizeT # 文本长度(不含 NUL)
@@ -42,9 +42,9 @@ class Line(GSListNode[Line]):
# ============================================================
@t.NoVTable
class BasicBlock(GSListNode[BasicBlock]):
Name: t.CChar | t.CPtr # 块名(如 "entry"/"if.then")
Lines: GSList[Line] | t.CPtr # 指令行链表容器(Head/Tail/Count)
IsTerminated: t.CInt # 1=已有终止指令(br/ret)
Name: str # 块名(如 "entry"/"if.then")
Lines: rowptr[GSList[Line]] # 指令行链表容器(Head/Tail/Count)
IsTerminated: int # 1=已有终止指令(br/ret)
# ============================================================
@@ -57,9 +57,9 @@ class BasicBlock(GSListNode[BasicBlock]):
# ============================================================
@t.NoVTable
class Param(GSListNode[Param]):
Ty: LLVMType | t.CPtr # 参数类型
Name: t.CChar | t.CPtr # 参数名(如 "%0"/"%a")
Attrs: t.CChar | t.CPtr # 参数属性文本(None=无属性)
Ty: rowptr[LLVMType] # 参数类型
Name: str # 参数名(如 "%0"/"%a")
Attrs: str # 参数属性文本(None=无属性)
# ============================================================
@@ -74,13 +74,15 @@ class Param(GSListNode[Param]):
# ============================================================
@t.NoVTable
class Function(GSListNode[Function]):
Name: t.CChar | t.CPtr # 函数名
RetTy: LLVMType | t.CPtr # 返回类型
Params: GSList[Param] | t.CPtr # 参数链表容器
Blocks: GSList[BasicBlock] | t.CPtr # 基本块链表容器
IsDeclared: t.CInt # 1=仅声明(declare), 0=定义(define)
IsVarArg: t.CInt # 1=变参函数(...)
Attrs: t.CChar | t.CPtr # 函数属性文本(None=无属性)
Name: str # 函数名
RetTy: rowptr[LLVMType] # 返回类型
Params: rowptr[GSList[Param]] # 参数链表容器
Blocks: rowptr[GSList[BasicBlock]] # 基本块链表容器
IsDeclared: int # 1=仅声明(declare), 0=定义(define)
IsVarArg: int # 1=变参函数(...)
Attrs: str # 函数属性文本(None=无属性)
AttrGroup: str # 字符串属性组内容(如 '"section"=".text.startup"',None=无)
AttrGroupId: int # 属性组编号(>0 时函数行输出 #N,模块尾输出 attributes #N)
# ============================================================
@@ -89,14 +91,14 @@ class Function(GSListNode[Function]):
# Line 硬编码大小: Next(8) + Buf(8) + Len(8) = 24 字节
LINE_SIZE: t.CDefine = 24
def new_line(pool: memhub.MemBuddy | t.CPtr, text: t.CChar | t.CPtr) -> Line | t.CPtr:
def new_line(pool: rowptr[memhub.MemBuddy], text: str) -> rowptr[Line]:
"""创建一个指令行,复制 text 到新分配的缓冲区"""
ptr: Line | t.CPtr = pool.alloc(LINE_SIZE)
ptr: rowptr[Line] = pool.alloc(LINE_SIZE)
if ptr is None: return None
string.memset(ptr, 0, LINE_SIZE)
if text is not None:
slen: t.CSizeT = string.strlen(text)
buf: t.CChar | t.CPtr = pool.alloc(slen + 1)
buf: str = pool.alloc(slen + 1)
if buf is not None:
string.strcpy(buf, text)
ptr.Buf = buf
@@ -104,7 +106,7 @@ def new_line(pool: memhub.MemBuddy | t.CPtr, text: t.CChar | t.CPtr) -> Line | t
return ptr
def _new_gslist(pool: memhub.MemBuddy | t.CPtr, list_size: t.CSizeT) -> t.CPtr:
def _new_gslist(pool: rowptr[memhub.MemBuddy], list_size: t.CSizeT) -> t.CPtr:
"""从 pool 分配并零初始化一个 GSList 容器(Head/Tail/Count 全零)"""
gsl: t.CPtr = pool.alloc(list_size)
if gsl is None: return None
@@ -115,9 +117,9 @@ def _new_gslist(pool: memhub.MemBuddy | t.CPtr, list_size: t.CSizeT) -> t.CPtr:
# BasicBlock 硬编码大小: Next(8) + Name(8) + Lines(8) + IsTerminated(4) = 32 字节
BLOCK_SIZE: t.CDefine = 32
def new_basic_block(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
def new_basic_block(pool: rowptr[memhub.MemBuddy], name: str) -> rowptr[BasicBlock]:
"""创建一个基本块"""
ptr: BasicBlock | t.CPtr = pool.alloc(BLOCK_SIZE)
ptr: rowptr[BasicBlock] = pool.alloc(BLOCK_SIZE)
if ptr is None: return None
string.memset(ptr, 0, BLOCK_SIZE)
ptr.Name = name
@@ -129,10 +131,10 @@ def new_basic_block(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> B
# Param 硬编码大小: Next(8) + Ty(8) + Name(8) + Attrs(8) = 32 字节
PARAM_SIZE: t.CDefine = 32
def new_param(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Param | t.CPtr:
def new_param(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
name: str) -> rowptr[Param]:
"""创建一个函数参数"""
ptr: Param | t.CPtr = pool.alloc(PARAM_SIZE)
ptr: rowptr[Param] = pool.alloc(PARAM_SIZE)
if ptr is None: return None
string.memset(ptr, 0, PARAM_SIZE)
ptr.Ty = ty
@@ -141,13 +143,13 @@ def new_param(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
return ptr
# Function 硬编码大小: Next(8) + Name(8) + RetTy(8) + Params(8) + Blocks(8) + IsDeclared(4) + IsVarArg(4) + Attrs(8) = 56 字节
FUNC_SIZE: t.CDefine = 56
# Function 硬编码大小: Next(8) + Name(8) + RetTy(8) + Params(8) + Blocks(8) + IsDeclared(4) + IsVarArg(4) + Attrs(8) + AttrGroup(8) + AttrGroupId(8) = 72 字节
FUNC_SIZE: t.CDefine = 72
def new_function(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr,
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
def new_function(pool: rowptr[memhub.MemBuddy], name: str,
ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
"""创建一个函数"""
ptr: Function | t.CPtr = pool.alloc(FUNC_SIZE)
ptr: rowptr[Function] = pool.alloc(FUNC_SIZE)
if ptr is None: return None
string.memset(ptr, 0, FUNC_SIZE)
ptr.Name = name
@@ -156,32 +158,34 @@ def new_function(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr,
ptr.Blocks = _new_gslist(pool, 24)
ptr.IsDeclared = 0
ptr.Attrs = None
ptr.AttrGroup = None
ptr.AttrGroupId = 0
return ptr
# ============================================================
# 链表操作(委托 GSList.append)
# ============================================================
def function_add_param(func: Function | t.CPtr, param: Param | t.CPtr):
def function_add_param(func: rowptr[Function], param: rowptr[Param]):
"""将参数追加到函数参数链表"""
if func is None or param is None: return
# 注意:必须先用局部变量 + 类型参数(对齐 function_move_block_to_end 注释),
# 链式 func.Params.append() 会被编译器解析成 LinkedNode.append 且 this 前移
# sizeof(LinkedNode)(兄弟 Mixin 兜底误匹配),写穿容器前 48 字节破坏数据结构。
params: GSList[Param] | t.CPtr = func.Params
params: rowptr[GSList[Param]] = func.Params
if params is None: return
params.append(param)
def function_add_block(func: Function | t.CPtr, block: BasicBlock | t.CPtr):
def function_add_block(func: rowptr[Function], block: rowptr[BasicBlock]):
"""将基本块追加到函数块链表"""
if func is None or block is None: return
blocks: GSList[BasicBlock] | t.CPtr = func.Blocks
blocks: rowptr[GSList[BasicBlock]] = func.Blocks
if blocks is None: return
blocks.append(block)
def function_move_block_to_end(func: Function | t.CPtr, block: BasicBlock | t.CPtr):
def function_move_block_to_end(func: rowptr[Function], block: rowptr[BasicBlock]):
"""将 block 移动到函数块链表末尾(保证 BB 文本顺序与控制流顺序一致)。
用于解决 SSA 名非单调问题:BB 按创建顺序排列,但指令按控制流顺序生成,
@@ -192,7 +196,7 @@ def function_move_block_to_end(func: Function | t.CPtr, block: BasicBlock | t.CP
struct 类型,导致 blocks.Head/Tail/Count 字段访问读取垃圾值。
"""
if func is None or block is None: return
blocks: GSList[BasicBlock] | t.CPtr = func.Blocks
blocks: rowptr[GSList[BasicBlock]] = func.Blocks
if blocks is None: return
# 已经是 Tail,无需移动
@@ -205,7 +209,7 @@ def function_move_block_to_end(func: Function | t.CPtr, block: BasicBlock | t.CP
blocks.Head = block.Next
else:
# 遍历找前驱
prev: BasicBlock | t.CPtr = blocks.Head
prev: rowptr[BasicBlock] = blocks.Head
while prev is not None and prev.Next is not block:
prev = prev.Next
if prev is None:
@@ -223,39 +227,39 @@ def function_move_block_to_end(func: Function | t.CPtr, block: BasicBlock | t.CP
blocks.Tail = block
def block_append_line(block: BasicBlock | t.CPtr, line: Line | t.CPtr):
def block_append_line(block: rowptr[BasicBlock], line: rowptr[Line]):
"""将指令行追加到基本块"""
if block is None or line is None: return
lines: GSList[Line] | t.CPtr = block.Lines
lines: rowptr[GSList[Line]] = block.Lines
if lines is None: return
lines.append(line)
def block_set_terminated(block: BasicBlock | t.CPtr, val: t.CInt):
def block_set_terminated(block: rowptr[BasicBlock], val: int):
"""设置块的终止标志(供跨模块调用,避免链式属性访问的 opaque 类型问题)"""
if block is None: return
block.IsTerminated = val
def block_get_terminated(block: BasicBlock | t.CPtr) -> t.CInt:
def block_get_terminated(block: rowptr[BasicBlock]) -> int:
"""获取块的终止标志(供跨模块调用,避免链式属性访问的 opaque 类型问题)"""
if block is None:
return 1
return block.IsTerminated
def block_append_text(pool: memhub.MemBuddy | t.CPtr, block: BasicBlock | t.CPtr,
text: t.CChar | t.CPtr):
def block_append_text(pool: rowptr[memhub.MemBuddy], block: rowptr[BasicBlock],
text: str):
"""创建指令行并追加到基本块"""
if block is None or text is None: return
line: Line | t.CPtr = new_line(pool, text)
line: rowptr[Line] = new_line(pool, text)
if line is not None:
block_append_line(block, line)
def block_insert_text_before_terminator(pool: memhub.MemBuddy | t.CPtr,
block: BasicBlock | t.CPtr,
text: t.CChar | t.CPtr):
def block_insert_text_before_terminator(pool: rowptr[memhub.MemBuddy],
block: rowptr[BasicBlock],
text: str):
"""创建指令行并插入到基本块终止指令之前
如果块未终止,追加到末尾。
@@ -264,14 +268,14 @@ def block_insert_text_before_terminator(pool: memhub.MemBuddy | t.CPtr,
"""
if block is None or text is None: return
if block.Lines is None: return
line: Line | t.CPtr = new_line(pool, text)
line: rowptr[Line] = new_line(pool, text)
if line is None: return
# 块未终止:直接追加
if block.IsTerminated == 0:
block_append_line(block, line)
return
# 块已终止:在 Tail(终止指令)之前插入
lines: GSList[Line] | t.CPtr = block.Lines
lines: rowptr[GSList[Line]] = block.Lines
if lines.Head is None:
block_append_line(block, line)
return
@@ -282,7 +286,7 @@ def block_insert_text_before_terminator(pool: memhub.MemBuddy | t.CPtr,
lines.Count += 1
return
# 找到 Tail 的前驱节点
prev: Line | t.CPtr = lines.Head
prev: rowptr[Line] = lines.Head
while prev is not None and prev.Next is not lines.Tail:
prev = prev.Next
if prev is None:
@@ -298,18 +302,29 @@ def block_insert_text_before_terminator(pool: memhub.MemBuddy | t.CPtr,
# ============================================================
# 属性设置
# ============================================================
def function_set_attrs(func: Function | t.CPtr, attrs: t.CChar | t.CPtr):
def function_set_attrs(func: rowptr[Function], attrs: str):
"""设置函数级属性文本(如 "nounwind"/"noinline")"""
if func is None: return
# [ATTR-DIAG] 确认 function_set_attrs 是否被调用及传入内容
if attrs is not None:
stdio.printf("[ATTR] function_set_attrs: func='%s' attrs='%s'\n", func.Name, attrs)
else:
stdio.printf("[ATTR] function_set_attrs: func='%s' attrs=None\n", func.Name)
func.Attrs = attrs
def param_set_attrs(param: Param | t.CPtr, attrs: t.CChar | t.CPtr):
_g_attr_group_counter: int = 0
def function_set_attr_group(func: rowptr[Function], group: str):
"""设置函数字符串属性组(如 '"section"=".text.startup"')并分配组编号 #N。
LLVM 字符串属性(带值的,如 section)不能内联在函数签名行,
必须用属性组:函数行输出 #N,组定义输出在函数尾。
"""
global _g_attr_group_counter
if func is None or group is None:
return
func.AttrGroup = group
_g_attr_group_counter += 1
func.AttrGroupId = _g_attr_group_counter
def param_set_attrs(param: rowptr[Param], attrs: str):
"""设置参数属性文本(如 "noundef"/"nocapture"/"readonly")"""
if param is None: return
param.Attrs = attrs
@@ -324,7 +339,7 @@ def param_set_attrs(param: Param | t.CPtr, attrs: t.CChar | t.CPtr):
# SHA1 命名空间的函数名(如 "4dad2ba72ed7ba09.GSListNode[Param]")含 '['、']',
# 需要加引号;但纯 hex+点 的名字(如 "abc.def")不需要。
# ============================================================
def _ll_name_needs_quote(name: str) -> t.CInt:
def _ll_name_needs_quote(name: str) -> int:
"""检查 LLVM 标识符是否需要加引号(以数字开头或含非合法字符)
LLVM IR 合法字符:a-z, A-Z, 0-9, -, $, ., _
@@ -373,7 +388,7 @@ def _ll_name_needs_quote(name: str) -> t.CInt:
# ============================================================
# 判定字符是否为十进制数字
def _is_digit_ch(ch: t.CChar) -> t.CInt:
def _is_digit_ch(ch: t.CChar) -> int:
"""判断字符是否是 '0'-'9'
ch 是值类型 (t.CChar = i8),TPC 已修复值类型 is None 处理:
@@ -393,56 +408,56 @@ def _is_digit_ch(ch: t.CChar) -> t.CInt:
# 导致内存损坏。必须显式计算字节偏移:addr = base + idx * 4,再转型为 i32*。
# 参见 HandlesTranslator.py:358 的 t.CUInt64T(ptr) + offset * sizeof 用法。
# ============================================================
def _map_get_i32(map_arr: t.CChar | t.CPtr, idx: t.CInt) -> t.CInt:
def _map_get_i32(map_arr: str, idx: int) -> int:
"""读取 i32 数组 map_arr[idx](显式字节偏移 idx*4)
使用 (t.CInt | t.CPtr)(uint64) 强转将字节偏移转为 i32*,再用 c.Deref 解引用。
使用 (rowptr[int])(uint64) 强转将字节偏移转为 i32*,再用 c.Deref 解引用。
TPC 已修复类型联合强转(_HandleTypeUnionCastLlvm 添加 fallback),此写法可用。
"""
if map_arr is None:
return -1
byte_off: t.CUInt64T = t.CUInt64T(map_arr) + idx * 4
elem_ptr: t.CInt | t.CPtr = (t.CInt | t.CPtr)(byte_off)
elem_ptr: rowptr[int] = (rowptr[int])(byte_off)
return c.Deref(elem_ptr)
def _map_set_i32(map_arr: t.CChar | t.CPtr, idx: t.CInt, val: t.CInt):
def _map_set_i32(map_arr: str, idx: int, val: int):
"""写入 map_arr[idx] = val(i32 数组,显式字节偏移 idx*4)
使用 (t.CInt | t.CPtr)(uint64) 强转 + c.DerefAs 解引用赋值。
使用 (rowptr[int])(uint64) 强转 + c.DerefAs 解引用赋值。
TPC 已修复类型联合强转,此写法可用。
"""
if map_arr is None:
return
byte_off: t.CUInt64T = t.CUInt64T(map_arr) + idx * 4
elem_ptr: t.CInt | t.CPtr = (t.CInt | t.CPtr)(byte_off)
elem_ptr: rowptr[int] = (rowptr[int])(byte_off)
c.DerefAs(elem_ptr, val)
def _scan_max_ssa_in_text(text: t.CChar | t.CPtr, cur_max: t.CInt) -> t.CInt:
def _scan_max_ssa_in_text(text: str, cur_max: int) -> int:
"""扫描文本,找出 %N(N 为数字)中最大的 N,与 cur_max 比较返回更大值
仅匹配 '%' 后紧跟数字的情况,跳过命名 SSA 名(%entry 等)。
"""
result: t.CInt = cur_max
p: t.CChar | t.CPtr = text
result: int = cur_max
p: str = text
while p is not None and p[0] != '\0':
if p[0] == '%':
nxt: t.CChar | t.CPtr = p + 1
nxt: str = p + 1
if nxt is not None and _is_digit_ch(nxt[0]) != 0:
num: t.CInt = string.atoi(nxt)
num: int = string.atoi(nxt)
if num > result:
result = num
p = p + 1
return result
def _find_max_ssa_number(func: Function | t.CPtr) -> t.CInt:
def _find_max_ssa_number(func: rowptr[Function]) -> int:
"""遍历所有 BB 指令行,找出最大的 %N 数字;无数字 SSA 名返回 -1"""
max_n: t.CInt = -1
max_n: int = -1
if func is None or func.Blocks is None:
return max_n
blk: BasicBlock | t.CPtr = func.Blocks.Head
blk: rowptr[BasicBlock] = func.Blocks.Head
blk_steps: t.CSizeT = 0
while blk is not None:
blk_steps += 1
@@ -450,7 +465,7 @@ def _find_max_ssa_number(func: Function | t.CPtr) -> t.CInt:
stdio.printf("[IR-DUMP] 链表成环: func blocks(函数名=%s,ssa 扫描终止)\n", func.Name)
stdlib.exit(1)
if blk.Lines is not None:
line: Line | t.CPtr = blk.Lines.Head
line: rowptr[Line] = blk.Lines.Head
line_steps: t.CSizeT = 0
while line is not None:
line_steps += 1
@@ -465,20 +480,20 @@ def _find_max_ssa_number(func: Function | t.CPtr) -> t.CInt:
return max_n
def _assign_new_numbers(text: t.CChar | t.CPtr,
map_arr: t.CChar | t.CPtr,
max_n: t.CInt, next_new: t.CInt) -> t.CInt:
def _assign_new_numbers(text: str,
map_arr: str,
max_n: int, next_new: int) -> int:
"""扫描文本,对每个 %N(数字),若 map_arr[N]==-1 则分配 next_new
返回更新后的 next_new。按文本首次出现顺序建立映射。
"""
result: t.CInt = next_new
p: t.CChar | t.CPtr = text
result: int = next_new
p: str = text
while p is not None and p[0] != '\0':
if p[0] == '%':
nxt: t.CChar | t.CPtr = p + 1
nxt: str = p + 1
if nxt is not None and _is_digit_ch(nxt[0]) != 0:
num: t.CInt = string.atoi(nxt)
num: int = string.atoi(nxt)
if num >= 0 and num <= max_n:
if _map_get_i32(map_arr, num) == -1:
_map_set_i32(map_arr, num, result)
@@ -487,10 +502,10 @@ def _assign_new_numbers(text: t.CChar | t.CPtr,
return result
def _replace_ssa_numbers(text: t.CChar | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
map_arr: t.CChar | t.CPtr,
max_n: t.CInt) -> t.CChar | t.CPtr:
def _replace_ssa_numbers(text: str,
pool: rowptr[memhub.MemBuddy],
map_arr: str,
max_n: int) -> str:
"""构建新文本,将 %N 替换为映射后的新编号
逐字符扫描:遇到 %N(数字)查映射表替换,其他字符原样复制。
@@ -499,29 +514,29 @@ def _replace_ssa_numbers(text: t.CChar | t.CPtr,
src_len: t.CSizeT = string.strlen(text)
# 新缓冲区:最坏情况每个数字变长(位数增加),分配 src_len*2 + 64
new_size: t.CSizeT = src_len * 2 + 64
new_buf: t.CChar | t.CPtr = pool.alloc(new_size)
new_buf: str = pool.alloc(new_size)
if new_buf is None:
return None
# 一次性分配数字缓冲区(循环中复用)
num_buf: t.CChar | t.CPtr = pool.alloc(16)
num_buf: str = pool.alloc(16)
if num_buf is None:
new_buf[0] = '\0'
return new_buf
dst_idx: t.CSizeT = 0
src_p: t.CChar | t.CPtr = text
src_p: str = text
while src_p is not None and src_p[0] != '\0':
if dst_idx + 16 >= new_size:
# 缓冲区不足,截断
break
if src_p[0] == '%':
nxt: t.CChar | t.CPtr = src_p + 1
nxt: str = src_p + 1
if nxt is not None and _is_digit_ch(nxt[0]) != 0:
num: t.CInt = string.atoi(nxt)
num: int = string.atoi(nxt)
# 先做范围检查再读 map_arr:num 超 max_n 时 map_arr 只有
# (max_n+1)*4 字节,先读后查会越界读远端内存
if num >= 0 and num <= max_n:
new_num: t.CInt = _map_get_i32(map_arr, num)
new_num: int = _map_get_i32(map_arr, num)
if new_num != -1:
# 写入 '%'
new_buf[dst_idx] = '%'
@@ -548,7 +563,7 @@ def _replace_ssa_numbers(text: t.CChar | t.CPtr,
return new_buf
def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
def RenumberSSA(func: rowptr[Function], pool: rowptr[memhub.MemBuddy]):
"""重编号函数内所有数字 SSA 名,确保按文本输出顺序单调递增
在 FunctionPrint 序列化函数体之前调用。
@@ -562,7 +577,7 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
return
# 1. 第一遍扫描:找出最大 SSA 编号
max_n: t.CInt = _find_max_ssa_number(func)
max_n: int = _find_max_ssa_number(func)
if max_n < 0:
return # 无数字 SSA 名
@@ -570,15 +585,15 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
# 用 i8* 存储(pool.alloc 返回 i8*),通过 _map_get_i32/_map_set_i32 访问。
# 初始化为 -1:每个 i32 元素 4 字节,0xFFFFFFFF = -1(有符号 i32)。
# 用 memset 一次性填充,避免循环内 ptr[i] 指针索引问题。
map_bytes: t.CSizeT = (max_n + 1) * 4 # t.CInt = 4 字节
map_arr: t.CChar | t.CPtr = pool.alloc(map_bytes)
map_bytes: t.CSizeT = (max_n + 1) * 4 # int = 4 字节
map_arr: str = pool.alloc(map_bytes)
if map_arr is None:
return
string.memset(map_arr, 0xFF, map_bytes) # 0xFF * 4 = 0xFFFFFFFF = -1
# 3. 第二遍扫描:按文本顺序分配新编号
next_new: t.CInt = 0
blk: BasicBlock | t.CPtr = func.Blocks.Head
next_new: int = 0
blk: rowptr[BasicBlock] = func.Blocks.Head
blk_steps: t.CSizeT = 0
while blk is not None:
blk_steps += 1
@@ -586,7 +601,7 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
stdio.printf("[IR-DUMP] 链表成环: func blocks(函数名=%s,ssa 重编号终止)\n", func.Name)
stdlib.exit(1)
if blk.Lines is not None:
line: Line | t.CPtr = blk.Lines.Head
line: rowptr[Line] = blk.Lines.Head
line_steps: t.CSizeT = 0
while line is not None:
line_steps += 1
@@ -600,10 +615,10 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
blk = blk.Next
# 4. 检查是否有需要重编号的(old != new)
need_renumber: t.CInt = 0
i: t.CInt = 0
need_renumber: int = 0
i: int = 0
while i <= max_n:
v: t.CInt = _map_get_i32(map_arr, i)
v: int = _map_get_i32(map_arr, i)
if v != -1 and v != i:
need_renumber = 1
break
@@ -620,7 +635,7 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
stdio.printf("[IR-DUMP] 链表成环: func blocks(函数名=%s,ssa 替换终止)\n", func.Name)
stdlib.exit(1)
if blk.Lines is not None:
line: Line | t.CPtr = blk.Lines.Head
line: rowptr[Line] = blk.Lines.Head
line_steps = 0
while line is not None:
line_steps += 1
@@ -629,7 +644,7 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
func.Name, blk.Name)
stdlib.exit(1)
if line.Buf is not None:
new_buf: t.CChar | t.CPtr = _replace_ssa_numbers(
new_buf: str = _replace_ssa_numbers(
line.Buf, pool, map_arr, max_n)
if new_buf is not None:
line.Buf = new_buf
@@ -650,8 +665,8 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
# <instruction>
# }
# ============================================================
def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
def FunctionPrint(buf: str, size: t.CSizeT,
func: rowptr[Function], pool: rowptr[memhub.MemBuddy]):
"""将函数 func 序列化为 IR 文本写入 buf"""
if func is None or buf is None or size == 0: return
@@ -661,7 +676,7 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
# RenumberSSA 内部会跳过 declare 函数(IsDeclared==1),无需在此判断。
RenumberSSA(func, pool)
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
ty_buf: str = pool.alloc(128)
if ty_buf is None: return
ty_buf[0] = '\0'
@@ -690,10 +705,10 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, "(")
# 参数列表(从 GSList[Param].Head 遍历)
cur: Param | t.CPtr = None
cur: rowptr[Param] = None
if func.Params is not None:
cur = func.Params.Head
first: t.CInt = 1
first: int = 1
cur_steps: t.CSizeT = 0
while cur is not None:
cur_steps += 1
@@ -735,15 +750,23 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
if func.Attrs is not None:
_append_cstr(buf, size, " ")
_append_cstr(buf, size, func.Attrs)
# B5:字符串属性(section 等)必须用属性组 #N 引用(LLVM 不接受内联
# section="..."),函数行输出 #N,组定义在函数尾/模块中输出。
if func.AttrGroup is not None and func.AttrGroupId > 0:
ag_ref: str = pool.alloc(32)
if ag_ref is not None:
viperlib.snprintf(ag_ref, 32, " #%d", func.AttrGroupId)
_append_cstr(buf, size, ag_ref)
if func.IsDeclared == 1:
_append_cstr(buf, size, "\n")
_append_attr_group_def(buf, size, pool, func)
return
# 函数体
_append_cstr(buf, size, " {\n")
blk: BasicBlock | t.CPtr = None
blk: rowptr[BasicBlock] = None
if func.Blocks is not None:
blk = func.Blocks.Head
blk_steps: t.CSizeT = 0
@@ -757,10 +780,10 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, blk.Name)
_append_cstr(buf, size, ":\n")
# 指令行(从 GSList[Line].Head 遍历)
line: Line | t.CPtr = None
line: rowptr[Line] = None
if blk.Lines is not None:
line = blk.Lines.Head
has_lines: t.CInt = 0
has_lines: int = 0
line_steps: t.CSizeT = 0
while line is not None:
line_steps += 1
@@ -785,6 +808,21 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
blk = blk.Next
_append_cstr(buf, size, "}\n")
_append_attr_group_def(buf, size, pool, func)
def _append_attr_group_def(buf: str, size: t.CSizeT,
pool: rowptr[memhub.MemBuddy],
func: rowptr[Function]):
"""输出字符串属性组定义: attributes #N = { "section"="..." }"""
if func is None or func.AttrGroup is None or func.AttrGroupId <= 0:
return
ag_buf: str = pool.alloc(192)
if ag_buf is None:
return
viperlib.snprintf(ag_buf, 192, "attributes #%d = { %s }\n",
func.AttrGroupId, func.AttrGroup)
_append_cstr(buf, size, ag_buf)
# ============================================================
@@ -796,7 +834,7 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
_g_last_dst: t.CUInt64T = 0
_g_last_pos: t.CSizeT = 0
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
def _append_cstr(dst: str, dst_size: t.CSizeT, src: str):
"""将 C 字符串 src 追加到 dst 末尾"""
global _g_last_dst, _g_last_pos
if dst is None or src is None: return
@@ -834,28 +872,28 @@ def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPt
# 这些访问器在拥有完整类型定义的本模块内执行,能正确访问
# 所有字段。其他模块通过函数调用获取字段值,绕过 stub 限制。
# ============================================================
def function_get_name(func: Function | t.CPtr) -> t.CChar | t.CPtr:
def function_get_name(func: rowptr[Function]) -> str:
"""获取函数名"""
if func is None:
return None
return func.Name
def function_get_ret_ty(func: Function | t.CPtr) -> LLVMType | t.CPtr:
def function_get_ret_ty(func: rowptr[Function]) -> rowptr[LLVMType]:
"""获取函数返回类型"""
if func is None:
return None
return func.RetTy
def function_get_params(func: Function | t.CPtr) -> GSList[Param] | t.CPtr:
def function_get_params(func: rowptr[Function]) -> rowptr[GSList[Param]]:
"""获取函数参数链表容器"""
if func is None:
return None
return func.Params
def function_get_param_head(func: Function | t.CPtr) -> Param | t.CPtr:
def function_get_param_head(func: rowptr[Function]) -> rowptr[Param]:
"""获取函数参数链表头节点(一步到位,避免调用方访问 GSList.Head)"""
if func is None:
return None
@@ -864,35 +902,35 @@ def function_get_param_head(func: Function | t.CPtr) -> Param | t.CPtr:
return func.Params.Head
def function_get_next(func: Function | t.CPtr) -> Function | t.CPtr:
def function_get_next(func: rowptr[Function]) -> rowptr[Function]:
"""获取链表下一个函数"""
if func is None:
return None
return func.Next
def function_is_declared(func: Function | t.CPtr) -> t.CInt:
def function_is_declared(func: rowptr[Function]) -> int:
"""获取函数是否为声明(1=declare 仅声明, 0=define 定义)"""
if func is None:
return 0
return func.IsDeclared
def param_get_name(param: Param | t.CPtr) -> t.CChar | t.CPtr:
def param_get_name(param: rowptr[Param]) -> str:
"""获取参数名"""
if param is None:
return None
return param.Name
def param_get_ty(param: Param | t.CPtr) -> LLVMType | t.CPtr:
def param_get_ty(param: rowptr[Param]) -> rowptr[LLVMType]:
"""获取参数类型"""
if param is None:
return None
return param.Ty
def param_get_next(param: Param | t.CPtr) -> Param | t.CPtr:
def param_get_next(param: rowptr[Param]) -> rowptr[Param]:
"""获取链表下一个参数"""
if param is None:
return None
+88 -86
View File
@@ -25,6 +25,7 @@ from .__function import (
function_add_param, function_add_block,
block_append_line, block_append_text,
function_set_attrs, param_set_attrs,
function_set_attr_group,
function_get_name, function_get_ret_ty, function_get_params,
function_get_param_head, function_get_next, function_is_declared,
param_get_name, param_get_ty, param_get_next,
@@ -33,6 +34,7 @@ from .__function import (
from .__module import (
LLVMModule, GlobalVariable, NamedTypeNode, new_module, new_global_variable,
module_add_function, module_add_global, module_add_named_type,
module_set_named_type_packed,
module_set_target, module_set_datalayout,
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT,
@@ -77,11 +79,11 @@ from .__verify import (
# ============================================================
# 便捷工厂: 字符串复制
# ============================================================
def _str_dup(pool: memhub.MemBuddy | t.CPtr, src: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
def _str_dup(pool: rowptr[memhub.MemBuddy], src: str) -> str:
"""从 pool 分配并复制一个 C 字符串"""
if src is None: return None
slen: t.CSizeT = string.strlen(src)
buf: t.CChar | t.CPtr = pool.alloc(slen + 1)
buf: str = pool.alloc(slen + 1)
if buf is None: return None
string.strcpy(buf, src)
return buf
@@ -90,14 +92,14 @@ def _str_dup(pool: memhub.MemBuddy | t.CPtr, src: t.CChar | t.CPtr) -> t.CChar |
# ============================================================
# 便捷工厂: 创建带名称的基本块
# ============================================================
def create_block(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
def create_block(pool: rowptr[memhub.MemBuddy], func: rowptr[Function],
name: str) -> rowptr[BasicBlock]:
"""创建基本块并添加到函数"""
# 块名与函数参数值名冲突防护:LLVM 中块标签 "entry:" 即值 %entry,
# 与参数 %entry 重名 → llc "unable to create block named 'entry'"
# (CallGenCall._field_byte_offset(self, pool, entry, ...) 根因)。
# 冲突时追加 .1/.2/... 后缀去重(Param.Name 可能带 % 前缀,剥离比较)。
use_name: t.CChar | t.CPtr = name
use_name: str = name
if func is not None and func.Params is not None and name is not None \
and name[0] != '\0':
cb_len: t.CSizeT = string.strlen(name) + 16
@@ -107,7 +109,7 @@ def create_block(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
cb_collide: int = 1
while cb_collide != 0:
cb_collide = 0
cb_p: Param | t.CPtr = function_get_param_head(func)
cb_p: rowptr[Param] = function_get_param_head(func)
while cb_p is not None:
cb_pnm: str = param_get_name(cb_p)
if cb_pnm is not None:
@@ -122,8 +124,8 @@ def create_block(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
viperlib.snprintf(cb_buf, cb_len, "%s.%d", name, cb_k)
use_name = cb_buf
cb_k += 1
name_dup: t.CChar | t.CPtr = _str_dup(pool, use_name)
blk: BasicBlock | t.CPtr = new_basic_block(pool, name_dup)
name_dup: str = _str_dup(pool, use_name)
blk: rowptr[BasicBlock] = new_basic_block(pool, name_dup)
if blk is not None:
function_add_block(func, blk)
return blk
@@ -132,8 +134,8 @@ def create_block(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
# ============================================================
# 便捷工厂: 创建整数常量值
# ============================================================
def const_int(pool: memhub.MemBuddy | t.CPtr, bits: t.CInt,
val: t.CInt64T) -> Value | t.CPtr:
def const_int(pool: rowptr[memhub.MemBuddy], bits: int,
val: int64) -> rowptr[Value]:
"""创建整数常量值(自动创建类型 + 名字文本)
参数:
@@ -141,13 +143,13 @@ def const_int(pool: memhub.MemBuddy | t.CPtr, bits: t.CInt,
val: 整数值
"""
# 创建类型
ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
ty: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__())
c.DerefAs(ty, LLVMType.Int(bits))
# 创建名字文本
name: t.CChar | t.CPtr = pool.alloc(32)
name: str = pool.alloc(32)
if name is None: return None
# LLVM i64 字面量范围不含 INT64_MIN(-9223372036854775808):该值必须
# 用无符号位模式 9223372036854775808 表示(LLVM 接受),否则 opt 解析
@@ -161,12 +163,12 @@ def const_int(pool: memhub.MemBuddy | t.CPtr, bits: t.CInt,
return ConstInt(pool, ty, val, name)
def const_int32(pool: memhub.MemBuddy | t.CPtr, val: t.CInt64T) -> Value | t.CPtr:
def const_int32(pool: rowptr[memhub.MemBuddy], val: int64) -> rowptr[Value]:
"""便捷: 创建 i32 整数常量"""
return const_int(pool, 32, val)
def const_int64(pool: memhub.MemBuddy | t.CPtr, val: t.CInt64T) -> Value | t.CPtr:
def const_int64(pool: rowptr[memhub.MemBuddy], val: int64) -> rowptr[Value]:
"""便捷: 创建 i64 整数常量"""
return const_int(pool, 64, val)
@@ -174,21 +176,21 @@ def const_int64(pool: memhub.MemBuddy | t.CPtr, val: t.CInt64T) -> Value | t.CPt
# ============================================================
# 便捷工厂: 创建函数并添加到模块
# ============================================================
def create_function(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
def create_function(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
name: str, ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
"""创建函数并添加到模块"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
func: Function | t.CPtr = new_function(pool, name_dup, ret_ty)
name_dup: str = _str_dup(pool, name)
func: rowptr[Function] = new_function(pool, name_dup, ret_ty)
if func is not None:
module_add_function(mod, func)
return func
def add_param(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Param | t.CPtr:
def add_param(pool: rowptr[memhub.MemBuddy], func: rowptr[Function],
ty: rowptr[LLVMType], name: str) -> rowptr[Param]:
"""创建参数并添加到函数"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
param: Param | t.CPtr = new_param(pool, ty, name_dup)
name_dup: str = _str_dup(pool, name)
param: rowptr[Param] = new_param(pool, ty, name_dup)
if param is not None:
function_add_param(func, param)
return param
@@ -197,15 +199,15 @@ def add_param(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
# ============================================================
# 便捷工厂: 创建函数声明(declare)
# ============================================================
def create_declare(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
def create_declare(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
name: str, ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
"""创建函数声明(declare,无函数体)并添加到模块
与 create_function 不同,声明不生成函数体,仅生成:
declare <ret_ty> @<name>(<params>)
"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
func: Function | t.CPtr = new_function(pool, name_dup, ret_ty)
name_dup: str = _str_dup(pool, name)
func: rowptr[Function] = new_function(pool, name_dup, ret_ty)
if func is not None:
func.IsDeclared = 1
module_add_function(mod, func)
@@ -218,8 +220,8 @@ def create_declare(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
# 生成 LLVM IR:
# @.str = private unnamed_addr constant [N x i8] c"contents\00"
# ============================================================
def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, text: t.CChar | t.CPtr) -> GlobalVariable | t.CPtr:
def create_global_string(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
name: str, text: str) -> rowptr[GlobalVariable]:
"""创建字符串常量全局变量并添加到模块
参数:
@@ -230,23 +232,23 @@ def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPt
"""
if text is None: return None
slen: t.CSizeT = string.strlen(text)
count: t.CInt = slen + 1 # 含末尾 NUL
count: int = slen + 1 # 含末尾 NUL
# 创建 i8 类型
i8_ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
i8_ty: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
if i8_ty is None: return None
string.memset(i8_ty, 0, LLVMType.__sizeof__())
c.DerefAs(i8_ty, LLVMType.Int(8))
# 创建 [count x i8] 数组类型
arr_ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
arr_ty: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
if arr_ty is None: return None
string.memset(arr_ty, 0, LLVMType.__sizeof__())
c.DerefAs(arr_ty, LLVMType.Array(i8_ty, count))
# 创建全局变量
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
gv: GlobalVariable | t.CPtr = new_global_variable(pool, name_dup, arr_ty)
name_dup: str = _str_dup(pool, name)
gv: rowptr[GlobalVariable] = new_global_variable(pool, name_dup, arr_ty)
if gv is None: return None
# 设置属性: private + unnamed_addr + constant
@@ -257,7 +259,7 @@ def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPt
# 构造初始化值文本: c"contents\00"
# LLVM IR 字符串字面量格式: c"<chars>" 其中 " 和 \ 及非打印字符用 \xx 转义
# 缓冲区大小: 最坏情况每个字符4字节(\xx)+ c"..." + \00 + "
init_buf: t.CChar | t.CPtr = pool.alloc(slen * 4 + 8)
init_buf: str = pool.alloc(slen * 4 + 8)
if init_buf is None: return None
pos: t.CSizeT = 0
init_buf[pos] = 'c'
@@ -271,8 +273,8 @@ def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPt
# 需要转义: " → \22, \ → \5c, 非打印字符 → \xx
init_buf[pos] = '\\'
pos += 1
hi: t.CInt = (ch >> 4) & 0x0F
lo: t.CInt = ch & 0x0F
hi: int = (ch >> 4) & 0x0F
lo: int = ch & 0x0F
if hi < 10:
init_buf[pos] = 0x30 + hi
else:
@@ -306,25 +308,25 @@ def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPt
# ============================================================
# 便捷工厂: 创建带初始化值的整数全局变量
# ============================================================
def create_global_int(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, bits: t.CInt, val: t.CInt64T) -> GlobalVariable | t.CPtr:
def create_global_int(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
name: str, bits: int, val: int64) -> rowptr[GlobalVariable]:
"""创建整数全局变量并添加到模块
生成 LLVM IR:
@<name> = global i<bits> <val>
"""
# 创建整数类型
ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
ty: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__())
c.DerefAs(ty, LLVMType.Int(bits))
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
gv: GlobalVariable | t.CPtr = new_global_variable(pool, name_dup, ty)
name_dup: str = _str_dup(pool, name)
gv: rowptr[GlobalVariable] = new_global_variable(pool, name_dup, ty)
if gv is None: return None
# 构造初始化值文本: "42" (类型由 _print_global 单独打印)
init_buf: t.CChar | t.CPtr = pool.alloc(48)
init_buf: str = pool.alloc(48)
if init_buf is None: return None
viperlib.snprintf(init_buf, 48, "%lld", val)
gv.Initializer = init_buf
@@ -337,123 +339,123 @@ def create_global_int(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
# LLVMModuleCore: 模块/函数/值创建核心,封装 pool 避免重复传参
#
# 用法:
# mcore: LLVMModuleCore | t.CPtr = LLVMModuleCore(pool)
# mod: LLVMModule | t.CPtr = mcore.NewModule("test")
# func: Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
# val: Value | t.CPtr = mcore.ConstInt32(42)
# mcore: rowptr[LLVMModuleCore] = LLVMModuleCore(pool)
# mod: rowptr[LLVMModule] = mcore.NewModule("test")
# func: rowptr[Function] = mcore.CreateFunction(mod, "add", ty_i32)
# val: rowptr[Value] = mcore.ConstInt32(42)
# ============================================================
@t.NoVTable
class LLVMModuleCore:
"""模块/函数/值创建核心,封装 pool 避免每次创建都传 pool"""
Pool: memhub.MemBuddy | t.CPtr
Pool: rowptr[memhub.MemBuddy]
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemBuddy]):
self.Pool = pool
# ---- 模块操作 ----
def NewModule(self, name: t.CChar | t.CPtr) -> LLVMModule | t.CPtr:
def NewModule(self, name: str) -> rowptr[LLVMModule]:
return new_module(self.Pool, name)
def CreateFunction(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
def CreateFunction(self, mod: rowptr[LLVMModule], name: str,
ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
return create_function(self.Pool, mod, name, ret_ty)
def CreateDeclare(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
def CreateDeclare(self, mod: rowptr[LLVMModule], name: str,
ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
"""创建函数声明(declare,无函数体)"""
return create_declare(self.Pool, mod, name, ret_ty)
def AddParam(self, func: Function | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Param | t.CPtr:
def AddParam(self, func: rowptr[Function], ty: rowptr[LLVMType],
name: str) -> rowptr[Param]:
return add_param(self.Pool, func, ty, name)
def FunctionSetAttrs(self, func: Function | t.CPtr, attrs: t.CChar | t.CPtr):
def FunctionSetAttrs(self, func: rowptr[Function], attrs: str):
"""设置函数级属性文本"""
function_set_attrs(func, attrs)
def ParamSetAttrs(self, param: Param | t.CPtr, attrs: t.CChar | t.CPtr):
def ParamSetAttrs(self, param: rowptr[Param], attrs: str):
"""设置参数属性文本"""
param_set_attrs(param, attrs)
def CreateBlock(self, func: Function | t.CPtr,
name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
def CreateBlock(self, func: rowptr[Function],
name: str) -> rowptr[BasicBlock]:
return create_block(self.Pool, func, name)
def NewBuilder(self, func: Function | t.CPtr) -> IRBuilder | t.CPtr:
def NewBuilder(self, func: rowptr[Function]) -> rowptr[IRBuilder]:
return new_builder(self.Pool, func)
# ---- 全局变量 ----
def NewGlobal(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
def NewGlobal(self, mod: rowptr[LLVMModule], name: str,
ty: rowptr[LLVMType]) -> rowptr[GlobalVariable]:
"""创建全局变量并添加到模块"""
name_dup: t.CChar | t.CPtr = _str_dup(self.Pool, name)
gv: GlobalVariable | t.CPtr = new_global_variable(self.Pool, name_dup, ty)
name_dup: str = _str_dup(self.Pool, name)
gv: rowptr[GlobalVariable] = new_global_variable(self.Pool, name_dup, ty)
if gv is not None:
module_add_global(mod, gv)
return gv
def CreateGlobalString(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
text: t.CChar | t.CPtr) -> GlobalVariable | t.CPtr:
def CreateGlobalString(self, mod: rowptr[LLVMModule], name: str,
text: str) -> rowptr[GlobalVariable]:
"""创建字符串常量全局变量"""
return create_global_string(self.Pool, mod, name, text)
def CreateGlobalInt(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
bits: t.CInt, val: t.CInt64T) -> GlobalVariable | t.CPtr:
def CreateGlobalInt(self, mod: rowptr[LLVMModule], name: str,
bits: int, val: int64) -> rowptr[GlobalVariable]:
"""创建带初始化值的整数全局变量"""
return create_global_int(self.Pool, mod, name, bits, val)
def GlobalSetConstant(self, gv: GlobalVariable | t.CPtr, is_const: t.CInt):
def GlobalSetConstant(self, gv: rowptr[GlobalVariable], is_const: int):
global_set_constant(gv, is_const)
def GlobalSetLinkage(self, gv: GlobalVariable | t.CPtr, linkage: t.CChar | t.CPtr):
def GlobalSetLinkage(self, gv: rowptr[GlobalVariable], linkage: str):
global_set_linkage(gv, linkage)
def GlobalSetUnnamedAddr(self, gv: GlobalVariable | t.CPtr, level: t.CInt):
def GlobalSetUnnamedAddr(self, gv: rowptr[GlobalVariable], level: int):
global_set_unnamed_addr(gv, level)
def GlobalSetSection(self, gv: GlobalVariable | t.CPtr, section: t.CChar | t.CPtr):
def GlobalSetSection(self, gv: rowptr[GlobalVariable], section: str):
global_set_section(gv, section)
# ---- 值创建 ----
def ConstInt(self, bits: t.CInt, val: t.CInt64T) -> Value | t.CPtr:
def ConstInt(self, bits: int, val: int64) -> rowptr[Value]:
return const_int(self.Pool, bits, val)
def ConstInt32(self, val: t.CInt64T) -> Value | t.CPtr:
def ConstInt32(self, val: int64) -> rowptr[Value]:
return const_int32(self.Pool, val)
def ConstInt64(self, val: t.CInt64T) -> Value | t.CPtr:
def ConstInt64(self, val: int64) -> rowptr[Value]:
return const_int64(self.Pool, val)
def ConstFloat(self, ty: LLVMType | t.CPtr, val: t.CDouble) -> Value | t.CPtr:
def ConstFloat(self, ty: rowptr[LLVMType], val: t.CDouble) -> rowptr[Value]:
return ConstFloat(self.Pool, ty, val)
def SSAValue(self, ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Value | t.CPtr:
def SSAValue(self, ty: rowptr[LLVMType], name: str) -> rowptr[Value]:
return SSAValue(self.Pool, ty, name)
def ConstNull(self, ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Value | t.CPtr:
def ConstNull(self, ty: rowptr[LLVMType], name: str) -> rowptr[Value]:
return ConstNull(self.Pool, ty, name)
# ---- 打印 ----
def PrintValue(self, buf: t.CChar | t.CPtr, size: t.CSizeT, val: Value | t.CPtr):
def PrintValue(self, buf: str, size: t.CSizeT, val: rowptr[Value]):
ValuePrint(buf, size, val, self.Pool)
def PrintFunction(self, buf: t.CChar | t.CPtr, size: t.CSizeT, func: Function | t.CPtr):
def PrintFunction(self, buf: str, size: t.CSizeT, func: rowptr[Function]):
FunctionPrint(buf, size, func, self.Pool)
def PrintModule(self, buf: t.CChar | t.CPtr, size: t.CSizeT, mod: LLVMModule | t.CPtr):
def PrintModule(self, buf: str, size: t.CSizeT, mod: rowptr[LLVMModule]):
LLVMModulePrint(buf, size, mod, self.Pool, OUTPUT_FULL)
# ---- SSA 验证 ----
def NewVerifyResult(self, buf_size: t.CSizeT) -> VerifyResult | t.CPtr:
def NewVerifyResult(self, buf_size: t.CSizeT) -> rowptr[VerifyResult]:
"""创建验证结果对象(buf_size 为错误消息缓冲区大小)"""
return _new_verify_result(self.Pool, buf_size)
def VerifyFunction(self, func: Function | t.CPtr,
result: VerifyResult | t.CPtr) -> t.CInt:
def VerifyFunction(self, func: rowptr[Function],
result: rowptr[VerifyResult]) -> int:
"""验证单个函数的 SSA 正确性,返回错误数(0=通过)"""
return verify_function(self.Pool, func, result)
def VerifyModule(self, mod: LLVMModule | t.CPtr,
result: VerifyResult | t.CPtr) -> t.CInt:
def VerifyModule(self, mod: rowptr[LLVMModule],
result: rowptr[VerifyResult]) -> int:
"""验证模块中所有函数的 SSA 正确性,返回错误数(0=通过)"""
return verify_module(self.Pool, mod, result)
+157 -107
View File
@@ -18,13 +18,14 @@ from .__function import Function, FunctionPrint, _ll_name_needs_quote, Param, pa
# ============================================================
@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
Name: str # 全局变量名(如 ".str" / "my_global")
Ty: rowptr[LLVMType] # 变量类型
Initializer: rowptr[t.CVoid] # 初始化值 Value*(None = 无初始化)
IsConstant: int # 1=constant, 0=variable
Linkage: str # 链接类型("private"/"internal"/"external"/...)
Section: str # 段名(None = 默认)
UnnamedAddr: int # 1=unnamed_addr, 2=local_unnamed_addr, 0=none
Align: int # 对齐字节数(0=默认对齐,如 @c.Attribute(t.attr.aligned(16)))
# ============================================================
@@ -35,7 +36,8 @@ class GlobalVariable(GSListNode[GlobalVariable]):
# ============================================================
@t.NoVTable
class NamedTypeNode(GSListNode[NamedTypeNode]):
Ty: LLVMType | t.CPtr # 命名结构体类型指针
Ty: rowptr[LLVMType] # 命名结构体类型指针
IsPacked: int # 1=packed 结构体(输出 <{...}>,无字段填充)
# ============================================================
@@ -48,17 +50,17 @@ class NamedTypeNode(GSListNode[NamedTypeNode]):
# ============================================================
@t.NoVTable
class LLVMModule:
Name: t.CChar | t.CPtr # 模块名
FuncHead: Function | t.CPtr # 函数链表头
FuncTail: Function | t.CPtr # 函数链表尾
Name: str # 模块名
FuncHead: rowptr[Function] # 函数链表头
FuncTail: rowptr[Function] # 函数链表尾
FuncCount: t.CSizeT # 函数计数
GlobalHead: GlobalVariable | t.CPtr # 全局变量链表头
GlobalTail: GlobalVariable | t.CPtr # 全局变量链表尾
GlobalHead: rowptr[GlobalVariable] # 全局变量链表头
GlobalTail: rowptr[GlobalVariable] # 全局变量链表尾
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 # 命名结构体类型链表尾
TargetTriple: str # 目标三元组(如 "x86_64-pc-linux-gnu")
DataLayout: str # 数据布局(如 "e-m:e-p270:32:32-...")
NamedTypeHead: rowptr[NamedTypeNode] # 命名结构体类型链表头
NamedTypeTail: rowptr[NamedTypeNode] # 命名结构体类型链表尾
NamedTypeCount: t.CSizeT # 命名结构体类型计数
# 总计: 12 字段 * 8 = 96 字节(无 vtable)
@@ -68,7 +70,7 @@ class LLVMModule:
# ============================================================
# ---- 链表操作 ----
def add_function(self, func: Function | t.CPtr):
def add_function(self, func: rowptr[Function]):
"""将函数追加到模块函数链表(O(1))"""
if self is None or func is None: return
func.Next = None
@@ -79,7 +81,7 @@ class LLVMModule:
self.FuncTail = func
self.FuncCount += 1
def add_global(self, gv: GlobalVariable | t.CPtr):
def add_global(self, gv: rowptr[GlobalVariable]):
"""将全局变量追加到模块全局变量链表(O(1))"""
if self is None or gv is None: return
gv.Next = None
@@ -91,18 +93,18 @@ class LLVMModule:
self.GlobalCount += 1
# ---- 目标属性 ----
def set_target(self, triple: t.CChar | t.CPtr):
def set_target(self, triple: str):
"""设置目标三元组"""
if self is None: return
self.TargetTriple = triple
def set_datalayout(self, layout: t.CChar | t.CPtr):
def set_datalayout(self, layout: str):
"""设置数据布局"""
if self is None: return
self.DataLayout = layout
# ---- 命名结构体类型管理 ----
def add_named_type(self, pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr):
def add_named_type(self, pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType]):
"""将命名结构体类型添加到模块(用于输出 %"name" = type { ... } 定义行)
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
@@ -110,12 +112,12 @@ class LLVMModule:
"""
if self is None or pool is None or ty is None:
return
name: t.CChar | t.CPtr = get_struct_name(ty)
name: str = get_struct_name(ty)
if name is None:
return
# 去重检查(opaque 声明可被完整定义替换)
cur: NamedTypeNode | t.CPtr = self.NamedTypeHead
cnt_dedup: t.CInt = 0
cur: rowptr[NamedTypeNode] = self.NamedTypeHead
cnt_dedup: int = 0
while cur is not None:
# 步数守卫:NamedTypeHead 链表成环(内存损坏/插入 bug)会导致
# 无限遍历挂起(G3 编译 LinkedNode.prepend 挂起根因)。
@@ -126,7 +128,7 @@ class LLVMModule:
name if name is not None else "(null)", cnt_dedup)
stdlib.exit(1)
if cur.Ty is not None:
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
existing_name: str = get_struct_name(cur.Ty)
if existing_name is not None:
if string.strcmp(existing_name, name) == 0:
# 已有完整定义则无需替换
@@ -140,11 +142,12 @@ class LLVMModule:
return
cur = cur.Next
# 创建新节点
node: NamedTypeNode | t.CPtr = pool.alloc(NAMED_TYPE_NODE_SIZE)
node: rowptr[NamedTypeNode] = pool.alloc(NAMED_TYPE_NODE_SIZE)
if node is None:
return
string.memset(node, 0, NAMED_TYPE_NODE_SIZE)
node.Ty = ty
node.IsPacked = 0
# opaque 类型插入链表头部,确保在引用它的完整定义之前声明。
# 例如 TypeRegistry{HashTable*, ...} 中,HashTable 的 opaque 声明
# 必须在 TypeRegistry 定义之前,否则 llc 报 "use of undefined type"。
@@ -163,12 +166,12 @@ class LLVMModule:
self.NamedTypeTail = node
self.NamedTypeCount += 1
def _is_type_defined_in_module(self, name: t.CChar | t.CPtr) -> int:
def _is_type_defined_in_module(self, name: str) -> int:
"""检查模块中是否已定义指定名称的结构体类型,返回 1=已定义 / 0=未定义"""
if self is None or name is None:
return 0
cur: NamedTypeNode | t.CPtr = self.NamedTypeHead
cnt_tdm: t.CInt = 0
cur: rowptr[NamedTypeNode] = self.NamedTypeHead
cnt_tdm: int = 0
while cur is not None:
# 步数守卫:同上,防 NamedTypeHead 链表成环无限遍历
cnt_tdm += 1
@@ -177,15 +180,15 @@ class LLVMModule:
name if name is not None else "(null)")
stdlib.exit(1)
if cur.Ty is not None:
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
existing_name: str = 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 ensure_opaque_for_type(self, pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
def ensure_opaque_for_type(self, pool: rowptr[memhub.MemBuddy],
ty: rowptr[LLVMType]):
"""为类型中的跨模块结构体引用添加 opaque 声明
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
@@ -194,8 +197,8 @@ class LLVMModule:
_scan_type_for_cross_module_refs(pool, self, ty)
# ---- 打印 ----
def PrintModule(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pool: memhub.MemBuddy | t.CPtr, mode: t.CInt):
def PrintModule(self, buf: str, size: t.CSizeT,
pool: rowptr[memhub.MemBuddy], mode: int):
"""将模块序列化为 .ll 文本写入 buf"""
if self is None or buf is None or size == 0: return
@@ -226,7 +229,7 @@ class LLVMModule:
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
# 修复:alloc_buf 返回 viperio.Buf,但 Buf 类型未在 NamedTypeHead 中注册
func_scan: Function | t.CPtr = self.FuncHead
func_scan: rowptr[Function] = self.FuncHead
func_scan_steps: t.CSizeT = 0
while func_scan is not None:
func_scan_steps += 1
@@ -237,7 +240,17 @@ class LLVMModule:
if func_scan.RetTy is not None:
self.ensure_opaque_for_type(pool, func_scan.RetTy)
if func_scan.Params is not None:
param_scan: Param | t.CPtr = func_scan.Params.Head
# [DBGCHAIN] Function.Params 指针合理性护栏(临时诊断,用后移除)
fp_v: t.CUInt64T = t.CUInt64T(func_scan.Params)
if fp_v < 0x10000 or fp_v == t.CUInt64T(0xFFFFFFFFFFFFFFFF) or ((fp_v >> 56) & 0xFF) == 0xFF:
fnp: str = "(nil)"
if func_scan.Name is not None:
fnp = func_scan.Name
stdio.printf("[DBGCHAIN] Function.Params 野值: func=%s func=%llx steps=%zu Params=%llx FuncCount=%zu\n",
fnp, t.CUInt64T(func_scan), func_scan_steps, fp_v, t.CUInt64T(self.FuncCount))
stdio.fflush(None)
stdlib.exit(1)
param_scan: rowptr[Param] = func_scan.Params.Head
param_scan_steps: t.CSizeT = 0
while param_scan is not None:
param_scan_steps += 1
@@ -246,6 +259,19 @@ class LLVMModule:
func_scan.Name, func_scan.Params.Count,
t.CUInt64T(param_scan), t.CUInt64T(param_scan.Next), IR_DUMP_CHAIN_LIMIT)
stdlib.exit(1)
# [DBGCHAIN] param 指针合理性护栏(临时诊断,用后移除):
# 指针被写坏成小值/全 F 时先打印归属函数与链表状态,再退出
pv_scan: t.CUInt64T = t.CUInt64T(param_scan)
pv_next: t.CUInt64T = 0
if param_scan.Next is not None:
pv_next = t.CUInt64T(param_scan.Next)
if pv_scan < 0x10000 or pv_scan == t.CUInt64T(0xFFFFFFFFFFFFFFFF) or ((pv_scan >> 56) & 0xFF) == 0xFF:
stdio.printf("[DBGCHAIN] param 指针野值: func=%s steps=%zu param=%llx next=%llx Params.Head=%llx Params.Tail=%llx Params.Count=%zu\n",
func_scan.Name, param_scan_steps, pv_scan, pv_next,
t.CUInt64T(func_scan.Params.Head), t.CUInt64T(func_scan.Params.Tail),
t.CUInt64T(func_scan.Params.Count))
stdio.fflush(None)
stdlib.exit(1)
# 用访问器(__function.vp 完整类型内)绕开 stub 字段访问
# 陷阱:跨模块 struct 字段访问可能生成错误 GEP/静默跳过,
# 导致 param_scan 永不更新死循环。
@@ -253,10 +279,10 @@ class LLVMModule:
self.ensure_opaque_for_type(pool, param_get_ty(param_scan))
param_scan = param_get_next(param_scan)
func_scan = func_scan.Next
nt: NamedTypeNode | t.CPtr = self.NamedTypeHead
nt: rowptr[NamedTypeNode] = self.NamedTypeHead
# 结构体定义缓冲区:48 字段 × ~50 字节/字段类型名 ≈ 2400 字节,4096 足够
# 在循环外分配一次并复用,减少 pool 碎片
ty_buf: t.CChar | t.CPtr = pool.alloc(4096)
ty_buf: str = pool.alloc(4096)
nt_steps: t.CSizeT = 0
while nt is not None:
nt_steps += 1
@@ -267,7 +293,7 @@ class LLVMModule:
if nt.Ty is not None:
if ty_buf is not None:
ty_buf[0] = '\0'
PrintStructDefinition(ty_buf, 4096, nt.Ty, pool)
PrintStructDefinition(ty_buf, 4096, nt.Ty, pool, nt.IsPacked)
_append_cstr(buf, size, ty_buf)
_append_cstr(buf, size, "\n")
nt = nt.Next
@@ -276,7 +302,7 @@ class LLVMModule:
_append_cstr(buf, size, "\n")
# 全局变量
gv: GlobalVariable | t.CPtr = self.GlobalHead
gv: rowptr[GlobalVariable] = self.GlobalHead
gv_steps: t.CSizeT = 0
if mode == OUTPUT_STUB:
# stub 模式:输出 external global(无初值)
@@ -292,7 +318,7 @@ class LLVMModule:
else:
# full 和 text 模式:输出完整全局变量
# text 模式跳过无初值的全局变量(纯声明)
gv_idx: t.CInt = 0
gv_idx: int = 0
while gv is not None:
gv_steps += 1
if gv_steps > IR_DUMP_CHAIN_LIMIT:
@@ -312,8 +338,8 @@ class LLVMModule:
_append_cstr(buf, size, "\n")
elif self.GlobalHead is not None and mode == OUTPUT_TEXT:
# text 模式下如果输出了全局变量,也加空行
had_global: t.CInt = 0
gv2: GlobalVariable | t.CPtr = self.GlobalHead
had_global: int = 0
gv2: rowptr[GlobalVariable] = self.GlobalHead
gv2_steps: t.CSizeT = 0
while gv2 is not None:
gv2_steps += 1
@@ -329,8 +355,8 @@ class LLVMModule:
_append_cstr(buf, size, "\n")
# 遍历函数
func: Function | t.CPtr = self.FuncHead
func_idx: t.CInt = 0
func: rowptr[Function] = self.FuncHead
func_idx: int = 0
func_steps: t.CSizeT = 0
while func is not None:
func_steps += 1
@@ -359,10 +385,10 @@ class LLVMModule:
# ============================================================
# 工厂函数
# ============================================================
def new_module(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> LLVMModule | t.CPtr:
def new_module(pool: rowptr[memhub.MemBuddy], name: str) -> rowptr[LLVMModule]:
"""创建一个模块"""
# 硬编码 96 字节:12 字段 * 8 字节(无 vtable,@t.NoVTable)
ptr: LLVMModule | t.CPtr = pool.alloc(96)
ptr: rowptr[LLVMModule] = pool.alloc(96)
if ptr is None: return None
string.memset(ptr, 0, 96)
ptr.Name = name
@@ -380,16 +406,16 @@ def new_module(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> LLVMMo
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
# GlobalVariable 硬编码大小: Next(8) + Name(8) + Ty(8) + Initializer(8) + IsConstant(4) + Linkage(8) + Section(8) + UnnamedAddr(4) + Align(4) = 72 字节
GV_SIZE: t.CDefine = 72
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) = 16 字节
NAMED_TYPE_NODE_SIZE: t.CDefine = 16
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) + IsPacked(8) = 24 字节
NAMED_TYPE_NODE_SIZE: t.CDefine = 24
def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
name: t.CChar | t.CPtr, ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
def new_global_variable(pool: rowptr[memhub.MemBuddy],
name: str, ty: rowptr[LLVMType]) -> rowptr[GlobalVariable]:
"""创建一个全局变量"""
ptr: GlobalVariable | t.CPtr = pool.alloc(GV_SIZE)
ptr: rowptr[GlobalVariable] = pool.alloc(GV_SIZE)
if ptr is None: return None
string.memset(ptr, 0, GV_SIZE)
ptr.Name = name
@@ -399,33 +425,34 @@ def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
ptr.Linkage = "external"
ptr.Section = None
ptr.UnnamedAddr = 0
ptr.Align = 0
return ptr
# ============================================================
# 链表操作(嵌入式 Head/Tail/Count,O(1) 追加)
# ============================================================
def module_add_function(mod: LLVMModule | t.CPtr, func: Function | t.CPtr):
return mod.add_function(func)
def module_add_function(mod: rowptr[LLVMModule], func: rowptr[Function]):
mod.add_function(func)
def module_get_func_head(mod: LLVMModule | t.CPtr) -> Function | t.CPtr:
def module_get_func_head(mod: rowptr[LLVMModule]) -> rowptr[Function]:
"""获取模块函数链表头(跨模块访问器,绕 stub 字段访问陷阱)"""
if mod is None:
return None
return mod.FuncHead
def module_add_global(mod: LLVMModule | t.CPtr, gv: GlobalVariable | t.CPtr):
return mod.add_global(gv)
def module_add_global(mod: rowptr[LLVMModule], gv: rowptr[GlobalVariable]):
mod.add_global(gv)
def module_set_target(mod: LLVMModule | t.CPtr, triple: t.CChar | t.CPtr):
return mod.set_target(triple)
def module_set_target(mod: rowptr[LLVMModule], triple: str):
mod.set_target(triple)
def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
return mod.set_datalayout(layout)
def module_set_datalayout(mod: rowptr[LLVMModule], layout: str):
mod.set_datalayout(layout)
# ============================================================
@@ -444,7 +471,7 @@ def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
#
# Returns: 1=是 opaque / 0=否
# ============================================================
def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
def _is_opaque_struct(ty: rowptr[LLVMType]) -> int:
"""检查类型是否是 opaque 结构体
opaque 是跨模块前向声明(仅名称无字段定义),由
@@ -466,9 +493,36 @@ def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
return 0
def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
return mod.add_named_type(pool, ty)
def module_add_named_type(mod: rowptr[LLVMModule], pool: rowptr[memhub.MemBuddy],
ty: rowptr[LLVMType]):
mod.add_named_type(pool, ty)
def module_set_named_type_packed(mod: rowptr[LLVMModule], pool: rowptr[memhub.MemBuddy],
ty: rowptr[LLVMType], is_packed: int):
"""按名称设置命名结构体的 packed 标记(输出 %"name" = type <{...}>)。
编译器解析 @c.Attribute(t.attr.packed) 后调用,使 llc 按 packed 布局
(无字段填充)计算字段偏移/GEP。ty 为命名 Struct 类型(按 get_struct_name
定位已注册节点);未找到则静默跳过(opaque/跨模块 stub 场景无布局需求)。
"""
if mod is None or ty is None:
return
name: str = get_struct_name(ty)
if name is None:
return
cur: rowptr[NamedTypeNode] = mod.NamedTypeHead
cnt_p: int = 0
while cur is not None:
cnt_p += 1
if cnt_p > 100000:
return
if cur.Ty is not None:
existing_name: str = get_struct_name(cur.Ty)
if existing_name is not None and string.strcmp(existing_name, name) == 0:
cur.IsPacked = is_packed
return
cur = cur.Next
# ============================================================
@@ -478,14 +532,14 @@ def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CP
# 如果该名称未在模块中定义,则添加 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:
def _is_type_defined_in_module(mod: rowptr[LLVMModule], name: str) -> int:
return mod._is_type_defined_in_module(name)
def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
mod: LLVMModule | t.CPtr,
ty: LLVMType | t.CPtr,
depth: t.CInt = 0):
def _scan_type_for_cross_module_refs(pool: rowptr[memhub.MemBuddy],
mod: rowptr[LLVMModule],
ty: rowptr[LLVMType],
depth: int = 0):
"""递归扫描类型树,为跨模块结构体引用添加 opaque 声明"""
if ty is None or mod is None or pool is None:
return
@@ -506,13 +560,13 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
# 创建 opaque 类型并添加到模块
# fcount=-1 哨兵标记 opaque(区别于空结构体 {},
# 后者 fcount==0 是合法完整定义,可 alloca)
opaque_ty: LLVMType | t.CPtr = Struct(pool, None, -1, sname)
opaque_ty: rowptr[LLVMType] = Struct(pool, None, -1, sname)
if opaque_ty is not None:
module_add_named_type(mod, pool, opaque_ty)
# 递归扫描结构体字段中的跨模块引用
# 例如 TypeRegistry{HashTable*, MemManager*} 中的 HashTable 引用
if sfields is not None:
fld: ParamNode | t.CPtr = sfields
fld: rowptr[ParamNode] = sfields
fld_steps: t.CSizeT = 0
while fld is not None:
fld_steps += 1
@@ -526,20 +580,9 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
case _:
_scan_type_for_cross_module_refs(pool, mod, pointee, depth + 1)
case LLVMType.Struct(sfields2, sfcount2, sname2):
# 顶层结构体(非指针):递归扫描字段,并补 opaque 声明。
# 此前只对 Ptr(Struct) 添加 opaque,裸 Struct(值类型,如
# 数组元素 [7 x gdt_entry] 的 gdt_entry)引用时无任何类型定义
# → llc "use of undefined type named 'sha1.gdt_entry'"
# (fpu/fat32 合并 IR external global 根因)。值类型引用
# 同样需要类型存在(opaque 即可);模块已有完整定义时
# _is_type_defined_in_module 命中,不重复添加。
if sname2 is not None and string.strchr(sname2, 46) is not None:
if _is_type_defined_in_module(mod, sname2) == 0:
opaque_ty2: LLVMType | t.CPtr = Struct(pool, None, -1, sname2)
if opaque_ty2 is not None:
module_add_named_type(mod, pool, opaque_ty2)
# 顶层结构体(非指针):递归扫描字段
if sfields2 is not None:
fld2: ParamNode | t.CPtr = sfields2
fld2: rowptr[ParamNode] = sfields2
fld2_steps: t.CSizeT = 0
while fld2 is not None:
fld2_steps += 1
@@ -557,34 +600,34 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
pass
def module_ensure_opaque_for_type(mod: LLVMModule | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
return mod.ensure_opaque_for_type(pool, ty)
def module_ensure_opaque_for_type(mod: rowptr[LLVMModule],
pool: rowptr[memhub.MemBuddy],
ty: rowptr[LLVMType]):
mod.ensure_opaque_for_type(pool, ty)
# ============================================================
# 全局变量属性设置
# ============================================================
def global_set_constant(gv: GlobalVariable | t.CPtr, is_const: t.CInt):
def global_set_constant(gv: rowptr[GlobalVariable], is_const: int):
"""设置全局变量是否为常量"""
if gv is None: return
gv.IsConstant = is_const
def global_set_linkage(gv: GlobalVariable | t.CPtr, linkage: t.CChar | t.CPtr):
def global_set_linkage(gv: rowptr[GlobalVariable], linkage: str):
"""设置链接类型 (private/internal/external/... )"""
if gv is None: return
gv.Linkage = linkage
def global_set_unnamed_addr(gv: GlobalVariable | t.CPtr, level: t.CInt):
def global_set_unnamed_addr(gv: rowptr[GlobalVariable], level: int):
"""设置 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):
def global_set_section(gv: rowptr[GlobalVariable], section: str):
"""设置段名"""
if gv is None: return
gv.Section = section
@@ -610,17 +653,17 @@ IR_DUMP_CHAIN_LIMIT: t.CDefine = 100000
#
# 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):
return mod.PrintModule(buf, size, pool, mode)
def LLVMModulePrint(buf: str, size: t.CSizeT,
mod: rowptr[LLVMModule], pool: rowptr[memhub.MemBuddy],
mode: int):
mod.PrintModule(buf, size, pool, mode)
# ============================================================
# 全局变量打印
# ============================================================
def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
def _print_global(buf: str, size: t.CSizeT,
gv: rowptr[GlobalVariable], pool: rowptr[memhub.MemBuddy]):
"""打印单个全局变量: @<name> = [linkage] [unnamed_addr] [constant] <ty> <init>"""
if gv is None: return
@@ -655,7 +698,7 @@ def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, "global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(512)
ty_buf: str = pool.alloc(512)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 512, gv.Ty, pool)
@@ -672,12 +715,19 @@ def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, gv.Section)
_append_cstr(buf, size, "\"")
# 对齐(@c.Attribute(t.attr.aligned(N)) 类的全局实例,如 fpu_context 16 对齐)
if gv.Align > 0:
align_buf: str = pool.alloc(32)
if align_buf is not None:
viperlib.snprintf(align_buf, 32, ", align %d", gv.Align)
_append_cstr(buf, size, align_buf)
# ============================================================
# _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):
def _print_global_stub(buf: str, size: t.CSizeT,
gv: rowptr[GlobalVariable], pool: rowptr[memhub.MemBuddy]):
"""打印全局变量声明: @<name> = external global <ty>"""
if gv is None: return
@@ -692,7 +742,7 @@ def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, " = external global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(512)
ty_buf: str = pool.alloc(512)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 512, gv.Ty, pool)
@@ -708,7 +758,7 @@ def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
_g_last_dst: t.CUInt64T = 0
_g_last_pos: t.CSizeT = 0
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
def _append_cstr(dst: str, dst_size: t.CSizeT, src: str):
"""将 C 字符串 src 追加到 dst 末尾"""
global _g_last_dst, _g_last_pos
if dst is None or src is None: return
+142 -127
View File
@@ -11,13 +11,13 @@ from linkedlist import GSListNode
# ============================================================
# ParamNode: 函数参数类型链表节点
# 继承 GSListNode[ParamNode] 获取强类型 Next: ParamNode|CPtr
# Ty 用 t.CVoid | t.CPtr 前向引用,使用时转型为 (LLVMType | t.CPtr)
# Ty 用 rowptr[t.CVoid] 前向引用,使用时转型为 (rowptr[LLVMType])
#
# 注意: 必须加 @t.NoVTable(理由见 __function.py 的 Line 注释)。
# ============================================================
@t.NoVTable
class ParamNode(GSListNode[ParamNode]):
Ty: t.CVoid | t.CPtr # LLVMType*(前向引用,使用时转型)
Ty: rowptr[t.CVoid] # LLVMType*(前向引用,使用时转型)
# ============================================================
@@ -29,34 +29,34 @@ class ParamNode(GSListNode[ParamNode]):
class LLVMType(t.REnum):
# 整数类型: i1/i8/i16/i32/i64
class Int:
Bits: t.CInt
Bits: int
# 指针类型: pointee*
class Ptr:
Pointee: LLVMType | t.CPtr
Pointee: rowptr[LLVMType]
# 函数类型: ret (params)
class Func:
Ret: LLVMType | t.CPtr
Params: ParamNode | t.CPtr
PCount: t.CInt
Ret: rowptr[LLVMType]
Params: rowptr[ParamNode]
PCount: int
# 数组类型: [N x elem_ty]
class Array:
ElemTy: LLVMType | t.CPtr
Count: t.CInt
ElemTy: rowptr[LLVMType]
Count: int
# 结构体类型: {ty1, ty2, ...} 或 %"name" = type {ty1, ty2, ...}
# Fields 复用 ParamNode 链表(ParamNode.Ty 即字段类型)
# Name 非 None 时为命名结构体,TypePrint 输出 %"name" 而非 {...}
class Struct:
Fields: ParamNode | t.CPtr
FCount: t.CInt
Name: t.CChar | t.CPtr
Fields: rowptr[ParamNode]
FCount: int
Name: str
# 浮点类型: half/float/double/fp128
class Float:
Bits: t.CInt # 16=half, 32=float, 64=double, 128=fp128
Bits: int # 16=half, 32=float, 64=double, 128=fp128
# 无值类型
class Void:
@@ -74,9 +74,9 @@ class LLVMType(t.REnum):
# ============================================================
# 内部分配辅助
# ============================================================
def _new_type(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
def _new_type(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
"""从 mpool 分配一个零初始化的 LLVMType"""
ptr: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
ptr: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
if ptr:
string.memset(ptr, 0, LLVMType.__sizeof__())
return ptr
@@ -85,42 +85,42 @@ def _new_type(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
# ============================================================
# 类型工厂函数
# ============================================================
def Int1(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Int1(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(1))
return ptr
def Int8(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Int8(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(8))
return ptr
def Int16(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Int16(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(16))
return ptr
def Int32(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Int32(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(32))
return ptr
def Int64(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Int64(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(64))
return ptr
def Ptr(pool: memhub.MemBuddy | t.CPtr, pointee: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
def Ptr(pool: rowptr[memhub.MemBuddy], pointee: rowptr[LLVMType]) -> rowptr[LLVMType]:
"""创建指针类型 Ptr(pointee)
LLVM IR 中 **不允许 void* 指针**("pointers to void are invalid"),
@@ -130,7 +130,7 @@ def Ptr(pool: memhub.MemBuddy | t.CPtr, pointee: LLVMType | t.CPtr) -> LLVMType
其他类型正常构造 Ptr(pointee)。
"""
# ============== 前置校验: 拦截 Void / None pointee(void* 非法)==============
safe_pointee: LLVMType | t.CPtr = pointee
safe_pointee: rowptr[LLVMType] = pointee
if safe_pointee is None:
safe_pointee = Int8(pool)
else:
@@ -139,85 +139,85 @@ def Ptr(pool: memhub.MemBuddy | t.CPtr, pointee: LLVMType | t.CPtr) -> LLVMType
safe_pointee = Int8(pool)
case _:
pass
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Ptr(safe_pointee))
return ptr
def Func(pool: memhub.MemBuddy | t.CPtr, ret: LLVMType | t.CPtr,
params: ParamNode | t.CPtr, count: t.CInt) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Func(pool: rowptr[memhub.MemBuddy], ret: rowptr[LLVMType],
params: rowptr[ParamNode], count: int) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Func(ret, params, count))
return ptr
def Void(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
def Void(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Void())
return ptr
def Array(pool: memhub.MemBuddy | t.CPtr, elem_ty: LLVMType | t.CPtr,
count: t.CInt) -> LLVMType | t.CPtr:
def Array(pool: rowptr[memhub.MemBuddy], elem_ty: rowptr[LLVMType],
count: int) -> rowptr[LLVMType]:
"""创建数组类型 [count x elem_ty]"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Array(elem_ty, count))
return ptr
def Struct(pool: memhub.MemBuddy | t.CPtr, fields: ParamNode | t.CPtr,
fcount: t.CInt, name: t.CChar | t.CPtr) -> LLVMType | t.CPtr:
def Struct(pool: rowptr[memhub.MemBuddy], fields: rowptr[ParamNode],
fcount: int, name: str) -> rowptr[LLVMType]:
"""创建结构体类型 {ty1, ty2, ...}
fields 为 ParamNode 链表头,fcount 为字段数量。
name 非 None 时为命名结构体(如 "sha1.ClassName"),TypePrint 输出 %"name"。
name 为 None 时为匿名结构体,TypePrint 输出 {ty1, ty2, ...}。
"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Struct(fields, fcount, name))
return ptr
def Half(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
def Half(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
"""创建半精度浮点类型 half (16-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(16))
return ptr
def Float(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
def Float(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
"""创建单精度浮点类型 float (32-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(32))
return ptr
def Double(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
def Double(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
"""创建双精度浮点类型 double (64-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(64))
return ptr
def FP128(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
def FP128(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
"""创建四精度浮点类型 fp128 (128-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(128))
return ptr
def Label(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
def Label(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
"""创建标签类型 label"""
ptr: LLVMType | t.CPtr = _new_type(pool)
ptr: rowptr[LLVMType] = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Label())
return ptr
@@ -229,9 +229,9 @@ def Label(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
# ParamNode 硬编码大小: Next(8) + Ty(8) = 16 字节
PNODE_SIZE: t.CDefine = 16
def new_param_node(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
def new_param_node(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType]) -> rowptr[ParamNode]:
"""创建一个参数节点,Ty 设为给定类型指针"""
ptr: ParamNode | t.CPtr = pool.alloc(PNODE_SIZE)
ptr: rowptr[ParamNode] = pool.alloc(PNODE_SIZE)
if ptr is None: return None
string.memset(ptr, 0, PNODE_SIZE)
ptr.Ty = ty
@@ -239,8 +239,8 @@ def new_param_node(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Par
return ptr
def param_list_append(head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
def param_list_append(head: rowptr[ParamNode], tail: rowptr[ParamNode],
node: rowptr[ParamNode]) -> rowptr[ParamNode]:
"""将 node 追加到参数链表尾部,返回 head 和更新后的 tail"""
if node is None: return head
node.Next = None
@@ -258,28 +258,28 @@ def param_list_append(head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
# 导致 TransPyC 静默跳过字段访问。这些访问器在拥有完整类型定义的
# 本模块内执行,能正确访问所有字段。
# ============================================================
def paramnode_get_ty(node: ParamNode | t.CPtr) -> LLVMType | t.CPtr:
def paramnode_get_ty(node: rowptr[ParamNode]) -> rowptr[LLVMType]:
"""获取参数节点的类型"""
if node is None:
return None
return (LLVMType | t.CPtr)(node.Ty)
return (rowptr[LLVMType])(node.Ty)
def paramnode_get_next(node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
def paramnode_get_next(node: rowptr[ParamNode]) -> rowptr[ParamNode]:
"""获取链表下一个参数节点"""
if node is None:
return None
return node.Next
def paramnode_set_ty(node: ParamNode | t.CPtr, ty: LLVMType | t.CPtr):
def paramnode_set_ty(node: rowptr[ParamNode], ty: rowptr[LLVMType]):
"""设置参数节点的类型"""
if node is None:
return
node.Ty = ty
def paramnode_set_next(node: ParamNode | t.CPtr, nxt: ParamNode | t.CPtr):
def paramnode_set_next(node: rowptr[ParamNode], nxt: rowptr[ParamNode]):
"""设置链表下一个参数节点"""
if node is None:
return
@@ -290,77 +290,77 @@ def paramnode_set_next(node: ParamNode | t.CPtr, nxt: ParamNode | t.CPtr):
# LLVMTypeCore: 类型创建核心,封装 pool 避免重复传参
#
# 用法:
# core: LLVMTypeCore | t.CPtr = LLVMTypeCore(pool)
# ty_i32: LLVMType | t.CPtr = core.Int32()
# ty_ptr: LLVMType | t.CPtr = core.Ptr(ty_i32)
# ty_void: LLVMType | t.CPtr = core.Void()
# core: rowptr[LLVMTypeCore] = LLVMTypeCore(pool)
# ty_i32: rowptr[LLVMType] = core.Int32()
# ty_ptr: rowptr[LLVMType] = core.Ptr(ty_i32)
# ty_void: rowptr[LLVMType] = core.Void()
# ============================================================
@t.NoVTable
class LLVMTypeCore:
"""类型创建核心,封装 pool 避免每次创建类型都传 pool"""
Pool: memhub.MemBuddy | t.CPtr
Pool: rowptr[memhub.MemBuddy]
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
def __init__(self, pool: rowptr[memhub.MemBuddy]):
self.Pool = pool
def Int1(self) -> LLVMType | t.CPtr:
def Int1(self) -> rowptr[LLVMType]:
return Int1(self.Pool)
def Int8(self) -> LLVMType | t.CPtr:
def Int8(self) -> rowptr[LLVMType]:
return Int8(self.Pool)
def Int16(self) -> LLVMType | t.CPtr:
def Int16(self) -> rowptr[LLVMType]:
return Int16(self.Pool)
def Int32(self) -> LLVMType | t.CPtr:
def Int32(self) -> rowptr[LLVMType]:
return Int32(self.Pool)
def Int64(self) -> LLVMType | t.CPtr:
def Int64(self) -> rowptr[LLVMType]:
return Int64(self.Pool)
def Ptr(self, pointee: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
def Ptr(self, pointee: rowptr[LLVMType]) -> rowptr[LLVMType]:
return Ptr(self.Pool, pointee)
def Func(self, ret: LLVMType | t.CPtr, params: ParamNode | t.CPtr,
count: t.CInt) -> LLVMType | t.CPtr:
def Func(self, ret: rowptr[LLVMType], params: rowptr[ParamNode],
count: int) -> rowptr[LLVMType]:
return Func(self.Pool, ret, params, count)
def Array(self, elem_ty: LLVMType | t.CPtr, count: t.CInt) -> LLVMType | t.CPtr:
def Array(self, elem_ty: rowptr[LLVMType], count: int) -> rowptr[LLVMType]:
return Array(self.Pool, elem_ty, count)
def Struct(self, fields: ParamNode | t.CPtr, fcount: t.CInt,
name: t.CChar | t.CPtr = None) -> LLVMType | t.CPtr:
def Struct(self, fields: rowptr[ParamNode], fcount: int,
name: str = None) -> rowptr[LLVMType]:
return Struct(self.Pool, fields, fcount, name)
def Void(self) -> LLVMType | t.CPtr:
def Void(self) -> rowptr[LLVMType]:
return Void(self.Pool)
def Half(self) -> LLVMType | t.CPtr:
def Half(self) -> rowptr[LLVMType]:
return Half(self.Pool)
def Float(self) -> LLVMType | t.CPtr:
def Float(self) -> rowptr[LLVMType]:
return Float(self.Pool)
def Double(self) -> LLVMType | t.CPtr:
def Double(self) -> rowptr[LLVMType]:
return Double(self.Pool)
def FP128(self) -> LLVMType | t.CPtr:
def FP128(self) -> rowptr[LLVMType]:
return FP128(self.Pool)
def Label(self) -> LLVMType | t.CPtr:
def Label(self) -> rowptr[LLVMType]:
return Label(self.Pool)
def NewParamNode(self, ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
def NewParamNode(self, ty: rowptr[LLVMType]) -> rowptr[ParamNode]:
return new_param_node(self.Pool, ty)
# ---- 链表辅助 ----
def ParamListAppend(self, head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
def ParamListAppend(self, head: rowptr[ParamNode], tail: rowptr[ParamNode],
node: rowptr[ParamNode]) -> rowptr[ParamNode]:
"""将 node 追加到参数/字段链表,返回新的 tail"""
return param_list_append(head, tail, node)
# ---- 打印 ----
def PrintType(self, buf: t.CChar | t.CPtr, size: t.CSizeT, ty: LLVMType | t.CPtr):
def PrintType(self, buf: str, size: t.CSizeT, ty: rowptr[LLVMType]):
TypePrint(buf, size, ty, self.Pool)
@@ -378,8 +378,8 @@ class LLVMTypeCore:
#
# pool 用于复杂类型(Array/Struct/Func)递归打印子类型时分配临时缓冲区。
# ============================================================
def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
def TypePrint(buf: str, size: t.CSizeT,
ty: rowptr[LLVMType], pool: rowptr[memhub.MemBuddy]):
"""将类型 ty 序列化为 IR 文本写入 buf(容量 size)
pool 用于递归打印子类型时分配临时缓冲区。
@@ -392,9 +392,9 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 造成 OOM(单文件暴涨 900MB 根因)。超过 100 层即停止打印。
TYPEPRINT_MAX_DEPTH: t.CDefine = 100
def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
depth: t.CInt):
def _TypePrintDepth(buf: str, size: t.CSizeT,
ty: rowptr[LLVMType], pool: rowptr[memhub.MemBuddy],
depth: int):
"""带递归深度上限的 TypePrint 内部实现"""
if ty is None or buf is None or size == 0:
return
@@ -422,7 +422,7 @@ def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 类型名含 sha1 前缀可超 40 字符(如
# "bbdf3bbd4c3bc28c.CONSOLE_SCREEN_BUFFER_INFO"=42),
# 原 40 字节截断会产生未定义类型引用(llc: undefined type)。
sn_cp: t.CChar | t.CPtr = pool.alloc(256)
sn_cp: str = pool.alloc(256)
if sn_cp is not None:
string.strncpy(sn_cp, sname, 255)
sn_cp[255] = '\0'
@@ -455,7 +455,7 @@ def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
viperlib.snprintf(buf, size, "[%d x ", count)
# SHA1 限定类型名(如 %"21a7fcfc665f75ef.NamedTypeNode")可达 ~50 字节,
# 嵌套指针/数组更易超过 128,使用 512 字节避免截断
tmp: t.CChar | t.CPtr = pool.alloc(512)
tmp: str = pool.alloc(512)
if tmp is not None:
_TypePrintDepth(tmp, 512, elem_ty, pool, depth + 1)
_strappend(buf, size, tmp)
@@ -471,11 +471,11 @@ def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
# ret (ty1, ty2, ...)
_TypePrintDepth(buf, size, ret, pool, depth + 1)
_strappend(buf, size, " (")
cur2: ParamNode | t.CPtr = params
first2: t.CInt = 1
_pc2: t.CInt = 0
cur2: rowptr[ParamNode] = params
first2: int = 1
_pc2: int = 0
# 函数参数类型可能为 SHA1 限定命名结构体指针,512 字节避免截断
tmp3: t.CChar | t.CPtr = pool.alloc(512)
tmp3: str = pool.alloc(512)
while cur2 is not None:
# 悬空保护:参数链若被 reset 回收后内容复用,可能成环无限循环
_pc2 += 1
@@ -514,7 +514,7 @@ def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
# ============================================================
# 内部辅助
# ============================================================
def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
def _strappend(dst: str, dst_size: t.CSizeT, src: str):
"""将 src 追加到 dst 末尾(不超过 dst_size)"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
@@ -537,25 +537,32 @@ def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr)
#
# 供 TypePrint(匿名结构体)和 PrintStructDefinition(命名结构体定义行)复用
# ============================================================
def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
depth: t.CInt = 0):
def _print_struct_body(buf: str, size: t.CSizeT,
fields: rowptr[ParamNode], pool: rowptr[memhub.MemBuddy],
depth: int = 0, packed: int = 0):
"""打印 {ty1, ty2, ...} 到 buf(追加模式,不覆盖已有内容)
直接在 buf 当前末尾写入字段类型,避免 pool.alloc 返回与 buf 重叠的内存
导致 TypePrint 写入 tmp 时覆盖 buf 已有内容。
packed=1 时输出 <{ty1, ty2, ...}>(LLVM packed struct,无字段填充)。
"""
if buf is None or size == 0:
return
_strappend(buf, size, "{")
cur: ParamNode | t.CPtr = fields
first: t.CInt = 1
fidx: t.CInt = 0
if packed != 0:
_strappend(buf, size, "<{")
else:
_strappend(buf, size, "{")
cur: rowptr[ParamNode] = fields
first: int = 1
fidx: int = 0
while cur is not None:
# 悬空保护:ParamNode 链若被 reset 回收后内容复用,Next 指针可能成环或
# 指向垃圾,无限循环。最多打印 200 个字段即停止,防止 OOM。
if fidx >= 200:
_strappend(buf, size, "...}")
if packed != 0:
_strappend(buf, size, "...}>")
else:
_strappend(buf, size, "...}")
return
if first == 0:
_strappend(buf, size, ", ")
@@ -567,7 +574,10 @@ def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
cur = cur.Next
first = 0
fidx += 1
_strappend(buf, size, "}")
if packed != 0:
_strappend(buf, size, "}>")
else:
_strappend(buf, size, "}")
# ============================================================
@@ -576,12 +586,14 @@ def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 输出格式: %"name" = type { ty1, ty2, ... }
# 供 LLVMModulePrint 在全局变量/函数之前输出类型定义
# ============================================================
def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
def PrintStructDefinition(buf: str, size: t.CSizeT,
ty: rowptr[LLVMType], pool: rowptr[memhub.MemBuddy],
packed: int = 0):
"""打印命名结构体类型定义行 %"name" = type { ty1, ty2, ... }
当 fcount == -1(哨兵)时输出 opaque 声明: %"name" = type opaque。
空结构体(fcount==0, fields==None,无字段类)是完整定义,输出 "= type {}"。
packed=1 时输出 %"name" = type <{ ty1, ty2, ... }>(LLVM packed struct)。
"""
if ty is None or buf is None or size == 0:
return
@@ -595,7 +607,7 @@ def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
viperlib.snprintf(buf, size, "%%\"%s\" = type opaque", name)
else:
viperlib.snprintf(buf, size, "%%\"%s\" = type ", name)
_print_struct_body(buf, size, fields, pool)
_print_struct_body(buf, size, fields, pool, 0, packed)
case _:
return
@@ -606,7 +618,7 @@ def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 返回 Name 字段(如 "sha1.ClassName"),非 Struct 类型或匿名 Struct 返回 None
# 供 module_add_named_type 检查是否为命名结构体及去重
# ============================================================
def get_struct_name(ty: LLVMType | t.CPtr) -> t.CChar | t.CPtr:
def get_struct_name(ty: rowptr[LLVMType]) -> str:
"""获取命名结构体的名称,非命名结构体返回 None"""
if ty is None:
return None
@@ -617,7 +629,7 @@ def get_struct_name(ty: LLVMType | t.CPtr) -> t.CChar | t.CPtr:
return None
def get_struct_fields(ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
def get_struct_fields(ty: rowptr[LLVMType]) -> rowptr[ParamNode]:
"""获取结构体的字段链表(供跨模块重建 Struct 类型用)"""
if ty is None:
return None
@@ -628,7 +640,7 @@ def get_struct_fields(ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
return None
def get_struct_fcount(ty: LLVMType | t.CPtr) -> t.CInt:
def get_struct_fcount(ty: rowptr[LLVMType]) -> int:
"""获取结构体的字段数量(供跨模块重建 Struct 类型用)"""
if ty is None:
return 0
@@ -656,14 +668,14 @@ def get_struct_fcount(ty: LLVMType | t.CPtr) -> t.CInt:
# ============================================================
DEEPCOPY_MAX_DEPTH: t.CDefine = 64
def DeepCopyType(pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
def DeepCopyType(pool: rowptr[memhub.MemBuddy],
ty: rowptr[LLVMType]) -> rowptr[LLVMType]:
"""深拷贝 LLVMType 到 stdlib 区(深度限制防自引用递归),失败返回 None"""
return _DeepCopyDepth(pool, ty, 0)
def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr, depth: t.CInt) -> LLVMType | t.CPtr:
def _DeepCopyDepth(pool: rowptr[memhub.MemBuddy],
ty: rowptr[LLVMType], depth: int) -> rowptr[LLVMType]:
"""带深度上限的深拷贝实现
分配源用传入的 pool 参数(调用方决定):传主 pool 为瞬时拷贝
@@ -672,7 +684,7 @@ def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
"""
if ty is None:
return None
new_ty: LLVMType | t.CPtr = (LLVMType | t.CPtr)(pool.alloc(LLVMType.__sizeof__()))
new_ty: rowptr[LLVMType] = (rowptr[LLVMType])(pool.alloc(LLVMType.__sizeof__()))
if new_ty is None:
return None
string.memset(new_ty, 0, LLVMType.__sizeof__())
@@ -716,25 +728,28 @@ def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
_DeepCopyParamChain(pool, fields, depth + 1),
fcount, _DeepCopyStr(pool, name)))
case _:
stdlib.free(new_ty)
# new_ty 由 pool(MemBuddy)分配,必须用 pool.free(buddy 回收)
# 而非 stdlib.free(仅回收 malloc 块)——后者对 arena 内指针调用
# 会损坏堆(0xC0000374 / ASan bad-free)。
pool.free(new_ty)
return None
return new_ty
def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
head: ParamNode | t.CPtr, depth: t.CInt) -> ParamNode | t.CPtr:
def _DeepCopyParamChain(pool: rowptr[memhub.MemBuddy],
head: rowptr[ParamNode], depth: int) -> rowptr[ParamNode]:
"""深拷贝 ParamNode 链表到 stdlib"""
if head is None:
return None
first: ParamNode | t.CPtr = None
prev: ParamNode | t.CPtr = None
cur: ParamNode | t.CPtr = head
guard: t.CInt = 0
first: rowptr[ParamNode] = None
prev: rowptr[ParamNode] = None
cur: rowptr[ParamNode] = head
guard: int = 0
while cur is not None:
guard += 1
if guard > 512:
break
node: ParamNode | t.CPtr = (ParamNode | t.CPtr)(pool.alloc(PNODE_SIZE))
node: rowptr[ParamNode] = (rowptr[ParamNode])(pool.alloc(PNODE_SIZE))
if node is None:
break
string.memset(node, 0, PNODE_SIZE)
@@ -749,12 +764,12 @@ def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
return first
def _DeepCopyStr(pool: memhub.MemBuddy | t.CPtr, s: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
def _DeepCopyStr(pool: rowptr[memhub.MemBuddy], s: str) -> str:
"""深拷贝字符串到 stdlib"""
if s is None:
return None
slen: t.CSizeT = string.strlen(s)
copy: t.CChar | t.CPtr = pool.alloc(slen + 1)
copy: str = pool.alloc(slen + 1)
if copy is None:
return None
string.strcpy(copy, s)
+31 -31
View File
@@ -19,10 +19,10 @@ from .__types import LLVMType, TypePrint
# ============================================================
@t.NoVTable
class Value(GSListNode[Value]):
Ty: LLVMType | t.CPtr # 值的类型
Name: t.CChar | t.CPtr # SSA 名("%0"/"%result")或常量文本("42"/"1.5e+00")
IsConst: t.CInt # 1=常量字面量, 0=SSA 临时值
IntVal: t.CInt64T # 整数常量值(当 IsConst=1 时使用)
Ty: rowptr[LLVMType] # 值的类型
Name: str # SSA 名("%0"/"%result")或常量文本("42"/"1.5e+00")
IsConst: int # 1=常量字面量, 0=SSA 临时值
IntVal: int64 # 整数常量值(当 IsConst=1 时使用)
FloatVal: t.CDouble # 浮点常量值(当 IsConst=1 且 Ty 为 Float 时使用)
@@ -32,16 +32,16 @@ class Value(GSListNode[Value]):
# Value 硬编码大小: Next(8) + Ty(8) + Name(8) + IsConst(4) + IntVal(8) + FloatVal(8) = 48 字节
VALUE_SIZE: t.CDefine = 48
def new_value(pool: memhub.MemBuddy | t.CPtr) -> Value | t.CPtr:
def new_value(pool: rowptr[memhub.MemBuddy]) -> rowptr[Value]:
"""从 mpool 分配一个零初始化的 Value"""
ptr: Value | t.CPtr = pool.alloc(VALUE_SIZE)
ptr: rowptr[Value] = pool.alloc(VALUE_SIZE)
if ptr:
string.memset(ptr, 0, VALUE_SIZE)
return ptr
def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
val: t.CInt64T, name: t.CChar | t.CPtr) -> Value | t.CPtr:
def ConstInt(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
val: int64, name: str) -> rowptr[Value]:
"""创建整数常量值
参数:
@@ -49,7 +49,7 @@ def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
val: 整数值
name: 常量文本(如 "42"),由调用方提供
"""
v: Value | t.CPtr = new_value(pool)
v: rowptr[Value] = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = name
@@ -58,10 +58,10 @@ def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
return v
def ConstNull(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Value | t.CPtr:
def ConstNull(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
name: str) -> rowptr[Value]:
"""创建 null 指针常量"""
v: Value | t.CPtr = new_value(pool)
v: rowptr[Value] = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = name
@@ -70,9 +70,9 @@ def ConstNull(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
return v
def ConstZero(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Value | t.CPtr:
def ConstZero(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType]) -> rowptr[Value]:
"""创建 zeroinitializer 常量(零初始化聚合类型:结构体/数组)"""
v: Value | t.CPtr = new_value(pool)
v: rowptr[Value] = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = "zeroinitializer"
@@ -81,8 +81,8 @@ def ConstZero(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Value |
return v
def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
val: t.CDouble) -> Value | t.CPtr:
def ConstFloat(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
val: t.CDouble) -> rowptr[Value]:
"""创建浮点常量值
参数:
@@ -90,7 +90,7 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
val: 浮点数值
名字自动格式化为 LLVM IR 科学计数法文本(如 "1.500000e+00")。
"""
v: Value | t.CPtr = new_value(pool)
v: rowptr[Value] = new_value(pool)
if v is None: return None
v.Ty = ty
v.IsConst = 1
@@ -102,13 +102,13 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
# 导致 add_scalar[0]==11 等浮点常量比较失败)。位模式无精度损失。
# 原 %e 默认 6 位小数还会截断精度(3.1415926535897931 -> 3.141593e+00)。
# 用 CRT stdio.snprintf: viperlib 自实现 %g 有小数位反转 bug。
f_bits: t.CInt = 64
f_bits: int = 64
match ty:
case LLVMType.Float(ftb):
f_bits = ftb
fv_bits: t.CUInt64T = 0
c.Load(c.Addr(fv_bits), c.Addr(val))
name_buf: t.CChar | t.CPtr = pool.alloc(32)
name_buf: str = pool.alloc(32)
if name_buf is not None:
if f_bits == 32:
stdio.snprintf(name_buf, 32, "0x%08x", t.CUInt32T(fv_bits))
@@ -118,15 +118,15 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
return v
def SSAValue(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Value | t.CPtr:
def SSAValue(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
name: str) -> rowptr[Value]:
"""创建 SSA 临时值
参数:
ty: 值类型
name: SSA 名(如 "%0"/"%result"),由调用方提供
"""
v: Value | t.CPtr = new_value(pool)
v: rowptr[Value] = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = name
@@ -142,8 +142,8 @@ def SSAValue(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
# ConstInt(i32, 42, "42") -> "i32 42"
# SSAValue(i32, "%0") -> "i32 %0"
# ============================================================
def ValuePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
val: Value | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
def ValuePrint(buf: str, size: t.CSizeT,
val: rowptr[Value], pool: rowptr[memhub.MemBuddy]):
"""将值 val 序列化为 IR 文本写入 buf
格式: <type> <name>
@@ -171,42 +171,42 @@ def ValuePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 导致 TransPyC 静默跳过字段访问(不生成 GEP,不报错)。
# 这些访问器在拥有完整类型定义的本模块内执行,能正确访问所有字段。
# ============================================================
def value_get_ty(val: Value | t.CPtr) -> LLVMType | t.CPtr:
def value_get_ty(val: rowptr[Value]) -> rowptr[LLVMType]:
"""获取值的类型"""
if val is None:
return None
return val.Ty
def value_get_next(val: Value | t.CPtr) -> Value | t.CPtr:
def value_get_next(val: rowptr[Value]) -> rowptr[Value]:
"""获取链表下一个值"""
if val is None:
return None
return val.Next
def value_set_ty(val: Value | t.CPtr, ty: LLVMType | t.CPtr):
def value_set_ty(val: rowptr[Value], ty: rowptr[LLVMType]):
"""设置值的类型"""
if val is None:
return
val.Ty = ty
def value_set_next(val: Value | t.CPtr, nxt: Value | t.CPtr):
def value_set_next(val: rowptr[Value], nxt: rowptr[Value]):
"""设置链表下一个值"""
if val is None:
return
val.Next = nxt
def value_set_name(val: Value | t.CPtr, name: t.CChar | t.CPtr):
def value_set_name(val: rowptr[Value], name: str):
"""设置值的名字"""
if val is None:
return
val.Name = name
def value_set_isconst(val: Value | t.CPtr, is_const: t.CInt):
def value_set_isconst(val: rowptr[Value], is_const: int):
"""设置是否为常量"""
if val is None:
return
@@ -216,7 +216,7 @@ def value_set_isconst(val: Value | t.CPtr, is_const: t.CInt):
# ============================================================
# 内部辅助
# ============================================================
def _append_str(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
def _append_str(dst: str, dst_size: t.CSizeT, src: str):
"""将 src 追加到 dst 末尾"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
+67 -67
View File
@@ -33,33 +33,33 @@ VERIFY_ERR_PHI_NOT_FIRST: t.CDefine = 4
# ============================================================
@t.NoVTable
class NameEntry(GSListNode[NameEntry]):
Name: t.CChar | t.CPtr # SSA 名(如 "%0"/"%result")
Name: str # SSA 名(如 "%0"/"%result")
# ============================================================
# VerifyResult: 验证结果
# ============================================================
class VerifyResult:
ErrorCount: t.CInt # 错误总数
WarningCount: t.CInt # 警告总数
ErrorCode: t.CInt # 第一个错误码
ErrorBuf: t.CChar | t.CPtr # 错误消息缓冲区
ErrorCount: int # 错误总数
WarningCount: int # 警告总数
ErrorCode: int # 第一个错误码
ErrorBuf: str # 错误消息缓冲区
ErrorBufSize: t.CSizeT # 缓冲区大小
# ============================================================
# 辅助函数
# ============================================================
def _new_verify_result(pool: memhub.MemBuddy | t.CPtr,
buf_size: t.CSizeT) -> VerifyResult | t.CPtr:
def _new_verify_result(pool: rowptr[memhub.MemBuddy],
buf_size: t.CSizeT) -> rowptr[VerifyResult]:
"""创建验证结果对象"""
ptr: VerifyResult | t.CPtr = pool.alloc(VerifyResult.__sizeof__())
ptr: rowptr[VerifyResult] = pool.alloc(VerifyResult.__sizeof__())
if ptr is None: return None
string.memset(ptr, 0, VerifyResult.__sizeof__())
ptr.ErrorCount = 0
ptr.WarningCount = 0
ptr.ErrorCode = VERIFY_OK
buf: t.CChar | t.CPtr = pool.alloc(buf_size)
buf: str = pool.alloc(buf_size)
if buf is not None:
buf[0] = '\0'
ptr.ErrorBuf = buf
@@ -67,7 +67,7 @@ def _new_verify_result(pool: memhub.MemBuddy | t.CPtr,
return ptr
def _report_error(result: VerifyResult | t.CPtr, code: t.CInt, msg: t.CChar | t.CPtr):
def _report_error(result: rowptr[VerifyResult], code: int, msg: str):
"""记录一个错误"""
if result is None: return
result.ErrorCount += 1
@@ -84,7 +84,7 @@ def _report_error(result: VerifyResult | t.CPtr, code: t.CInt, msg: t.CChar | t.
_g_last_dst: t.CUInt64T = 0
_g_last_pos: t.CSizeT = 0
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
def _append_cstr(dst: str, dst_size: t.CSizeT, src: str):
"""将 src 追加到 dst 末尾"""
global _g_last_dst, _g_last_pos
if dst is None or src is None: return
@@ -115,9 +115,9 @@ def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPt
# ============================================================
# SSA 名表操作
# ============================================================
def _new_name_table(pool: memhub.MemBuddy | t.CPtr) -> GSList[NameEntry] | t.CPtr:
def _new_name_table(pool: rowptr[memhub.MemBuddy]) -> rowptr[GSList[NameEntry]]:
"""创建空名表"""
gsl: GSList[NameEntry] | t.CPtr = pool.alloc(24) # GSList: Head+Tail+Count
gsl: rowptr[GSList[NameEntry]] = pool.alloc(24) # GSList: Head+Tail+Count
if gsl is None: return None
string.memset(gsl, 0, 24)
return gsl
@@ -126,19 +126,19 @@ def _new_name_table(pool: memhub.MemBuddy | t.CPtr) -> GSList[NameEntry] | t.CPt
# NameEntry 硬编码大小: Next(8) + Name(8) = 16 字节
NENTRY_SIZE: t.CDefine = 16
def _name_table_add(table: GSList[NameEntry] | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
name: t.CChar | t.CPtr) -> t.CInt:
def _name_table_add(table: rowptr[GSList[NameEntry]],
pool: rowptr[memhub.MemBuddy],
name: str) -> int:
"""添加名到表。返回 1=重复, 0=成功添加"""
if table is None or name is None: return 0
# 检查重复
cur: NameEntry | t.CPtr = table.Head
cur: rowptr[NameEntry] = table.Head
while cur is not None:
if string.strcmp(cur.Name, name) == 0:
return 1
cur = cur.Next
# 添加新条目
entry: NameEntry | t.CPtr = pool.alloc(NENTRY_SIZE)
entry: rowptr[NameEntry] = pool.alloc(NENTRY_SIZE)
if entry is None: return 0
string.memset(entry, 0, NENTRY_SIZE)
entry.Name = name
@@ -146,11 +146,11 @@ def _name_table_add(table: GSList[NameEntry] | t.CPtr,
return 0
def _name_table_contains(table: GSList[NameEntry] | t.CPtr,
name: t.CChar | t.CPtr) -> t.CInt:
def _name_table_contains(table: rowptr[GSList[NameEntry]],
name: str) -> int:
"""检查名是否在表中。返回 1=存在, 0=不存在"""
if table is None or name is None: return 0
cur: NameEntry | t.CPtr = table.Head
cur: rowptr[NameEntry] = table.Head
while cur is not None:
if string.strcmp(cur.Name, name) == 0:
return 1
@@ -161,7 +161,7 @@ def _name_table_contains(table: GSList[NameEntry] | t.CPtr,
# ============================================================
# 文本分析辅助
# ============================================================
def _is_char_name(ch: t.CChar) -> t.CInt:
def _is_char_name(ch: t.CChar) -> int:
"""判断字符是否为 SSA 名字符 [a-zA-Z0-9._]"""
if ch >= 'a' and ch <= 'z': return 1
if ch >= 'A' and ch <= 'Z': return 1
@@ -170,8 +170,8 @@ def _is_char_name(ch: t.CChar) -> t.CInt:
return 0
def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
text: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
def _extract_def_name(pool: rowptr[memhub.MemBuddy],
text: str) -> str:
"""从定义行提取被定义的 SSA 名。
定义行格式: "%<name> = <instruction>"
@@ -180,14 +180,14 @@ def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
if text is None: return None
if text[0] != '%': return None
# 扫描 " = " 模式
i: t.CInt = 1
i: int = 1
while text[i] != '\0':
if text[i] == ' ' and text[i + 1] == '=' and text[i + 2] == ' ':
# 找到 " = " 在位置 i
name_len: t.CInt = i
name: t.CChar | t.CPtr = pool.alloc(name_len + 1)
name_len: int = i
name: str = pool.alloc(name_len + 1)
if name is None: return None
j: t.CInt = 0
j: int = 0
while j < name_len:
name[j] = text[j]
j += 1
@@ -197,7 +197,7 @@ def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
return None
def _is_terminator(text: t.CChar | t.CPtr) -> t.CInt:
def _is_terminator(text: str) -> int:
"""判断文本是否为终止指令"""
if text is None: return 0
if string.strncmp(text, "ret", 3) == 0: return 1
@@ -209,32 +209,32 @@ def _is_terminator(text: t.CChar | t.CPtr) -> t.CInt:
return 0
def _is_phi(text: t.CChar | t.CPtr) -> t.CInt:
def _is_phi(text: str) -> int:
"""判断文本是否为 phi 指令"""
if text is None: return 0
if string.strstr(text, " = phi ") is not None: return 1
return 0
def _check_uses_in_line(table: GSList[NameEntry] | t.CPtr,
text: t.CChar | t.CPtr,
def_name: t.CChar | t.CPtr) -> t.CInt:
def _check_uses_in_line(table: rowptr[GSList[NameEntry]],
text: str,
def_name: str) -> int:
"""检查行中所有 SSA 名使用是否已定义。
跳过 def_name(定义位置的名字)。
返回未定义使用数量。
"""
if text is None: return 0
i: t.CInt = 0
undef_count: t.CInt = 0
i: int = 0
undef_count: int = 0
while text[i] != '\0':
if text[i] == '%':
# 提取名
name_start: t.CInt = i
name_start: int = i
i += 1
while text[i] != '\0' and _is_char_name(text[i]) == 1:
i += 1
name_len: t.CInt = i - name_start
name_len: int = i - name_start
if name_len > 1:
# 构建临时名串进行比较
# 由于无法在栈上分配,用 strstr 进行简化检查
@@ -251,13 +251,13 @@ def _check_uses_in_line(table: GSList[NameEntry] | t.CPtr,
return undef_count
def _name_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
table: GSList[NameEntry] | t.CPtr) -> t.CInt:
def _name_matches_at(text: str, start: int, length: int,
table: rowptr[GSList[NameEntry]]) -> int:
"""检查 text[start:start+length] 是否匹配名表中的某个条目。
返回 1=匹配, 0=不匹配
"""
if table is None: return 0
cur: NameEntry | t.CPtr = table.Head
cur: rowptr[NameEntry] = table.Head
while cur is not None:
if cur.Name is not None:
if _str_matches_at(text, start, length, cur.Name) == 1:
@@ -266,16 +266,16 @@ def _name_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
return 0
def _str_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
target: t.CChar | t.CPtr) -> t.CInt:
def _str_matches_at(text: str, start: int, length: int,
target: str) -> int:
"""检查 text[start:start+length] 是否等于 target 字符串。
返回 1=匹配, 0=不匹配
"""
if text is None or target is None: return 0
# 检查 target 长度
target_len: t.CInt = string.strlen(target)
target_len: t.CSizeT = string.strlen(target)
if target_len != length: return 0
i: t.CInt = 0
i: t.CSizeT = 0
while i < length:
if text[start + i] != target[i]: return 0
i += 1
@@ -285,9 +285,9 @@ def _str_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
# ============================================================
# 主验证函数
# ============================================================
def verify_function(pool: memhub.MemBuddy | t.CPtr,
func: Function | t.CPtr,
result: VerifyResult | t.CPtr) -> t.CInt:
def verify_function(pool: rowptr[memhub.MemBuddy],
func: rowptr[Function],
result: rowptr[VerifyResult]) -> int:
"""验证函数的 SSA 正确性。
参数:
@@ -300,11 +300,11 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
if func is None or result is None: return 1
# 创建名表
name_table: GSList[NameEntry] | t.CPtr = _new_name_table(pool)
name_table: rowptr[GSList[NameEntry]] = _new_name_table(pool)
if name_table is None: return 1
# 1. 将函数参数加入名表(参数是已定义的)
param: Param | t.CPtr = None
param: rowptr[Param] = None
if func.Params is not None:
param = func.Params.Head
while param is not None:
@@ -313,13 +313,13 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
param = param.Next
# 1b. 将基本块名加入名表(块标签如 %then 是 br/phi 的合法引用目标)
blk_iter: BasicBlock | t.CPtr = None
blk_iter: rowptr[BasicBlock] = None
if func.Blocks is not None:
blk_iter = func.Blocks.Head
while blk_iter is not None:
if blk_iter.Name is not None:
blk_name_len: t.CSizeT = string.strlen(blk_iter.Name)
blk_ref: t.CChar | t.CPtr = pool.alloc(blk_name_len + 2)
blk_ref: str = pool.alloc(blk_name_len + 2)
if blk_ref is not None:
# 构造 "%<name>" 字符串
blk_ref[0] = '%'
@@ -332,15 +332,15 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
blk_iter = blk_iter.Next
# 2. 遍历所有块
blk: BasicBlock | t.CPtr = None
blk: rowptr[BasicBlock] = None
if func.Blocks is not None:
blk = func.Blocks.Head
while blk is not None:
# 检查终止指令
if blk.IsTerminated == 0:
# 进一步检查最后一行是否为终止指令
has_term: t.CInt = 0
line_check: Line | t.CPtr = None
has_term: int = 0
line_check: rowptr[Line] = None
if blk.Lines is not None:
line_check = blk.Lines.Head
while line_check is not None:
@@ -349,27 +349,27 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
has_term = 1
line_check = line_check.Next
if has_term == 0:
blk_name: t.CChar | t.CPtr = "<unnamed>"
blk_name: str = "<unnamed>"
if blk.Name is not None:
blk_name = blk.Name
err_buf: t.CChar | t.CPtr = pool.alloc(128)
err_buf: str = pool.alloc(128)
if err_buf is not None:
viperlib.snprintf(err_buf, 128, "ERROR: block '%s' missing terminator", blk_name)
_report_error(result, VERIFY_ERR_NO_TERMINATOR, err_buf)
# 遍历块内指令行
seen_non_phi: t.CInt = 0
line: Line | t.CPtr = None
seen_non_phi: int = 0
line: rowptr[Line] = None
if blk.Lines is not None:
line = blk.Lines.Head
while line is not None:
if line.Buf is not None:
text: t.CChar | t.CPtr = line.Buf
text: str = line.Buf
# 检查 phi 位置
if _is_phi(text) == 1:
if seen_non_phi == 1:
phi_err: t.CChar | t.CPtr = pool.alloc(128)
phi_err: str = pool.alloc(128)
if phi_err is not None:
viperlib.snprintf(phi_err, 128, "ERROR: phi not at block start")
_report_error(result, VERIFY_ERR_PHI_NOT_FIRST, phi_err)
@@ -379,20 +379,20 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
seen_non_phi = 1
# 提取定义名
def_name: t.CChar | t.CPtr = _extract_def_name(pool, text)
def_name: str = _extract_def_name(pool, text)
if def_name is not None:
# 检查重复定义
dup: t.CInt = _name_table_add(name_table, pool, def_name)
dup: int = _name_table_add(name_table, pool, def_name)
if dup == 1:
dup_err: t.CChar | t.CPtr = pool.alloc(128)
dup_err: str = pool.alloc(128)
if dup_err is not None:
viperlib.snprintf(dup_err, 128, "ERROR: duplicate definition '%s'", def_name)
_report_error(result, VERIFY_ERR_DUPLICATE_DEF, dup_err)
# 检查未定义使用
undef: t.CInt = _check_uses_in_line(name_table, text, def_name)
undef: int = _check_uses_in_line(name_table, text, def_name)
if undef > 0:
use_err: t.CChar | t.CPtr = pool.alloc(128)
use_err: str = pool.alloc(128)
if use_err is not None:
viperlib.snprintf(use_err, 128, "ERROR: %d undefined use(s) in: %s", undef, text)
_report_error(result, VERIFY_ERR_UNDEFINED_USE, use_err)
@@ -404,13 +404,13 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
return result.ErrorCount
def verify_module(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr, result: VerifyResult | t.CPtr) -> t.CInt:
def verify_module(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule], result: rowptr[VerifyResult]) -> int:
"""验证模块中所有函数的 SSA 正确性。
返回: 错误总数
"""
if mod is None or result is None: return 1
func: Function | t.CPtr = mod.FuncHead
func: rowptr[Function] = mod.FuncHead
while func is not None:
if func.IsDeclared == 0:
# 只验证有函数体的定义,跳过声明
+157 -82
View File
@@ -18,12 +18,12 @@ import stdlib
MEMHUB_ALIGN: t.CDefine = 8
# MemSlab bitmap constants
MEMSLAB_MIN_BLOCK: t.CDefine = 16
MEMSLAB_MIN_BLOCK: t.CDefine = 16
MEMSLAB_BITMAP_BYTES: t.CDefine = 256
# MemBuddy buddy constants
MEMBUDDY_MIN_BLOCK: t.CDefine = 32
MEMBUDDY_MAX_ORDERS: t.CDefine = 32
MEMBUDDY_MIN_BLOCK: t.CDefine = 32
MEMBUDDY_MAX_ORDERS: t.CDefine = 32
MEMBUDDY_HEADER_SIZE: t.CDefine = 8
# 块尾 canary:alloc 时在块尾(用户数据区之外)写 8 字节哨兵,
# check_alive_blocks 校验——越界写穿数据区会破坏 canary,把
@@ -34,7 +34,7 @@ MEMBUDDY_CANARY: t.CDefine = 8
# alloc 时把用户数据区填充 0xCD 哨兵。若对象初始化(list.__init__ 等)
# 未执行,其字段保持 0xCDCD...,CTORDBG/VDBG 打印字段时一眼可辨
# "未初始化(0xCDCD)" 与 "被覆盖(其他值)"。0=关闭(性能),1=开启。
MEMBUDDY_FILL_GUARD: t.CDefine = 1
MEMBUDDY_FILL_GUARD: t.CDefine = 1
MEMBUDDY_FILL_PATTERN: t.CDefine = 0xCD
# [DET] 分配检测(alloc 前后 2 字节 0xCDCD 标记 + 记录表探测越界写):
@@ -51,7 +51,15 @@ MEMBUDDY_DET_RECORD_SIZE: t.CDefine = 33554432
# 记录追加本身 O(1) 不受影响;损坏是持久性的,不依赖即时扫描,采样
# 不损失检测能力——2M 次 alloc 若每次全表 O(n) 扫描 = O(n²) 太慢
# (用户反馈 detection 模式过慢),采样把扫描次数降为 1/N。
MEMBUDDY_DET_PROBE_PERIOD: t.CDefine = 256
MEMBUDDY_DET_PROBE_PERIOD: t.CDefine = 32
# [MEMDBG] 临时插桩(2026-09-04,定位 free list 重复 put / 悬空 free / alloc
# 重复出块;定位后整体移除,勿长期保留)。改动点:
# 1. alloc:采样分支内校验"新出块仍残留于同 order free list";
# 2. free :归还前校验"同 order free list 已含本块"(double-put 实锤);
# 3. free :无效/悬空指针(池内但 header 偶数=已释放)不再静默忽略;
# 4. 既有 [DET]/[MEM] 终止路径补 stdio.fflush(None)(stdout 重定向丢输出)。
MEMBUDDY_DBG: t.CDefine = 1
def _canary_pattern() -> t.CUInt64T:
@@ -88,30 +96,30 @@ def _block_size_at_order(order: t.CInt) -> t.CSizeT:
@t.CVTable
class MemManager:
__provides__: list[str] = ['__memmgr__']
base: t.CVoid | t.CPtr # Starting address of memory region
base: t.CPtr # Starting address of memory region
size: t.CSizeT # Total size of memory region
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT):
def __init__(self, base: t.CPtr, size: t.CSizeT):
self.base = base
self.size = size
# === Virtual functions (overridden by subclasses) ===
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
def alloc(self, size: t.CSizeT) -> t.CPtr:
# Default: allocation not supported
return None
def free(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
def free(self, ptr: t.CPtr) -> int:
# Default: no operation
return 0
def reset(self) -> t.CInt:
def reset(self) -> int:
# Default: no operation
return 0
# === Concrete methods (invoke virtual functions for automatic polymorphic dispatch) ===
def calloc(self, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr:
def calloc(self, count: t.CSizeT, size: t.CSizeT) -> t.CPtr:
total: t.CSizeT = count * size
ptr: t.CVoid | t.CPtr = self.alloc(total)
if ptr is not None:
@@ -418,16 +426,18 @@ class MemBuddy(MemManager):
rem -= blk
self.usable_size = used_area
# [DET] 分配检测记录区:stdlib.malloc 独立分配(不占用 buddy 区,
# 分配记录区:stdlib.malloc 独立分配(不占用 buddy 区,
# 与 chk_stack 同策略)。容量 = detection_size // 16(每条 {ptr,size})。
if detection != 0:
det_arena: t.CVoid | t.CPtr = t.CVoid(
stdlib.malloc(self.detection_size), t.CPtr)
if det_arena is not None:
self._det_arena = det_arena
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(det_arena, t.CPtr))
self._det_cap = self.detection_size // 16
self._det_count = 0
# 2026-09-04:记录+重叠检测从 detection 解耦——非 detection 也分配
# 记录区并启用同地址重复分配检测(不做前后标记、不改 alloc 布局),
# 定位 free-list/重复分配类损坏(memhub 翻译早期容器 Count 槽被写坏)。
det_arena: t.CVoid | t.CPtr = t.CVoid(
stdlib.malloc(self.detection_size), t.CPtr)
if det_arena is not None:
self._det_arena = det_arena
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(det_arena, t.CPtr))
self._det_cap = self.detection_size // 16
self._det_count = 0
# === Checkpoint support ===
@@ -487,7 +497,10 @@ class MemBuddy(MemManager):
# free 只置标志不删),截断 chk_depth 必须同步截断 _det_count,
# 否则 reset 后旧记录仍标 active → 下一轮 alloc 复用同一块被
# 误报为"分配重叠/越界写"(SlotsBugTest 7B buf + 72B Token 误报根因)。
if self.detection != 0 and self._det_records is not None:
# 2026-09-04 记录表已与 detection 解耦(detection=0 也启用记录+重叠
# 检测),截断条件不能挂 detection——否则检测模式下 reset_to 后
# 旧记录残留 active,复用块被误报重叠(记录[647] sz=72 误报例)。
if self._det_records is not None:
self._det_count = mark
self._unlock()
@@ -668,54 +681,80 @@ class MemBuddy(MemManager):
if self.chk_depth < self.chk_cap:
self.chk_stack[self.chk_depth] = t.CUInt64T(block)
self.chk_depth += 1
if result is not None and self.detection != 0:
# [DET] 布局 [0xCDCD][请求大小内存][0xCDCD]:返回指针 = 用户区 + 2
# (前标记之后);记录 {返回 ptr, size} 到独立记录区;随后探测全部
# 存活块的后标记——被破坏 = 越界写,立即汇报并终止。
if result is not None and self._det_records is not None:
base_ret_d: t.CUInt64T = t.CUInt64T(result)
m_f_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(base_ret_d, t.CPtr))
m_f_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
tail_d: t.CUInt64T = base_ret_d + 2 + t.CUInt64T(size)
m_t_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(tail_d, t.CPtr))
m_t_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
if self._det_records is not None:
# 采样:每 MEMBUDDY_DET_PROBE_PERIOD 次 alloc 做一次全表扫描
# (分配重叠 + 探测),其余只追加记录(O(1))。损坏是持久性的,
# 不依赖即时扫描——2M 次 alloc 若每次全表 O(n) = O(n²) 太慢
# (用户反馈 detection 模式过慢),采样把扫描降为 O(n²/PERIOD)。
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
# 分配重叠即时检测:新块地址是否已在 active 记录(同一块重复
# 分配实锤——SlotsBugTest 7B buf 与 72B Token 同 ptr、cargs
# 只写 0/40 根因)。重叠 = MemBuddy free list 损坏(active 块
# 混入 free list),在第一次重叠处拦截并打印两个 size。
ff_d: t.CUInt64T = t.CUInt64T(1) << 63
dup_i: t.CSizeT = 0
while dup_i < self._det_count:
drp: t.CUInt64T = self._det_records[dup_i * 2]
drs: t.CUInt64T = self._det_records[dup_i * 2 + 1]
if drp == base_ret_d + 2 and (drs & ff_d) == 0:
stdio.printf("[DET] 分配重叠: 新alloc(size=%llu)与记录[%zu](sz=%llu)同地址 ptr=%llu(同一块重复分配,free list 损坏)\n",
t.CUInt64T(size), dup_i, drs & (ff_d - 1), base_ret_d + 2)
# 返回指针(detection 布局下 = 用户区 + 2,前标记之后)
rec_ptr_d: t.CUInt64T = base_ret_d
if self.detection != 0:
# [DET] 布局 [0xCDCD][请求大小内存][0xCDCD]:返回指针 = 用户区 + 2
# (前标记之后);记录 {返回 ptr, size} 到独立记录区;随后探测全部
# 存活块的后标记——被破坏 = 越界写,立即汇报并终止。
m_f_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(base_ret_d, t.CPtr))
m_f_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
tail_d: t.CUInt64T = base_ret_d + 2 + t.CUInt64T(size)
m_t_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(tail_d, t.CPtr))
m_t_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
rec_ptr_d = base_ret_d + 2
# 采样:每 MEMBUDDY_DET_PROBE_PERIOD 次 alloc 做一次全表扫描
# (分配重叠 + 探测),其余只追加记录(O(1))。损坏是持久性的,
# 不依赖即时扫描——2M 次 alloc 若每次全表 O(n) = O(n²) 太慢
# (用户反馈 detection 模式过慢),采样把扫描降为 O(n²/PERIOD)。
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
# 分配重叠即时检测:新块地址是否已在 active 记录(同一块重复
# 分配实锤——SlotsBugTest 7B buf 与 72B Token 同 ptr、cargs
# 只写 0/40 根因)。重叠 = MemBuddy free list 损坏(active 块
# 混入 free list),在第一次重叠处拦截并打印两个 size。
ff_d: t.CUInt64T = t.CUInt64T(1) << 63
dup_i: t.CSizeT = 0
while dup_i < self._det_count:
drp: t.CUInt64T = self._det_records[dup_i * 2]
drs: t.CUInt64T = self._det_records[dup_i * 2 + 1]
if drp == rec_ptr_d and (drs & ff_d) == 0:
stdio.printf("[DET] 分配重叠: 新alloc(size=%llu)与记录[%zu](sz=%llu)同地址 ptr=%llu(同一块重复分配,free list 损坏)\n",
t.CUInt64T(size), dup_i, drs & (ff_d - 1), rec_ptr_d)
stdio.fflush(None)
stdlib.exit(1)
dup_i += 1
if MEMBUDDY_DBG != 0:
# [MEMDBG] 新出块是否仍残留于同 order free list(此前的重复 put
# 使链表含两条本块 → pop 后还有残条 → 本块将被二次分配,双向写穿)。
# 记录表重叠检测要等下次 pop 同地址才撞见,这里在出块当场提前拦截。
dbg_block: t.CVoid | t.CPtr = t.CVoid(base_ret_d - MEMBUDDY_HEADER_SIZE, t.CPtr)
dbg_hdr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(dbg_block, t.CPtr)), t.CPtr)
dbg_order: t.CInt = t.CInt(t.CUInt64T(dbg_hdr) >> 1)
dbg_cur: t.CVoid | t.CPtr = t.CVoid(self.free_lists[dbg_order], t.CPtr)
dbg_n: t.CSizeT = 0
while t.CUInt64T(dbg_cur) != 0:
if t.CUInt64T(dbg_cur) == t.CUInt64T(dbg_block):
stdio.printf("[MEMDBG] alloc 重复出块: size=%llu block=%llu 仍残留 free list order=%d(重复 put 实锤,终止)\n",
t.CUInt64T(size), t.CUInt64T(dbg_block), dbg_order)
stdio.fflush(None)
stdlib.exit(1)
dup_i += 1
if self._det_count >= self._det_cap:
# 记录表满:stdlib.realloc 翻倍扩容(防 is_alive/_det_probe
# 因容量耗尽漏检——SlotsBugTest 编译 includes 超 2M 次 alloc,
# 满后新块无记录 → is_alive 误报"读取悬空")
new_cap: t.CSizeT = self._det_cap * 2
new_rec: t.CVoid | t.CPtr = t.CVoid(
stdlib.realloc(self._det_arena, new_cap * 16), t.CPtr)
if new_rec is not None:
self._det_arena = new_rec
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(new_rec, t.CPtr))
self._det_cap = new_cap
if self._det_count < self._det_cap:
self._det_records[self._det_count * 2] = base_ret_d + 2
self._det_records[self._det_count * 2 + 1] = t.CUInt64T(size)
self._det_count += 1
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
self._det_probe()
result = t.CVoid(base_ret_d + 2, t.CPtr)
dbg_n += 1
if dbg_n > self.usable_size / MEMBUDDY_MIN_BLOCK + 2:
stdio.printf("[MEMDBG] alloc 扫描 free list order=%d 成环/超长(自检异常,终止)\n", dbg_order)
stdio.fflush(None)
stdlib.exit(1)
dbg_cur = t.CVoid(c.Deref(t.CUInt64T(dbg_cur, t.CPtr)), t.CPtr)
if self._det_count >= self._det_cap:
# 记录表满:stdlib.realloc 翻倍扩容(防 is_alive/_det_probe
# 因容量耗尽漏检——SlotsBugTest 编译 includes 超 2M 次 alloc,
# 满后新块无记录 → is_alive 误报"读取悬空")
new_cap: t.CSizeT = self._det_cap * 2
new_rec: t.CVoid | t.CPtr = t.CVoid(
stdlib.realloc(self._det_arena, new_cap * 16), t.CPtr)
if new_rec is not None:
self._det_arena = new_rec
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(new_rec, t.CPtr))
self._det_cap = new_cap
if self._det_count < self._det_cap:
self._det_records[self._det_count * 2] = rec_ptr_d
self._det_records[self._det_count * 2 + 1] = t.CUInt64T(size)
self._det_count += 1
if self.detection != 0 and (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
self._det_probe()
if self.detection != 0:
result = t.CVoid(base_ret_d + 2, t.CPtr)
if result is None:
# 分配失败诊断(定位"异常 size/池耗尽导致 None → 调用方解引用段错误")
if size != 0 and self.usable is not None:
@@ -751,27 +790,60 @@ class MemBuddy(MemManager):
if self.detection != 0:
# [DET] 返回指针比实际用户区靠后 2 字节,回收时向前偏移 2
p_eff = t.CVoid(t.CUInt64T(ptr) - 2, t.CPtr)
# 从记录表取本条真实 size,free 后把用户区填 0xCD(UAF 写入
# 检测:free 后块被写穿 → 探测时 0xCD 被破坏 → 报警);记录
# 保留并置 free 标志(探测时对仍 free 的块验证 0xCD 完整)。
if self._det_records is not None:
ri: t.CSizeT = 0
while ri < self._det_count:
rp: t.CUInt64T = self._det_records[ri * 2]
rs: t.CUInt64T = self._det_records[ri * 2 + 1]
if rp == t.CUInt64T(ptr) and (rs & (t.CUInt64T(1) << 63)) == 0:
if rs > 0:
string.memset(ptr, MEMBUDDY_FILL_PATTERN, rs)
self._det_records[ri * 2 + 1] = rs | (t.CUInt64T(1) << 63)
break
ri += 1
# 记录表置 free 标志(解耦于 detection,2026-09-04):非 detection
# 也需置位,否则 free 后同地址再 alloc(正常 reuse)被误报重叠。
if self._det_records is not None:
# 从记录表取本条真实 size(detection 下 free 后填 0xCD,UAF
# 写入检测:free 后块被写穿 → 探测时 0xCD 被破坏 → 报警);
# 记录保留并置 free 标志(探测时对仍 free 的块验证 0xCD 完整)。
ri: t.CSizeT = 0
while ri < self._det_count:
rp: t.CUInt64T = self._det_records[ri * 2]
rs: t.CUInt64T = self._det_records[ri * 2 + 1]
if rp == t.CUInt64T(ptr) and (rs & (t.CUInt64T(1) << 63)) == 0:
if self.detection != 0 and rs > 0:
string.memset(ptr, MEMBUDDY_FILL_PATTERN, rs)
self._det_records[ri * 2 + 1] = rs | (t.CUInt64T(1) << 63)
break
ri += 1
if self._is_valid_ptr(p_eff) != 0:
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(p_eff) - MEMBUDDY_HEADER_SIZE, t.CPtr)
stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
stored_val: t.CUInt64T = t.CUInt64T(stored)
order: t.CInt = t.CInt(stored_val >> 1)
if MEMBUDDY_DBG != 0:
# [MEMDBG] 重复归还检测:活跃块(header 奇数)绝不该已在本 order
# free list;命中 = 同块被 put 两次(free list 重复 put 实锤)。
dbg_f: t.CVoid | t.CPtr = t.CVoid(self.free_lists[order], t.CPtr)
dbg_fn: t.CSizeT = 0
while t.CUInt64T(dbg_f) != 0:
if t.CUInt64T(dbg_f) == t.CUInt64T(block):
stdio.printf("[MEMDBG] 重复归还: free(ptr=%llu) block=%llu 已在 free list order=%d(double-put 实锤,终止)\n",
t.CUInt64T(ptr), t.CUInt64T(block), order)
stdio.fflush(None)
stdlib.exit(1)
dbg_fn += 1
if dbg_fn > self.usable_size / MEMBUDDY_MIN_BLOCK + 2:
stdio.printf("[MEMDBG] free 扫描 free list order=%d 成环/超长(自检异常,终止)\n", order)
stdio.fflush(None)
stdlib.exit(1)
dbg_f = t.CVoid(c.Deref(t.CUInt64T(dbg_f, t.CPtr)), t.CPtr)
c.DerefAs(block, t.CVoid(0, t.CPtr))
self._coalesce(block, order)
elif MEMBUDDY_DBG != 0:
# [MEMDBG] 无效/悬空 free(原实现静默忽略):块在本池范围内但 header
# 为偶 = 已被释放/未初始化 → 悬空重复 free(stale 指针)。范围外
# (非本池指针)是正常多池场景,不报。
dbg_eff: t.CUInt64T = t.CUInt64T(p_eff)
dbg_blk: t.CUInt64T = dbg_eff - MEMBUDDY_HEADER_SIZE
if (dbg_eff >= MEMBUDDY_HEADER_SIZE and dbg_blk >= t.CUInt64T(self.usable)
and dbg_blk < t.CUInt64T(self.usable) + self.usable_size):
dbg_hv: t.CUInt64T = t.CUInt64T(t.CVoid(c.Deref(t.CUInt64T(t.CVoid(dbg_blk, t.CPtr), t.CPtr)), t.CPtr))
if (dbg_hv & 1) == 0:
stdio.printf("[MEMDBG] 悬空/重复 free: ptr=%llu block=%llu header=0x%llX(偶数=已释放/未初始化,终止)\n",
t.CUInt64T(ptr), dbg_blk, dbg_hv)
stdio.fflush(None)
stdlib.exit(1)
self._unlock()
return 1
@@ -804,7 +876,8 @@ class MemBuddy(MemManager):
self._rebuild_free_lists()
# [DET] reset 重建全部 free list = 全部块释放:记录表同步清空,
# 防止后续 alloc 复用旧块被误报(与 reset_to 截断同因)。
if self.detection != 0 and self._det_records is not None:
# 2026-09-04 记录表已与 detection 解耦,清空条件同样不能挂 detection。
if self._det_records is not None:
self._det_count = 0
return 1
@@ -898,6 +971,7 @@ class MemBuddy(MemManager):
if mfv_a != t.CUInt16T(MEMBUDDY_DET_MARKER):
stdio.printf("[DET] 下溢写: ptr=%llu size=%llu 前标记=0x%04X(期望 0xCDCD)\n",
p, s, t.CUInt32T(mfv_a))
stdio.fflush(None)
stdlib.exit(1)
m16: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(p + s, t.CPtr))
mv: t.CUInt16T = m16[0]
@@ -938,6 +1012,7 @@ class MemBuddy(MemManager):
stdio.printf("[%zu]sz=%llu ", ci3, cs3 & (free_flag - 1))
ci3 += 1
stdio.printf("\n")
stdio.fflush(None)
stdlib.exit(1)
i += 1
+6 -3
View File
@@ -164,9 +164,12 @@ extern def SSL_get_verify_mode(ssl: SslPtr) -> int
extern def SSL_get_peer_certificate(s: SslPtr) -> X509Ptr
extern def SSL_get1_peer_certificate(s: SslPtr) -> X509Ptr
# 当前加密套件
# const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) → 文本用下句
# const char *SSL_get_cipher_name(const SSL *s) / int SSL_get_cipher_bits
extern def SSL_get_cipher_name(s: SslPtr) -> str
# SSL_get_cipher_name 在 ssl.h 是宏(SSL_CIPHER_get_name(SSL_get_current_cipher(s))),
# FFI 拆成两个真实导出函数调用:
# const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
extern def SSL_get_current_cipher(s: SslPtr) -> SslCipherPtr
# const char *SSL_CIPHER_get_name(const SSL_CIPHER *c)
extern def SSL_CIPHER_get_name(cipher: SslCipherPtr) -> str
# SNI: int SSL_set_tlsext_host_name(SSL *s, const char *name)(宏 → SSL_ctrl)
# const char *SSL_get_servername(const SSL *s, int type)
extern def SSL_get_servername(s: SslPtr, type: int) -> str
+47 -42
View File
@@ -4,61 +4,66 @@ import t, c
# openssl/types.vp — OpenSSL 3.x 不透明对象句柄 typedef
#
# 对接 libcrypto / libssl(OpenSSL 3.x 导出符号)。
# 对象一律按不透明指针 (i8*) 处理,生命周期由 OpenSSL 库管理
# 对象一律按不透明指针 (void*) 处理,生命周期由 OpenSSL 库管理
# (X509_free/SSL_free/BIO_free/CRYPTO_free 等对应释放函数)。
# 链接目标:ViperOpenSSLProject 的 project.vpj 后续配置
# (msys2 mingw64 libcrypto/libssl 或 openssl_358_C 自编译库)。
# 链接目标:ViperOpenSSLProject 的 project.vpj 链接 openssl_358_C
# 自编译静态库(libcrypto.a / libssl.a)。
#
# 注意:typedef 用 `t.CVoid | t.CPtr` 表达(与 vqt6 一致),生成 i8*
# 指针参数,可被 ASan 插桩;纯 `t.CPtr` 会生成 opaque struct 参数,
# opt -passes=asan 会报 invalid type for function argument。
# ============================================================
# ---- 基础上下文 ----
OsslLibCtxPtr: t.CTypedef = t.CPtr # OSSL_LIB_CTX*
EnginePtr: t.CTypedef = t.CPtr # ENGINE*
OpensslInitSettingsPtr: t.CTypedef = t.CPtr # OPENSSL_INIT_SETTINGS*
OsslLibCtxPtr: t.CTypedef = t.CVoid | t.CPtr # OSSL_LIB_CTX*
EnginePtr: t.CTypedef = t.CVoid | t.CPtr # ENGINE*
OpensslInitSettingsPtr: t.CTypedef = t.CVoid | t.CPtr # OPENSSL_INIT_SETTINGS*
# ---- BIO(内存/文件/Socket/Connect)----
BioPtr: t.CTypedef = t.CPtr # BIO*
BioMethodPtr: t.CTypedef = t.CPtr # BIO_METHOD*
BioAddrPtr: t.CTypedef = t.CPtr # BIO_ADDR*
BioAddrInfoPtr: t.CTypedef = t.CPtr # BIO_ADDRINFO*
BioPtr: t.CTypedef = t.CVoid | t.CPtr # BIO*
BioMethodPtr: t.CTypedef = t.CVoid | t.CPtr # BIO_METHOD*
BioAddrPtr: t.CTypedef = t.CVoid | t.CPtr # BIO_ADDR*
BioAddrInfoPtr: t.CTypedef = t.CVoid | t.CPtr # BIO_ADDRINFO*
# ---- EVP(摘要/对称/非对称)----
EvpMdPtr: t.CTypedef = t.CPtr # EVP_MD*
EvpMdCtxPtr: t.CTypedef = t.CPtr # EVP_MD_CTX*
EvpCipherPtr: t.CTypedef = t.CPtr # EVP_CIPHER*
EvpCipherCtxPtr: t.CTypedef = t.CPtr # EVP_CIPHER_CTX*
EvpPkeyPtr: t.CTypedef = t.CPtr # EVP_PKEY*
EvpPkeyCtxPtr: t.CTypedef = t.CPtr # EVP_PKEY_CTX*
EvpEncodeCtxPtr: t.CTypedef = t.CPtr # EVP_ENCODE_CTX*
HmacCtxPtr: t.CTypedef = t.CPtr # HMAC_CTX*
EvpMdPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_MD*
EvpMdCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_MD_CTX*
EvpCipherPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_CIPHER*
EvpCipherCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_CIPHER_CTX*
EvpPkeyPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_PKEY*
EvpPkeyCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_PKEY_CTX*
EvpEncodeCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_ENCODE_CTX*
HmacCtxPtr: t.CTypedef = t.CVoid | t.CPtr # HMAC_CTX*
# ---- X509 / 证书 ----
X509Ptr: t.CTypedef = t.CPtr # X509*
X509NamePtr: t.CTypedef = t.CPtr # X509_NAME*
X509NameEntryPtr: t.CTypedef = t.CPtr # X509_NAME_ENTRY*
X509CrlPtr: t.CTypedef = t.CPtr # X509_CRL*
X509ReqPtr: t.CTypedef = t.CPtr # X509_REQ*
X509ExtensionPtr: t.CTypedef = t.CPtr # X509_EXTENSION*
X509StorePtr: t.CTypedef = t.CPtr # X509_STORE*
X509StoreCtxPtr: t.CTypedef = t.CPtr # X509_STORE_CTX*
X509InfoPtr: t.CTypedef = t.CPtr # X509_INFO*
X509VerifyParamPtr: t.CTypedef = t.CPtr # X509_VERIFY_PARAM*
X509Ptr: t.CTypedef = t.CVoid | t.CPtr # X509*
X509NamePtr: t.CTypedef = t.CVoid | t.CPtr # X509_NAME*
X509NameEntryPtr: t.CTypedef = t.CVoid | t.CPtr # X509_NAME_ENTRY*
X509CrlPtr: t.CTypedef = t.CVoid | t.CPtr # X509_CRL*
X509ReqPtr: t.CTypedef = t.CVoid | t.CPtr # X509_REQ*
X509ExtensionPtr: t.CTypedef = t.CVoid | t.CPtr # X509_EXTENSION*
X509StorePtr: t.CTypedef = t.CVoid | t.CPtr # X509_STORE*
X509StoreCtxPtr: t.CTypedef = t.CVoid | t.CPtr # X509_STORE_CTX*
X509InfoPtr: t.CTypedef = t.CVoid | t.CPtr # X509_INFO*
X509VerifyParamPtr: t.CTypedef = t.CVoid | t.CPtr # X509_VERIFY_PARAM*
# ---- ASN.1 ----
Asn1ObjectPtr: t.CTypedef = t.CPtr # ASN1_OBJECT*
Asn1StringPtr: t.CTypedef = t.CPtr # ASN1_STRING*
Asn1IntegerPtr: t.CTypedef = t.CPtr # ASN1_INTEGER*
Asn1TimePtr: t.CTypedef = t.CPtr # ASN1_TIME*
Asn1OctetStringPtr: t.CTypedef = t.CPtr # ASN1_OCTET_STRING*
Asn1BitStringPtr: t.CTypedef = t.CPtr # ASN1_BIT_STRING*
GeneralNamesPtr: t.CTypedef = t.CPtr # GENERAL_NAMES*
GeneralNamePtr: t.CTypedef = t.CPtr # GENERAL_NAME*
Asn1ObjectPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_OBJECT*
Asn1StringPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_STRING*
Asn1IntegerPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_INTEGER*
Asn1TimePtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_TIME*
Asn1OctetStringPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_OCTET_STRING*
Asn1BitStringPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_BIT_STRING*
GeneralNamesPtr: t.CTypedef = t.CVoid | t.CPtr # GENERAL_NAMES*
GeneralNamePtr: t.CTypedef = t.CVoid | t.CPtr # GENERAL_NAME*
# ---- SSL/TLS ----
SslPtr: t.CTypedef = t.CPtr # SSL*
SslCtxPtr: t.CTypedef = t.CPtr # SSL_CTX*
SslMethodPtr: t.CTypedef = t.CPtr # SSL_METHOD*
SslSessionPtr: t.CTypedef = t.CPtr # SSL_SESSION*
SslPtr: t.CTypedef = t.CVoid | t.CPtr # SSL*
SslCtxPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_CTX*
SslMethodPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_METHOD*
SslSessionPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_SESSION*
SslCipherPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_CIPHER*
# ---- BIGNUM ----
BnPtr: t.CTypedef = t.CPtr # BIGNUM*
BnCtxPtr: t.CTypedef = t.CPtr # BN_CTX*
BnPtr: t.CTypedef = t.CVoid | t.CPtr # BIGNUM*
BnCtxPtr: t.CTypedef = t.CVoid | t.CPtr # BN_CTX*
+1 -1
View File
@@ -226,7 +226,7 @@ def normpath(path: str) -> str:
out_pos: t.CSizeT = 0
i: t.CSizeT = 0
s: str = sep()
s: t.CChar = sep()
# 处理绝对路径前缀
is_absolute: bool = False
+1 -1
View File
@@ -215,7 +215,7 @@ extern def isatty(fd: INT) -> INT
# =============================================================================
# Inline macros (C macros, implemented as normal functions, not marked as t.CExtern)
# Inline macros (C macros, implemented as normal functions, not marked as extern)
# =============================================================================
# st_mode type determination
+12 -13
View File
@@ -82,19 +82,18 @@ class timeval:
# (Windows SOCKET=u64, POSIX fd=int → u64 Zero-Extension Compatible)
# ============================================================
def socket(family: INT, type: INT, protocol: INT) -> u64 | t.CExtern | t.CExport: pass
def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT | t.CExtern | t.CExport: pass
def send(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.CExtern | t.CExport: pass
def recv(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.CExtern | t.CExport: pass
def bind(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT | t.CExtern | t.CExport: pass
def listen(fd: u64, backlog: INT) -> INT | t.CExtern | t.CExport: pass
def accept(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64 | t.CExtern | t.CExport: pass
def setsockopt(fd: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT | t.CExtern | t.CExport: pass
def gethostbyname(name: t.CChar | t.CConst | t.CPtr) -> HostEnt | t.CPtr | t.CExtern | t.CExport: pass
def ntohs(netshort: u16) -> u16 | t.CExtern | t.CExport: pass
def htons(hostshort: u16) -> u16 | t.CExtern | t.CExport: pass
def close(fd: u64) -> INT | t.CExtern | t.CExport: pass
extern def socket(family: INT, type: INT, protocol: INT) -> u64
extern def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT
extern def send(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT
extern def recv(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT
extern def bind(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT
extern def listen(fd: u64, backlog: INT) -> INT
extern def accept(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64
extern def setsockopt(fd: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT
extern def gethostbyname(name: t.CConst | str) -> HostEnt | t.CPtr
extern def ntohs(netshort: u16) -> u16
extern def htons(hostshort: u16) -> u16
extern def close(fd: u64) -> INT
# ============================================================
# Internal Auxiliary Functions
+10 -7
View File
@@ -66,20 +66,23 @@ def strncat(dest: str, src: str, n: t.CSizeT) -> str:
# String length function
def strlen(src: str) -> t.CSizeT | t.CExport:
export def strlen(src: str) -> t.CSizeT:
length: t.CSizeT = 0
for _ in src:
length += 1
return length
# String comparison function
# 注意:str1[0] - str2[0] 是 i8 减法会回绕(0xFF 表示 -1),返回前必须
# int() 提升到 i32 再相减(与下方 memcmp 的 int(p1[i]) - int(p2[i]) 一致),
# 否则 strcmp("abc","abd") 返回 255 而非 -1(StringTest Test 4 根因)。
def strcmp(str1: str, str2: str) -> int:
while str1[0] != '\0' and str2[0] != '\0':
if str1[0] != str2[0]:
return str1[0] - str2[0]
return int(str1[0]) - int(str2[0])
str1 += 1
str2 += 1
return str1[0] - str2[0]
return int(str1[0]) - int(str2[0])
def samestr(str1: str, str2: str) -> bool:
return strcmp(str1, str2) == 0
@@ -90,12 +93,12 @@ def strncmp(str1: str, str2: str, n: t.CSizeT) -> int:
i: t.CSizeT = 0
while str1[0] != '\0' and str2[0] != '\0' and i < n:
if str1[0] != str2[0]:
return str1[0] - str2[0]
return int(str1[0]) - int(str2[0])
str1 += 1
str2 += 1
i += 1
if i < n:
return str1[0] - str2[0]
return int(str1[0]) - int(str2[0])
return 0
@@ -164,7 +167,7 @@ def strspn(s: str, skip: str = " ") -> int:
return si
# Memory set function
def memset(ptr: t.CVoid | t.CPtr, value: int, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport:
export def memset(ptr: t.CVoid | t.CPtr, value: int, num: t.CSizeT) -> t.CVoid | t.CPtr:
# Original implementation:
# p: BYTEPTR = BYTEPTR(ptr)
# i: t.CSizeT
@@ -197,7 +200,7 @@ def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVo
# Memory copy function
def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport:
export def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CPtr:
# Original implementation:
# d: BYTEPTR = BYTEPTR(dest)
# s: BYTEPTR = BYTEPTR(src)
+8 -8
View File
@@ -12,7 +12,7 @@ def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt:
num //= base
return count
def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid | t.CExport:
export def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid:
if buf is None or rule is None: return
vsnprintf(buf, 0x7FFFFFFF, rule, args)
@@ -20,33 +20,33 @@ def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt:
if buf is None or rule is None: return 0
return vsnprintf(buf, 0x7FFFFFFF, rule, args)
def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.CExport:
export def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt:
if fmt is None: return 0
if buf is None or size == 0:
return vsnprintf(None, 0, fmt, args)
ret: t.CInt = vsnprintf(buf, size, fmt, args)
ret: int = vsnprintf(buf, size, fmt, args)
return ret
# Check floating-point special values (IEEE 754)
# Return: 0=normal, 1=+inf, 2=-inf, 3=nan
def _check_special_float(fv: t.CDouble) -> t.CInt:
def _check_special_float(fv: double) -> int:
fbits: t.CUInt64T = 0
c.Load(c.Addr(fbits), c.Addr(fv))
if ((fbits >> 52) & 0x7FF) != 0x7FF:
return 0
is_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0
is_neg: int = 1 if (fbits >> 63) != 0 else 0
if (fbits & 0x000FFFFFFFFFFFFF) == 0:
if is_neg:
return 2
return 1
return 3
def vsnprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, ap: t.CChar | t.CPtr) -> t.CInt | t.CExport:
export def vsnprintf(buf: bytes, size: t.CSizeT, fmt: str, ap: t.CChar | t.CPtr) -> int:
if fmt is None: return 0
# 长度探测模式:buf is None 时只计算格式化后长度,不实际写入
# _step=0 使 ptr 不前进,反复写入同一个 dummy 字节(无害),write_count 正确累加
count_mode: t.CInt = 0
_step: t.CInt = 1
count_mode: int = 0
_step: int = 1
_dummy: t.CChar = '\0'
if buf is None or size == 0:
count_mode = 1
+202 -39
View File
@@ -19,8 +19,13 @@
#include <QPainter>
#include <QPainterPath>
#include <QStyleOptionButton>
#include <QStyleOptionViewItem>
#include <QHash>
#include <QSet>
#include <QList>
#include <QTimer>
#include <QShowEvent>
#include <QProxyStyle>
#include <QComboBox>
#include <QListWidget>
#include <QProgressBar>
@@ -853,6 +858,70 @@ extern "C" VQT6_API int vqt6_qplaintextedit_line_count(void* pte) {
// QCheckBox / QRadioButton
// ============================================================
// ------------------------------------------------------------------
// 共享的“勾选指示器”渲染(自绘 QCheckBox 与树形勾选代理复用同一套绘制)
// ------------------------------------------------------------------
static QColor vqt6_mix_color(const QColor& a, const QColor& b, qreal t) {
if (t < 0.0) t = 0.0;
else if (t > 1.0) t = 1.0;
return QColor::fromRgbF(a.redF() + (b.redF() - a.redF()) * t,
a.greenF() + (b.greenF() - a.greenF()) * t,
a.blueF() + (b.blueF() - a.blueF()) * t,
a.alphaF() + (b.alphaF() - a.alphaF()) * t);
}
// 规整指示区:内部收缩 1px;过小时回退为 16×16 并居中
static QRectF vqt6_indicator_box(const QRect& r) {
QRectF box(r.left() + 1.0, r.top() + 1.0, r.width() - 2.0, r.height() - 2.0);
if (box.width() < 10.0 || box.height() < 10.0) {
box = QRectF(0, 0, 16, 16);
box.moveCenter(QRectF(r).center());
}
return box;
}
// 统一的指示器绘制:圆角框 + QPalette 配色 + 对勾(或半选横线)
// box —— 绘制区域(约 16~18px 见方)
// pal —— 控件调色板(决定深浅主题配色)
// enabled —— 是否可用
// progress —— 勾选过渡进度(0=未选 1=选中)
// partial —— 半选态(画横线,progress 按 1 传入)
static void vqt6_paint_check_indicator(QPainter* p, const QRectF& box, const QPalette& pal,
bool enabled, qreal progress, bool partial) {
p->setRenderHint(QPainter::Antialiasing, true);
const qreal t = progress < 0.0 ? 0.0 : (progress > 1.0 ? 1.0 : progress);
const QColor cBase = enabled ? pal.base().color() : pal.window().color();
const QColor cOn = enabled ? pal.highlight().color() : pal.button().color();
const QColor cB0 = enabled ? pal.text().color() : pal.placeholderText().color();
const QColor cB1 = enabled ? pal.highlight().color() : pal.buttonText().color();
const QColor fill = vqt6_mix_color(cBase, cOn, t);
const QColor border = vqt6_mix_color(cB0, cB1, t);
QPainterPath path;
path.addRoundedRect(box, 3.0, 3.0);
p->fillPath(path, fill);
QPen bpen(border, 1.4);
p->setPen(bpen);
p->drawPath(path);
if (!enabled || t <= 0.003) return;
QColor gc = pal.highlightedText().color();
gc.setAlphaF(gc.alphaF() * t);
const qreal x0 = box.left(), y0 = box.top(), w = box.width(), h = box.height();
if (partial) {
QPen dpen(gc, 1.6);
dpen.setCapStyle(Qt::RoundCap);
p->setPen(dpen);
p->drawLine(QPointF(x0 + w * 0.22, y0 + h * 0.5), QPointF(x0 + w * 0.78, y0 + h * 0.5));
} else {
QPen cpen(gc, 1.6 + 0.8 * t);
cpen.setCapStyle(Qt::RoundCap);
p->setPen(cpen);
p->drawLine(QPointF(x0 + w * 0.24, y0 + h * 0.54), QPointF(x0 + w * 0.43, y0 + h * 0.73));
p->drawLine(QPointF(x0 + w * 0.43, y0 + h * 0.73), QPointF(x0 + w * 0.78, y0 + h * 0.28));
}
}
// 自绘 QCheckBox:矢量框+对勾按 QPalette 绘制,勾选带过渡动画
class vqt6_CheckBox : public QCheckBox {
public:
@@ -875,41 +944,12 @@ protected:
r = QRect(0, 0, 16, 16);
r.moveCenter(QPoint(rect().left() + 12, rect().center().y()));
}
QRectF box(r.left() + 1.0, r.top() + 1.0, r.width() - 2.0, r.height() - 2.0);
if (box.width() < 10.0 || box.height() < 10.0) {
box = QRectF(0, 0, 16, 16);
box.moveCenter(QPointF(r.center().x(), r.center().y()));
}
const bool en = isEnabled();
qreal t = m_progress;
if (t < 0.0) t = 0.0;
else if (t > 1.0) t = 1.0;
QColor cBase = en ? pal.base().color() : pal.window().color();
QColor cOn = en ? pal.highlight().color() : pal.button().color();
QColor cBorder0 = en ? pal.text().color() : pal.placeholderText().color();
QColor cBorder1 = en ? pal.highlight().color() : pal.buttonText().color();
QColor fill = mix(cBase, cOn, t);
QColor border = mix(cBorder0, cBorder1, t);
QPainterPath path;
path.addRoundedRect(box, 3.0, 3.0);
p.fillPath(path, fill);
QPen bpen(border, 1.4);
p.setPen(bpen);
p.drawPath(path);
if (en && t > 0.003) {
QColor gc = pal.highlightedText().color();
gc.setAlphaF(gc.alphaF() * t);
QPen cpen(gc, 1.6 + 0.8 * t);
cpen.setCapStyle(Qt::RoundCap);
p.setPen(cpen);
const qreal x0 = box.left(), y0 = box.top(), w = box.width(), h = box.height();
p.drawLine(QPointF(x0 + w * 0.24, y0 + h * 0.54), QPointF(x0 + w * 0.43, y0 + h * 0.73));
p.drawLine(QPointF(x0 + w * 0.43, y0 + h * 0.73), QPointF(x0 + w * 0.78, y0 + h * 0.28));
}
// 框 + 对勾:与树形勾选共用同一渲染(含动画进度)
vqt6_paint_check_indicator(&p, vqt6_indicator_box(r), pal, isEnabled(), m_progress, false);
// 文本
QRect lr = style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, this);
if (!lr.isEmpty() && !lr.isNull()) {
p.setPen(QPen(en ? pal.text() : pal.placeholderText(), 1.0));
p.setPen(QPen(isEnabled() ? pal.text() : pal.placeholderText(), 1.0));
p.drawText(lr, Qt::AlignLeft | Qt::AlignVCenter, text());
}
}
@@ -949,13 +989,6 @@ private:
m_progress = m_target;
m_timer.stop();
}
static QColor mix(const QColor& a, const QColor& b, qreal t) {
return QColor::fromRgbF(a.redF() + (b.redF() - a.redF()) * t,
a.greenF() + (b.greenF() - a.greenF()) * t,
a.blueF() + (b.blueF() - a.blueF()) * t,
a.alphaF() + (b.alphaF() - a.alphaF()) * t);
}
};
extern "C" VQT6_API void* vqt6_qcheckbox_create(void) {
@@ -1002,6 +1035,136 @@ extern "C" VQT6_API int vqt6_qcheckbox_is_tristate(void* cb) {
return static_cast<QCheckBox*>(cb)->isTristate() ? 1 : 0;
}
// ============================================================
// item-view(QTreeWidget 等)勾选框自绘代理
// 拦截 PE_IndicatorItemViewItemCheck,复用 vqt6_paint_check_indicator,
// 与自绘 QCheckBox 观感一致(含勾选过渡动画:QTreeWidget 勾选变化时
// 按 60fps 指数衰减驱动对应 item 重绘,动画节奏与复选框完全相同)。
// 采用 QProxyStyle 默认构造(基样式按需自动创建),应用 setStyle 后由
// Qt 管理生命周期 —— 与 Qt 官方 QProxyStyle 示例一致,避免基样式
// 所有权/悬空问题。
// ============================================================
class vqt6_CheckProxyStyle : public QProxyStyle {
public:
vqt6_CheckProxyStyle() : QProxyStyle() {
m_timer.setInterval(16);
QObject::connect(&m_timer, &QTimer::timeout, this, [this]() { advance(); });
}
void drawPrimitive(PrimitiveElement element, const QStyleOption* option,
QPainter* painter, const QWidget* widget) const override {
if (element == PE_IndicatorItemViewItemCheck && option != nullptr && painter != nullptr) {
drawItemCheck(option, painter, widget);
return;
}
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
private:
struct AnimState {
qreal progress = 0.0; // 当前绘制进度 0..1
qreal target = 0.0; // 目标进度
};
// 勾选动画记录(键 = QTreeWidgetItem* 指针值)
mutable QHash<quintptr, AnimState> m_anims;
// 已绑定 itemChanged 的树视图(避免重复连接)
mutable QSet<const QTreeWidget*> m_hooked;
// 动画期间需要定时重绘的树视图
mutable QSet<QTreeWidget*> m_repaint;
mutable QTimer m_timer;
void drawItemCheck(const QStyleOption* option, QPainter* painter, const QWidget* widget) const {
const bool enabled = (option->state & QStyle::State_Enabled) != 0;
const bool on = (option->state & QStyle::State_On) != 0;
const bool partial = (option->state & QStyle::State_NoChange) != 0;
qreal progress = (on || partial) ? 1.0 : 0.0;
// 懒绑定 QTreeWidget:勾选变化时驱动对应 item 的过渡动画
QTreeWidget* tw = (widget != nullptr)
? const_cast<QTreeWidget*>(qobject_cast<const QTreeWidget*>(widget)) : nullptr;
if (tw != nullptr) {
if (!m_hooked.contains(tw)) {
m_hooked.insert(tw);
QObject::connect(tw, &QTreeWidget::itemChanged, this,
[this, tw](QTreeWidgetItem* item, int) { onItemChanged(tw, item); });
}
const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option);
if (vopt != nullptr && vopt->index.isValid()) {
const quintptr key = quintptr(vopt->index.internalPointer());
auto it = m_anims.constFind(key);
if (it != m_anims.constEnd())
progress = it->progress;
}
}
const QPalette& pal = (widget != nullptr) ? widget->palette()
: QApplication::palette();
vqt6_paint_check_indicator(painter, vqt6_indicator_box(option->rect),
pal, enabled, progress, partial);
}
void onItemChanged(QTreeWidget* tw, QTreeWidgetItem* item) const {
if (tw == nullptr || item == nullptr) return;
const Qt::CheckState cs = item->checkState(0);
const bool on = (cs == Qt::Checked || cs == Qt::PartiallyChecked);
const qreal target = on ? 1.0 : 0.0;
const quintptr key = quintptr(static_cast<void*>(item));
auto it = m_anims.find(key);
if (it == m_anims.end()) {
// 从“变化前”的观感出发开始过渡(与复选框一致:勾选=淡入对勾,
// 取消勾选=淡出),中途连续切换时延续当前进度。
AnimState st;
st.progress = (target > 0.5) ? 0.0 : 1.0;
st.target = target;
m_anims.insert(key, st);
} else {
it->target = target;
}
if (!tw->isVisible()) {
// 建页/初始化阶段的程序化勾选:直接落定,不产生无谓动画
m_anims.remove(key);
return;
}
m_repaint.insert(tw);
tw->viewport()->update();
if (!m_timer.isActive())
m_timer.start();
}
void advance() const {
QList<quintptr> done;
for (auto it = m_anims.begin(); it != m_anims.end(); ++it) {
AnimState& st = it.value();
st.progress += (st.target - st.progress) * 0.25;
if (qAbs(st.target - st.progress) < 0.005) {
st.progress = st.target;
done.append(it.key());
}
}
for (quintptr k : done)
m_anims.remove(k);
for (QTreeWidget* tw : m_repaint) {
if (tw != nullptr && tw->viewport() != nullptr)
tw->viewport()->update();
}
if (m_anims.isEmpty()) {
m_repaint.clear();
m_timer.stop();
}
}
};
extern "C" VQT6_API void vqt6_enable_custom_item_checks(void* app) {
QApplication* a = (app != nullptr) ? static_cast<QApplication*>(app)
: static_cast<QApplication*>(QApplication::instance());
if (a == nullptr) return;
static bool s_custom_checks_enabled = false;
if (s_custom_checks_enabled) return; // 幂等:只安装一次
s_custom_checks_enabled = true;
a->setStyle(new vqt6_CheckProxyStyle());
}
extern "C" VQT6_API void* vqt6_qradiobutton_create(void) {
return new QRadioButton();
}
+1
View File
@@ -25,6 +25,7 @@ VQT6_API int vqt6_qapplication_desktop_height(void* app);
VQT6_API void vqt6_qapplication_set_quit_on_last_window_closed(void* app, int quit);
VQT6_API int vqt6_qapplication_quit_on_last_window_closed(void* app);
VQT6_API void vqt6_qapplication_set_theme_palette(void* app, int theme);
VQT6_API void vqt6_enable_custom_item_checks(void* app);
// ============================================================
// QWidget
+1
View File
@@ -21,6 +21,7 @@ def vqt6_qapplication_desktop_height(app: QtAppPtr) -> t.CInt | t.State: pass
def vqt6_qapplication_set_quit_on_last_window_closed(app: QtAppPtr, quit: t.CInt) -> t.State: pass
def vqt6_qapplication_quit_on_last_window_closed(app: QtAppPtr) -> t.CInt | t.State: pass
def vqt6_qapplication_set_theme_palette(app: QtAppPtr, theme: t.CInt) -> t.State: pass
def vqt6_enable_custom_item_checks(app: QtAppPtr) -> t.State: pass
# ============================================================
+1 -1
View File
@@ -129,7 +129,7 @@ class File:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_write: return FRESULT.ERR_PERM
bytes_written: ULONG = 0
result: BOOL = w32.win32file.WriteFile(self.handle, buf, count, t.CPtr(c.Addr(bytes_written)), None)
result: BOOL = w32.win32file.WriteFile(self.handle, buf, count, c.Addr(bytes_written), None)
if result == 0: return FRESULT.ERR_IO
return LONG(bytes_written)
+86 -46
View File
@@ -24,7 +24,9 @@ import t, c
from stdint import *
import stdlib
import string
import w32.fileio as fio
import viperlib
import w32.win32base as wb
import w32.win32file as wf
import zlib.pyzlib as zpy
@@ -71,6 +73,16 @@ def zipfile_set_error(code: t.CInt, msg: str):
zipfile_error_msg[0] = '\0'
def zipfile_set_error_win(code: t.CInt, msg: str, err: ULONG):
global zipfile_error_code_val, zipfile_error_msg
zipfile_error_code_val = code
if err != 0:
viperlib.snprintf(zipfile_error_msg, 256, "%s (win32 err=%u)", msg, err)
else:
string.strncpy(zipfile_error_msg, msg, 255)
zipfile_error_msg[255] = '\0'
def error_code() -> t.CInt:
return zipfile_error_code_val
@@ -124,31 +136,47 @@ def zf_w32le(h: BYTEPTR, v: t.CUInt32T):
h[3] = (v >> 24) & 0xFF
def zf_fwrite_all(f: fio.File | t.CPtr, p: BYTEPTR, n: t.CSizeT) -> t.CInt:
# 所有文件打开都允许读/写/删共享,避免句柄互斥
_ZF_SHARE: t.CDefine = 7 # FILE_SHARE_READ|WRITE|DELETE
def zf_share_flags() -> ULONG:
return ULONG(_ZF_SHARE)
def zf_write_all(h: wb.HANDLE, p: BYTEPTR, n: t.CSizeT) -> t.CInt:
done: t.CSizeT = 0
while done < n:
chunk: t.CSizeT = n - done
if chunk > 0xFFFFFF00:
chunk = 0xFFFFFF00
w: LONG = f.write(p + done, ULONG(chunk))
if w <= 0:
zipfile_set_error(ZIP_ERR_IO, "write failed")
written: ULONG = 0
ok: BOOL = wf.WriteFile(h, p + done, ULONG(chunk), c.Addr(written), None)
if ok == 0 or written == 0:
global zipfile_error_code_val, zipfile_error_msg
zipfile_error_code_val = ZIP_ERR_IO
viperlib.snprintf(zipfile_error_msg, 256,
"write failed (win32_err=%u)", wb.GetLastError())
return ZIP_ERR_IO
done += t.CSizeT(w)
done += t.CSizeT(written)
return ZIP_ERR_OK
def zf_fread_all(f: fio.File | t.CPtr, p: BYTEPTR, n: t.CSizeT) -> t.CInt:
def zf_read_all(h: wb.HANDLE, p: BYTEPTR, n: t.CSizeT) -> t.CInt:
done: t.CSizeT = 0
while done < n:
chunk: t.CSizeT = n - done
if chunk > 0xFFFFFF00:
chunk = 0xFFFFFF00
rd: LONG = f.read(p + done, ULONG(chunk))
if rd <= 0:
zipfile_set_error(ZIP_ERR_IO, "read failed")
bytes_read: ULONG = 0
ok: BOOL = wf.ReadFile(h, p + done, ULONG(chunk), c.Addr(bytes_read), None)
if ok == 0 or bytes_read == 0:
global zipfile_error_code_val, zipfile_error_msg
zipfile_error_code_val = ZIP_ERR_IO
viperlib.snprintf(zipfile_error_msg, 256,
"read failed (win32_err=%u)", wb.GetLastError())
return ZIP_ERR_IO
done += t.CSizeT(rd)
done += t.CSizeT(bytes_read)
return ZIP_ERR_OK
@@ -156,27 +184,30 @@ def zf_read_whole(path: str, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not out_len:
zipfile_set_error(ZIP_ERR_OPEN, "out_len is None")
return None
f: fio.File | t.CPtr = fio.File(path, fio.MODE.R)
if f.closed:
zipfile_set_error(ZIP_ERR_OPEN, "cannot open file for reading")
h: wb.HANDLE = wf.CreateFileA(
path, wf.GENERIC_READ, zf_share_flags(),
None, wf.OPEN_EXISTING, wf.FILE_ATTRIBUTE_NORMAL, None)
if h == wb.INVALID_HANDLE_VALUE:
zipfile_set_error_win(ZIP_ERR_OPEN, "cannot open file for reading", wb.GetLastError())
return None
sz64: LONGLONG = f.size()
if sz64 < 0:
f.close()
li: wb.LARGE_INTEGER = wb.LARGE_INTEGER()
ok_size: BOOL = wf.GetFileSizeEx(h, t.CPtr(c.Addr(li)))
if ok_size == 0:
wb.CloseHandle(h)
zipfile_set_error(ZIP_ERR_IO, "cannot get file size")
return None
sz: t.CSizeT = t.CSizeT(sz64)
sz: t.CSizeT = t.CSizeT(li.QuadPart)
if sz == 0:
f.close()
wb.CloseHandle(h)
zipfile_set_error(ZIP_ERR_NOT_ZIP, "empty file is not a zip archive")
return None
buf: BYTEPTR = BYTEPTR(stdlib.malloc(sz))
if not buf:
f.close()
wb.CloseHandle(h)
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return None
rc: t.CInt = zf_fread_all(f, buf, sz)
f.close()
rc: t.CInt = zf_read_all(h, buf, sz)
wb.CloseHandle(h)
if rc != ZIP_ERR_OK:
stdlib.free(buf)
return None
@@ -186,8 +217,11 @@ def zf_read_whole(path: str, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
# ============================================================
# 条目信息(目录项)
# 注意: 节点为显式 calloc 分配(@t.Object 裸结构,无 GC 追踪),
# 由 ZipFile 负责释放——避免 GC 实例经 | t.CPtr 联合字段引用被回收。
# ============================================================
@t.Object
class ZipInfo:
filename: bytes # 原始字节名(含 \0,zipfile 持有并负责释放)
name_len: t.CSizeT
@@ -198,16 +232,6 @@ class ZipInfo:
header_offset: t.CSizeT # 本地文件头偏移
next: "ZipInfo" | t.CPtr # 链表(保持写入/目录顺序)
def __init__(self):
self.filename = None
self.name_len = 0
self.compress_type = ZIP_STORED
self.crc32 = 0
self.compress_size = 0
self.file_size = 0
self.header_offset = 0
self.next = None
# ============================================================
# ZipFile
@@ -217,7 +241,7 @@ class ZipFile:
path: bytes
mode: t.CInt # 0 = 读,1 = 写
compression: t.CInt # write() 未显式指定时的压缩类型
fh: fio.File | t.CPtr # 写模式句柄
fh: wb.HANDLE # 写模式句柄(裸 win32 CreateFileA)
data: BYTEPTR # 读模式:整个归档的内存副本
data_len: t.CSizeT
info_head: ZipInfo | t.CPtr
@@ -240,9 +264,10 @@ class ZipFile:
self.pos = 0
self.ok = 0
self.closed = 0
if mode == "r":
# 注意: 字符串必须用 strcmp 比较(== 只会比较指针)
if string.strcmp(mode, "r") == 0:
self.mode = 0
elif mode == "w":
elif string.strcmp(mode, "w") == 0:
self.mode = 1
else:
zipfile_set_error(ZIP_ERR_OPEN, "mode must be 'r' or 'w'")
@@ -261,9 +286,11 @@ class ZipFile:
self.closed = 1
return
else:
self.fh = fio.File(path, fio.MODE.W)
if self.fh.closed:
zipfile_set_error(ZIP_ERR_OPEN, "cannot create file for writing")
self.fh = wf.CreateFileA(
path, wf.GENERIC_WRITE, zf_share_flags(),
None, wf.CREATE_ALWAYS, wf.FILE_ATTRIBUTE_NORMAL, None)
if self.fh == wb.INVALID_HANDLE_VALUE:
zipfile_set_error_win(ZIP_ERR_OPEN, "cannot create file for writing", wb.GetLastError())
self.fh = None
self.closed = 1
return
@@ -278,13 +305,18 @@ class ZipFile:
n.filename = None
nxt: ZipInfo | t.CPtr = n.next
n.next = None
stdlib.free(n)
n = nxt
self.info_head = None
self.info_tail = None
self.info_count = 0
def _append_info(self) -> ZipInfo | t.CPtr:
node: ZipInfo | t.CPtr = ZipInfo()
node: ZipInfo | t.CPtr = stdlib.calloc(1, ZipInfo.__sizeof__())
if not node:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return None
node.next = None
if self.info_tail is None:
self.info_head = node
else:
@@ -354,6 +386,9 @@ class ZipFile:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return ZIP_ERR_MEMORY
node: ZipInfo | t.CPtr = self._append_info()
if node is None:
stdlib.free(dup)
return ZIP_ERR_MEMORY
node.filename = dup
node.name_len = t.CSizeT(nlen)
node.compress_type = t.CInt(method)
@@ -514,12 +549,12 @@ class ZipFile:
zf_w32le(hdr + 18, t.CUInt32T(plen))
zf_w32le(hdr + 22, t.CUInt32T(data_len))
zf_w16le(hdr + 26, t.CUInt32T(name_len))
rc: t.CInt = zf_fwrite_all(self.fh, hdr, 30)
rc: t.CInt = zf_write_all(self.fh, hdr, 30)
stdlib.free(hdr)
if rc == ZIP_ERR_OK:
rc = zf_fwrite_all(self.fh, arcname, name_len)
rc = zf_write_all(self.fh, arcname, name_len)
if rc == ZIP_ERR_OK:
rc = zf_fwrite_all(self.fh, payload, plen)
rc = zf_write_all(self.fh, payload, plen)
if ctype == ZIP_DEFLATED:
stdlib.free(payload)
if rc != ZIP_ERR_OK:
@@ -531,6 +566,9 @@ class ZipFile:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return ZIP_ERR_MEMORY
node: ZipInfo | t.CPtr = self._append_info()
if node is None:
stdlib.free(dup)
return ZIP_ERR_MEMORY
node.filename = dup
node.name_len = name_len
node.compress_type = ctype
@@ -565,9 +603,11 @@ class ZipFile:
zf_w32le(hdr + 24, t.CUInt32T(n.file_size))
zf_w16le(hdr + 28, t.CUInt32T(n.name_len))
zf_w32le(hdr + 42, t.CUInt32T(n.header_offset))
rc = zf_fwrite_all(self.fh, hdr, 46)
rc = zf_write_all(self.fh, hdr, 46)
if rc == ZIP_ERR_OK:
rc = zf_fwrite_all(self.fh, n.filename, n.name_len)
rc = zf_write_all(self.fh, n.filename, n.name_len)
if rc == ZIP_ERR_OK:
self.pos = self.pos + 46 + n.name_len
n = n.next
stdlib.free(hdr)
if rc != ZIP_ERR_OK:
@@ -584,7 +624,7 @@ class ZipFile:
zf_w16le(e + 10, t.CUInt32T(self.info_count))
zf_w32le(e + 12, t.CUInt32T(cd_size))
zf_w32le(e + 16, t.CUInt32T(cd_start))
rc = zf_fwrite_all(self.fh, e, 22)
rc = zf_write_all(self.fh, e, 22)
stdlib.free(e)
if rc != ZIP_ERR_OK:
zipfile_set_error(ZIP_ERR_IO, "write EOCD failed")
@@ -596,7 +636,7 @@ class ZipFile:
rc: t.CInt = ZIP_ERR_OK
if self.mode == 1 and self.fh is not None:
rc = self._finish_write()
self.fh.close()
wb.CloseHandle(self.fh)
self.fh = None
elif self.mode == 0:
if self.data is not None:
+17 -10
View File
@@ -52,8 +52,11 @@ class zdeflate_stream:
attempts += 1
return best_len if (best_len >= zdef.ZDEFLATE_MIN_MATCH) else 0
def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT):
if pos + 2 < pos: return
def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT, data_len: t.CSizeT):
# 只在还能作为匹配起点的位置维护 hash(pos+2 >= data_len 的尾部
# 字节不会再被 find_match 引用,且 zdeflate_hash 会读 pos..pos+2,
# 越过末尾则越界——见 ASan heap-buffer-overflow)
if pos + 2 >= data_len: return
h: t.CUnsignedInt = zdeflate_hash(data + pos)
self.hash_prev[pos & zdef.ZDEFLATE_WINDOW_MASK] = self.hash_head[h]
self.hash_head[h] = t.CInt(pos)
@@ -83,11 +86,11 @@ class zdeflate_stream:
if extra > 0:
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
for i in range(match_len):
self.update_hash(data, pos + i)
self.update_hash(data, pos + i, length)
pos += match_len
else:
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
self.update_hash(data, pos)
self.update_hash(data, pos, length)
pos += 1
lit_tree.encode_symbol(256, c.Addr(self.writer))
@@ -111,11 +114,11 @@ class zdeflate_stream:
if extra > 0:
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
for j in range(match_len):
self.update_hash(data, pos + j)
self.update_hash(data, pos + j, length)
pos += match_len
else:
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
self.update_hash(data, pos)
self.update_hash(data, pos, length)
pos += 1
lit_tree.encode_symbol(256, c.Addr(self.writer))
@@ -270,11 +273,11 @@ def zdeflate_count_freqs(lit_freqs: INTPTR, dist_freqs: INTPTR,
lit_freqs[len_sym] += 1
dist_freqs[zdeflate_dist_to_symbol(best_dist)] += 1
for i in range(match_len):
zdeflate_stream.update_hash(s, data, pos + i)
zdeflate_stream.update_hash(s, data, pos + i, length)
pos += match_len
else:
lit_freqs[data[pos]] += 1
zdeflate_stream.update_hash(s, data, pos)
zdeflate_stream.update_hash(s, data, pos, length)
pos += 1
lit_freqs[256] = 1
@@ -329,7 +332,9 @@ def zdeflate_count_cl_freqs(all_lengths: INTPTR, total: t.CInt, cl_freqs: INTPTR
if count > 6: count = 6
cl_freqs[16] += 1
run -= count
i += run
i += count
# 剩余的 1~2 个相同长度值不静默跳过,交由外层循环
# 按字面量(符号 val)逐个统计,保证总覆盖数恰为 total
def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt,
w: zdef.zbit_writer | t.CPtr, cl_tree: zhuff.zhuff_tree | t.CPtr):
@@ -367,7 +372,9 @@ def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt,
cl_tree.encode_symbol(16, w)
w.write_bits(count - 3, 2)
run -= count
i += run
i += count
# 剩余的 1~2 个相同长度值不静默跳过,交由外层循环
# 按字面量(符号 val)逐个编码,保证 RLE 覆盖总数恰为 total
+2 -1
View File
@@ -70,7 +70,8 @@ class zinflate_stream:
self.is_gzip = 1
if self.input_pos + 10 > self.input_len: return -3
self.input_pos += 10
flg: BYTE = self.input_data[self.input_pos - 6]
# FLG 位于 gzip 头第 4 字节(偏移 3),即 self.input_pos - 7
flg: BYTE = self.input_data[self.input_pos - 7]
if flg & 0x04:
if self.input_pos + 2 > self.input_len: return -3
xlen: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8)