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:
1 parent
e2dd0fb18f
commit
2992674783
42 files changed
+3506
-2941
No files matched your search
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+79
-79
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+280
-280
File diff suppressed because it is too large.
Load diff
+47
-43
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+157
-119
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
# 只验证有函数体的定义,跳过声明
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user