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:
|
def inb(port: t.CUInt16T) -> t.CUInt8T:
|
||||||
value: t.CUInt32T
|
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)}
|
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||||||
in al, dx
|
in al, dx
|
||||||
movzx eax, al
|
movzx eax, al""",
|
||||||
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
|
|
||||||
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
|
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)
|
return t.CUInt8T(value)
|
||||||
|
|
||||||
def outb(port: t.CUInt16T, value: t.CUInt8T):
|
def outb(port: t.CUInt16T, value: t.CUInt8T):
|
||||||
@@ -40,10 +36,9 @@ def inw(port: t.CUInt16T) -> t.CUInt16T:
|
|||||||
value: t.CUInt32T
|
value: t.CUInt32T
|
||||||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||||||
in ax, dx
|
in ax, dx
|
||||||
movzx eax, ax
|
movzx eax, ax""",
|
||||||
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
|
|
||||||
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
|
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)
|
return t.CUInt16T(value)
|
||||||
|
|
||||||
def outw(port: t.CUInt16T, value: t.CUInt16T):
|
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:
|
def inl(port: t.CUInt16T) -> t.CUInt32T:
|
||||||
value: t.CUInt32T
|
value: t.CUInt32T
|
||||||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||||||
in eax, dx
|
in eax, dx""",
|
||||||
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
|
|
||||||
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
|
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
|
return value
|
||||||
|
|
||||||
def outl(port: t.CUInt16T, value: t.CUInt32T):
|
def outl(port: t.CUInt16T, value: t.CUInt32T):
|
||||||
|
|||||||
+12
-14
@@ -37,9 +37,7 @@ from .exprs import (
|
|||||||
Constant, NamedExpr, Attribute, Subscript, Starred, Name,
|
Constant, NamedExpr, Attribute, Subscript, Starred, Name,
|
||||||
List, Tuple, Slice,
|
List, Tuple, Slice,
|
||||||
Call, Compare, OpNode,
|
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,
|
name_get_id, constant_get_str_val,
|
||||||
binop_get_left, binop_get_right,
|
binop_get_left, binop_get_right,
|
||||||
attribute_get_attr, attribute_get_value,
|
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)
|
# Global Memory Pool Pointer (follows project rules: declare _mbuddy)
|
||||||
# User initializes in main: ast._mbuddy = memhub.MemBuddy(arena, size)
|
# User initializes in main: ast._mbuddy = memhub.MemBuddy(arena, size)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
_mbuddy: rowptr[memhub.MemBuddy]
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Common API: parse
|
# 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.
|
"""Parse Python source code, return the AST Module node.
|
||||||
|
|
||||||
Parameters:
|
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:
|
if src is None or pool is None:
|
||||||
return None
|
return None
|
||||||
_init_tables(pool)
|
_init_tables(pool)
|
||||||
lx: Lexer | t.CPtr = new_lexer(pool)
|
lx: rowptr[Lexer] = new_lexer(pool)
|
||||||
if lx is None:
|
if lx is None:
|
||||||
return None
|
return None
|
||||||
_lexer_init(lx, src, pool)
|
_lexer_init(lx, src, pool)
|
||||||
tokens: Token | t.CPtr = tokenize(lx)
|
tokens: rowptr[Token] = tokenize(lx)
|
||||||
if tokens is None:
|
if tokens is None:
|
||||||
return None
|
return None
|
||||||
tree: AST | t.CPtr = parse_tokens(pool, tokens)
|
tree: rowptr[AST] = parse_tokens(pool, tokens)
|
||||||
return tree
|
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.
|
"""Parse a single expression, return the Expression node.
|
||||||
|
|
||||||
Parameters:
|
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
|
pool: memhub.MemManager instance, to allocate AST nodes
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Expression node, or None
|
Expression node (包装节点,body 字段为实际表达式), or None
|
||||||
"""
|
"""
|
||||||
if src is None or pool is None:
|
if src is None or pool is None:
|
||||||
return None
|
return None
|
||||||
_init_tables(pool)
|
_init_tables(pool)
|
||||||
lx: Lexer | t.CPtr = new_lexer(pool)
|
lx: rowptr[Lexer] = new_lexer(pool)
|
||||||
if lx is None: return None
|
if lx is None: return None
|
||||||
_lexer_init(lx, src, pool)
|
_lexer_init(lx, src, pool)
|
||||||
tokens: Token | t.CPtr = tokenize(lx)
|
tokens: rowptr[Token] = tokenize(lx)
|
||||||
if tokens is None: return None
|
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
|
if ps is None: return None
|
||||||
_parser_init(ps, tokens, pool)
|
_parser_init(ps, tokens, pool)
|
||||||
body: AST | t.CPtr = _parse_test(ps)
|
body: rowptr[AST] = _parse_test(ps)
|
||||||
return Expression(pool, body)
|
return Expression(pool, body)
|
||||||
+63
-63
@@ -15,23 +15,23 @@ from .base import (
|
|||||||
|
|
||||||
class ExceptHandler(AST):
|
class ExceptHandler(AST):
|
||||||
"""ExceptHandler(type: AST, name: str)"""
|
"""ExceptHandler(type: AST, name: str)"""
|
||||||
type: AST | t.CPtr
|
type: rowptr[AST]
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
type: AST | t.CPtr, name: str):
|
type: rowptr[AST], name: str):
|
||||||
ptr: ExceptHandler | t.CPtr = pool.alloc(ExceptHandler.__sizeof__())
|
ptr: rowptr[ExceptHandler] = pool.alloc(ExceptHandler.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, ExceptHandler.__sizeof__())
|
string.memset(ptr, 0, ExceptHandler.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
type: AST | t.CPtr, name: str):
|
type: rowptr[AST], name: str):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.type = type
|
self.type = type
|
||||||
self.name = _copy_str(pool, name)
|
self.name = _copy_str(pool, name)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.ExceptHandler
|
return ASTKind.ExceptHandler
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -59,27 +59,27 @@ class ExceptHandler(AST):
|
|||||||
class Arguments(AST):
|
class Arguments(AST):
|
||||||
"""Arguments(args: list[AST | CPtr], vararg: AST, kwarg: AST,
|
"""Arguments(args: list[AST | CPtr], vararg: AST, kwarg: AST,
|
||||||
defaults: list[AST | CPtr], kw_defaults: list[AST | CPtr])"""
|
defaults: list[AST | CPtr], kw_defaults: list[AST | CPtr])"""
|
||||||
args: list[AST | t.CPtr] | t.CPtr
|
args: rowptr[list[rowptr[AST]]]
|
||||||
vararg: AST | t.CPtr
|
vararg: rowptr[AST]
|
||||||
kwarg: AST | t.CPtr
|
kwarg: rowptr[AST]
|
||||||
defaults: list[AST | t.CPtr] | t.CPtr
|
defaults: rowptr[list[rowptr[AST]]]
|
||||||
kw_defaults: list[AST | t.CPtr] | t.CPtr
|
kw_defaults: rowptr[list[rowptr[AST]]]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
args: list[AST | t.CPtr] | t.CPtr,
|
args: rowptr[list[rowptr[AST]]],
|
||||||
vararg: AST | t.CPtr, kwarg: AST | t.CPtr,
|
vararg: rowptr[AST], kwarg: rowptr[AST],
|
||||||
defaults: list[AST | t.CPtr] | t.CPtr,
|
defaults: rowptr[list[rowptr[AST]]],
|
||||||
kw_defaults: list[AST | t.CPtr] | t.CPtr):
|
kw_defaults: rowptr[list[rowptr[AST]]]):
|
||||||
ptr: Arguments | t.CPtr = pool.alloc(Arguments.__sizeof__())
|
ptr: rowptr[Arguments] = pool.alloc(Arguments.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, Arguments.__sizeof__())
|
string.memset(ptr, 0, Arguments.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
args: list[AST | t.CPtr] | t.CPtr,
|
args: rowptr[list[rowptr[AST]]],
|
||||||
vararg: AST | t.CPtr, kwarg: AST | t.CPtr,
|
vararg: rowptr[AST], kwarg: rowptr[AST],
|
||||||
defaults: list[AST | t.CPtr] | t.CPtr,
|
defaults: rowptr[list[rowptr[AST]]],
|
||||||
kw_defaults: list[AST | t.CPtr] | t.CPtr):
|
kw_defaults: rowptr[list[rowptr[AST]]]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.args = args
|
self.args = args
|
||||||
self.vararg = vararg
|
self.vararg = vararg
|
||||||
@@ -90,7 +90,7 @@ class Arguments(AST):
|
|||||||
_set_parent_list(defaults, self)
|
_set_parent_list(defaults, self)
|
||||||
_set_parent_list(kw_defaults, self)
|
_set_parent_list(kw_defaults, self)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.Arguments
|
return ASTKind.Arguments
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -125,22 +125,22 @@ class Arguments(AST):
|
|||||||
class Arg(AST):
|
class Arg(AST):
|
||||||
"""Arg(arg: str, annotation: AST)"""
|
"""Arg(arg: str, annotation: AST)"""
|
||||||
arg: str
|
arg: str
|
||||||
annotation: AST | t.CPtr
|
annotation: rowptr[AST]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
arg: str, annotation: AST | t.CPtr):
|
arg: str, annotation: rowptr[AST]):
|
||||||
ptr: Arg | t.CPtr = pool.alloc(Arg.__sizeof__())
|
ptr: rowptr[Arg] = pool.alloc(Arg.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, Arg.__sizeof__())
|
string.memset(ptr, 0, Arg.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
arg: str, annotation: AST | t.CPtr):
|
arg: str, annotation: rowptr[AST]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.arg = _copy_str(pool, arg)
|
self.arg = _copy_str(pool, arg)
|
||||||
self.annotation = annotation
|
self.annotation = annotation
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.Arg
|
return ASTKind.Arg
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -166,22 +166,22 @@ class Arg(AST):
|
|||||||
class Keyword(AST):
|
class Keyword(AST):
|
||||||
"""Keyword(arg: str, value: AST)"""
|
"""Keyword(arg: str, value: AST)"""
|
||||||
arg: str
|
arg: str
|
||||||
value: AST | t.CPtr
|
value: rowptr[AST]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
arg: str, value: AST | t.CPtr):
|
arg: str, value: rowptr[AST]):
|
||||||
ptr: Keyword | t.CPtr = pool.alloc(Keyword.__sizeof__())
|
ptr: rowptr[Keyword] = pool.alloc(Keyword.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, Keyword.__sizeof__())
|
string.memset(ptr, 0, Keyword.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
arg: str, value: AST | t.CPtr):
|
arg: str, value: rowptr[AST]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.arg = _copy_str(pool, arg)
|
self.arg = _copy_str(pool, arg)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.Keyword
|
return ASTKind.Keyword
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -209,20 +209,20 @@ class Alias(AST):
|
|||||||
name: str
|
name: str
|
||||||
asname: str
|
asname: str
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
name: str, asname: str):
|
name: str, asname: str):
|
||||||
ptr: Alias | t.CPtr = pool.alloc(Alias.__sizeof__())
|
ptr: rowptr[Alias] = pool.alloc(Alias.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, Alias.__sizeof__())
|
string.memset(ptr, 0, Alias.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
name: str, asname: str):
|
name: str, asname: str):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.name = _copy_str(pool, name)
|
self.name = _copy_str(pool, name)
|
||||||
self.asname = _copy_str(pool, asname)
|
self.asname = _copy_str(pool, asname)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.Alias
|
return ASTKind.Alias
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -244,23 +244,23 @@ class Alias(AST):
|
|||||||
|
|
||||||
class WithItem(AST):
|
class WithItem(AST):
|
||||||
"""WithItem(context_expr: AST, optional_vars: AST)"""
|
"""WithItem(context_expr: AST, optional_vars: AST)"""
|
||||||
context_expr: AST | t.CPtr
|
context_expr: rowptr[AST]
|
||||||
optional_vars: AST | t.CPtr
|
optional_vars: rowptr[AST]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr):
|
context_expr: rowptr[AST], optional_vars: rowptr[AST]):
|
||||||
ptr: WithItem | t.CPtr = pool.alloc(WithItem.__sizeof__())
|
ptr: rowptr[WithItem] = pool.alloc(WithItem.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, WithItem.__sizeof__())
|
string.memset(ptr, 0, WithItem.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr):
|
context_expr: rowptr[AST], optional_vars: rowptr[AST]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.context_expr = context_expr
|
self.context_expr = context_expr
|
||||||
self.optional_vars = optional_vars
|
self.optional_vars = optional_vars
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.WithItem
|
return ASTKind.WithItem
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -288,22 +288,22 @@ class WithItem(AST):
|
|||||||
|
|
||||||
class Comprehension(AST):
|
class Comprehension(AST):
|
||||||
"""Comprehension(target: AST, iter: AST, ifs: list[AST | CPtr], is_async: CInt)"""
|
"""Comprehension(target: AST, iter: AST, ifs: list[AST | CPtr], is_async: CInt)"""
|
||||||
target: AST | t.CPtr
|
target: rowptr[AST]
|
||||||
iter: AST | t.CPtr
|
iter: rowptr[AST]
|
||||||
ifs: list[AST | t.CPtr] | t.CPtr
|
ifs: rowptr[list[rowptr[AST]]]
|
||||||
is_async: t.CInt
|
is_async: int
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
target: AST | t.CPtr, iter: AST | t.CPtr,
|
target: rowptr[AST], iter: rowptr[AST],
|
||||||
ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt):
|
ifs: rowptr[list[rowptr[AST]]], is_async: int):
|
||||||
ptr: Comprehension | t.CPtr = pool.alloc(Comprehension.__sizeof__())
|
ptr: rowptr[Comprehension] = pool.alloc(Comprehension.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, Comprehension.__sizeof__())
|
string.memset(ptr, 0, Comprehension.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
target: AST | t.CPtr, iter: AST | t.CPtr,
|
target: rowptr[AST], iter: rowptr[AST],
|
||||||
ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt):
|
ifs: rowptr[list[rowptr[AST]]], is_async: int):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.target = target
|
self.target = target
|
||||||
self.iter = iter
|
self.iter = iter
|
||||||
@@ -311,7 +311,7 @@ class Comprehension(AST):
|
|||||||
self.is_async = is_async
|
self.is_async = is_async
|
||||||
_set_parent_list(ifs, self)
|
_set_parent_list(ifs, self)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.Comprehension
|
return ASTKind.Comprehension
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
@@ -332,6 +332,6 @@ class Comprehension(AST):
|
|||||||
pos = _emit(buf, size, pos, ", ifs=")
|
pos = _emit(buf, size, pos, ", ifs=")
|
||||||
pos = _dump_list(self.ifs, buf, size, pos)
|
pos = _dump_list(self.ifs, buf, size, pos)
|
||||||
pos = _emit(buf, size, pos, ", is_async=")
|
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, ")")
|
pos = _emit(buf, size, pos, ")")
|
||||||
return pos
|
return pos
|
||||||
+46
-41
@@ -138,6 +138,8 @@ class OpKind(t.CEnum):
|
|||||||
UAdd: t.State
|
UAdd: t.State
|
||||||
USub: t.State
|
USub: t.State
|
||||||
Invert: t.State
|
Invert: t.State
|
||||||
|
Deref: t.State
|
||||||
|
AddrOf: t.State
|
||||||
# None
|
# None
|
||||||
NoneOp: t.State
|
NoneOp: t.State
|
||||||
|
|
||||||
@@ -156,6 +158,7 @@ FLAG_SIMPLE: t.CDefine = 2
|
|||||||
FLAG_HAS_STAR: t.CDefine = 4
|
FLAG_HAS_STAR: t.CDefine = 4
|
||||||
FLAG_IS_EXTERN: t.CDefine = 8
|
FLAG_IS_EXTERN: t.CDefine = 8
|
||||||
FLAG_IS_EXPORT: t.CDefine = 16
|
FLAG_IS_EXPORT: t.CDefine = 16
|
||||||
|
FLAG_IS_DEFINE: t.CDefine = 32
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -172,7 +175,7 @@ class ASTFlag(t.CEnum):
|
|||||||
# Helper Functions
|
# 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."""
|
"""Allocate and copy a C string from pool."""
|
||||||
if src is None: return None
|
if src is None: return None
|
||||||
slen: t.CSizeT = string.strlen(src)
|
slen: t.CSizeT = string.strlen(src)
|
||||||
@@ -182,8 +185,8 @@ def _copy_str(pool: memhub.MemManager | t.CPtr, src: str) -> str:
|
|||||||
return buf
|
return buf
|
||||||
|
|
||||||
|
|
||||||
def _set_pos(node: AST | t.CPtr, lineno: t.CInt, col_offset: t.CInt,
|
def _set_pos(node: rowptr[AST], lineno: int, col_offset: int,
|
||||||
end_lineno: t.CInt, end_col_offset: t.CInt):
|
end_lineno: int, end_col_offset: int):
|
||||||
if node is None: return
|
if node is None: return
|
||||||
node.lineno = lineno
|
node.lineno = lineno
|
||||||
node.col_offset = col_offset
|
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
|
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
|
if node is None or ref is None: return
|
||||||
node.lineno = ref.lineno
|
node.lineno = ref.lineno
|
||||||
node.col_offset = ref.col_offset
|
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
|
node.end_col_offset = ref.end_col_offset
|
||||||
|
|
||||||
|
|
||||||
def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr,
|
def _init_ast(node: rowptr[AST], pool: rowptr[memhub.MemManager],
|
||||||
lineno: t.CInt, col: t.CInt):
|
lineno: int, col: int):
|
||||||
"""Initialize AST base fields."""
|
"""Initialize AST base fields."""
|
||||||
node.parent = None
|
node.parent = None
|
||||||
node.pool = pool
|
node.pool = pool
|
||||||
@@ -211,20 +214,20 @@ def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr,
|
|||||||
node.children = None
|
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."""
|
"""Set list children parent pointers."""
|
||||||
if lst is None: return
|
if lst is None: return
|
||||||
n: t.CSizeT = lst.__len__()
|
n: t.CSizeT = lst.__len__()
|
||||||
i: t.CSizeT = 0
|
i: t.CSizeT = 0
|
||||||
while i < n:
|
while i < n:
|
||||||
child: AST | t.CPtr = lst.get(i)
|
child: rowptr[AST] = lst.get(i)
|
||||||
if child is not None:
|
if child is not None:
|
||||||
child.parent = parent
|
child.parent = parent
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
def _append_child(lst: list[AST | t.CPtr] | t.CPtr, node: AST | t.CPtr,
|
def _append_child(lst: list[rowptr[AST]] | t.CPtr, node: rowptr[AST],
|
||||||
pool: memhub.MemManager | t.CPtr):
|
pool: rowptr[memhub.MemManager]):
|
||||||
"""Append child nodes to a list (module-level function, to avoid conflicts with the AST.append method name).
|
"""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."""
|
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
|
# 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.Plus: return OpKind.Add
|
||||||
if op_id == TokOp.Minus: return OpKind.Sub
|
if op_id == TokOp.Minus: return OpKind.Sub
|
||||||
if op_id == TokOp.Star: return OpKind.Mult
|
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
|
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.PlusEq: return OpKind.Add
|
||||||
if op_id == TokOp.MinusEq: return OpKind.Sub
|
if op_id == TokOp.MinusEq: return OpKind.Sub
|
||||||
if op_id == TokOp.StarEq: return OpKind.Mult
|
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
|
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.EqEq: return OpKind.Eq
|
||||||
if op_id == TokOp.ExclaimEq: return OpKind.Ne
|
if op_id == TokOp.ExclaimEq: return OpKind.Ne
|
||||||
if op_id == TokOp.Less: return OpKind.Lt
|
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
|
# 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:
|
text: str) -> t.CSizeT:
|
||||||
"""Append literal to buf+pos."""
|
"""Append literal to buf+pos."""
|
||||||
if buf is None or pos >= size:
|
if buf is None or pos >= size:
|
||||||
return pos
|
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
|
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:
|
if n < 0:
|
||||||
return pos
|
return pos
|
||||||
return pos + t.CSizeT(n)
|
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:
|
text: str) -> t.CSizeT:
|
||||||
"""Append a string value to buf pos (using %s format)"""
|
"""Append a string value to buf pos (using %s format)"""
|
||||||
if buf is None or pos >= size:
|
if buf is None or pos >= size:
|
||||||
return pos
|
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
|
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:
|
if n < 0:
|
||||||
return pos
|
return pos
|
||||||
return pos + t.CSizeT(n)
|
return pos + t.CSizeT(n)
|
||||||
|
|
||||||
|
|
||||||
def _emit_int(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
|
def _emit_int(buf: str, size: t.CSizeT, pos: t.CSizeT,
|
||||||
val: t.CInt64T) -> t.CSizeT:
|
val: int64) -> t.CSizeT:
|
||||||
"""Append an integer value to buf pos (using %lld format)."""
|
"""Append an integer value to buf pos (using %lld format)."""
|
||||||
if buf is None or pos >= size:
|
if buf is None or pos >= size:
|
||||||
return pos
|
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
|
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:
|
if n < 0:
|
||||||
return pos
|
return pos
|
||||||
return pos + t.CSizeT(n)
|
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."""
|
"""Return the string name of an OpKind."""
|
||||||
if op == OpKind.Add: return "Add"
|
if op == OpKind.Add: return "Add"
|
||||||
if op == OpKind.Sub: return "Sub"
|
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.UAdd: return "UAdd"
|
||||||
if op == OpKind.USub: return "USub"
|
if op == OpKind.USub: return "USub"
|
||||||
if op == OpKind.Invert: return "Invert"
|
if op == OpKind.Invert: return "Invert"
|
||||||
|
if op == OpKind.Deref: return "Deref"
|
||||||
|
if op == OpKind.AddrOf: return "AddrOf"
|
||||||
return "NoneOp"
|
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:
|
size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT:
|
||||||
"""Traverse a list[AST | CPtr] container, polymorphically dump each element."""
|
"""Traverse a list[AST | CPtr] container, polymorphically dump each element."""
|
||||||
if lst is None:
|
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:
|
while i < n:
|
||||||
if i > 0:
|
if i > 0:
|
||||||
pos = _emit(buf, size, pos, ", ")
|
pos = _emit(buf, size, pos, ", ")
|
||||||
child: AST | t.CPtr = lst.get(i)
|
child: rowptr[AST] = lst.get(i)
|
||||||
if child is not None:
|
if child is not None:
|
||||||
pos = child.dump(buf, size, pos)
|
pos = child.dump(buf, size, pos)
|
||||||
i += 1
|
i += 1
|
||||||
@@ -378,20 +383,20 @@ def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr,
|
|||||||
return pos
|
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:
|
size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT:
|
||||||
"""Traverse a list[CInt] (OpKind values), output a list of op names."""
|
"""Traverse a list[CInt] (OpKind values), output a list of op names."""
|
||||||
if lst is None:
|
if lst is None:
|
||||||
pos = _emit(buf, size, pos, "[]")
|
pos = _emit(buf, size, pos, "[]")
|
||||||
return 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, "[")
|
pos = _emit(buf, size, pos, "[")
|
||||||
n: t.CSizeT = ops_list.__len__()
|
n: t.CSizeT = ops_list.__len__()
|
||||||
i: t.CSizeT = 0
|
i: t.CSizeT = 0
|
||||||
while i < n:
|
while i < n:
|
||||||
if i > 0:
|
if i > 0:
|
||||||
pos = _emit(buf, size, pos, ", ")
|
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))
|
pos = _emit(buf, size, pos, _op_name(op))
|
||||||
i += 1
|
i += 1
|
||||||
pos = _emit(buf, size, pos, "]")
|
pos = _emit(buf, size, pos, "]")
|
||||||
@@ -417,15 +422,15 @@ class AST:
|
|||||||
end_lineno/end_col_offset: Ending position
|
end_lineno/end_col_offset: Ending position
|
||||||
children: List of child nodes (body block, added via append)
|
children: List of child nodes (body block, added via append)
|
||||||
"""
|
"""
|
||||||
parent: AST | t.CPtr
|
parent: rowptr[AST]
|
||||||
pool: memhub.MemManager | t.CPtr
|
pool: rowptr[memhub.MemManager]
|
||||||
lineno: t.CInt
|
lineno: int
|
||||||
col_offset: t.CInt
|
col_offset: int
|
||||||
end_lineno: t.CInt
|
end_lineno: int
|
||||||
end_col_offset: t.CInt
|
end_col_offset: int
|
||||||
children: list[AST | t.CPtr] | t.CPtr
|
children: list[rowptr[AST]] | t.CPtr
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
"""Returns the node type (ASTKind value), overridden by subclasses"""
|
"""Returns the node type (ASTKind value), overridden by subclasses"""
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -433,7 +438,7 @@ class AST:
|
|||||||
"""Return the node type name, subclasses override"""
|
"""Return the node type name, subclasses override"""
|
||||||
return "AST"
|
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:
|
pos: t.CSizeT) -> t.CSizeT:
|
||||||
"""Polymorphic dump: subclasses override to define custom format. Returns the written pos"""
|
"""Polymorphic dump: subclasses override to define custom format. Returns the written pos"""
|
||||||
return pos
|
return pos
|
||||||
@@ -443,7 +448,7 @@ class AST:
|
|||||||
Current implementation is empty. override this method to dispatch to visitor.visit_X(self)"""
|
Current implementation is empty. override this method to dispatch to visitor.visit_X(self)"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def append(self, node: AST | t.CPtr):
|
def append(self, node: rowptr[AST]):
|
||||||
"""Append node to the children list.
|
"""Append node to the children list.
|
||||||
|
|
||||||
Used for parser to build statement blocks: module.append(stmt), if_node.append(stmt), etc.
|
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:
|
if self is None or node is None:
|
||||||
return
|
return
|
||||||
if self.children is None:
|
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
|
node.parent = self
|
||||||
_append_child(self.children, node, self.pool)
|
_append_child(self.children, node, self.pool)
|
||||||
|
|
||||||
@@ -492,7 +497,7 @@ class ExprNode(AST):
|
|||||||
# Module dump function (for ast.dump(node, buf, size))
|
# 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)"""
|
"""Serialize AST node to buf (with capacity size)"""
|
||||||
if node is None or buf is None or size == 0:
|
if node is None or buf is None or size == 0:
|
||||||
return
|
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)
|
src: str # Source code (NUL-terminated)
|
||||||
pos: t.CSizeT # Current position
|
pos: t.CSizeT # Current position
|
||||||
len: t.CSizeT # Source code length
|
len: t.CSizeT # Source code length
|
||||||
lineno: t.CInt # Current line number (1-based)
|
lineno: int # Current line number (1-based)
|
||||||
col: t.CInt # Current column number (0-based)
|
col: int # Current column number (0-based)
|
||||||
pool: memhub.MemManager | t.CPtr # Memory pool
|
pool: rowptr[memhub.MemManager] # Memory pool
|
||||||
indent_stack: t.CInt | t.CPtr # Indent stack (int array, allocated from pool)
|
indent_stack: rowptr[int] # Indent stack (int array, allocated from pool)
|
||||||
indent_top: t.CInt # Stack top (-1 for empty stack)
|
indent_top: int # Stack top (-1 for empty stack)
|
||||||
paren_depth: t.CInt # Paren depth (>0 for no TokenType.NewLine)
|
paren_depth: int # Paren depth (>0 for no TokenType.NewLine)
|
||||||
tokens_head: Token | t.CPtr # token list head
|
tokens_head: rowptr[Token] # token list head
|
||||||
tokens_tail: Token | t.CPtr # token list tail
|
tokens_tail: rowptr[Token] # token list tail
|
||||||
at_line_start: t.CInt # 1=line start (need indent)
|
at_line_start: int # 1=line start (need indent)
|
||||||
error_count: t.CInt # Error count
|
error_count: int # Error count
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr):
|
def __new__(self, pool: rowptr[memhub.MemManager]):
|
||||||
ptr: Lexer | t.CPtr = pool.alloc(Lexer.__sizeof__())
|
ptr: rowptr[Lexer] = pool.alloc(Lexer.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, Lexer.__sizeof__())
|
string.memset(ptr, 0, Lexer.__sizeof__())
|
||||||
return ptr
|
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)"""
|
"""Allocate from the pool and return a Lexer (cross-module safe wrapper)"""
|
||||||
return Lexer(pool)
|
return Lexer(pool)
|
||||||
|
|
||||||
|
|
||||||
def _lexer_init(lx: Lexer | t.CPtr, src: str,
|
def _lexer_init(lx: rowptr[Lexer], src: str,
|
||||||
pool: memhub.MemManager | t.CPtr):
|
pool: rowptr[memhub.MemManager]):
|
||||||
"""Initialize Lexer"""
|
"""Initialize Lexer"""
|
||||||
if lx == None: return
|
if lx == None: return
|
||||||
lx.src = src
|
lx.src = src
|
||||||
@@ -73,7 +73,7 @@ def _lexer_init(lx: Lexer | t.CPtr, src: str,
|
|||||||
# Auxiliary Functions
|
# 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"""
|
"""Peek character at position pos+offset, return '\0' if out of bounds"""
|
||||||
p: t.CSizeT = lx.pos + offset
|
p: t.CSizeT = lx.pos + offset
|
||||||
if p >= lx.len:
|
if p >= lx.len:
|
||||||
@@ -81,13 +81,13 @@ def _peek(lx: Lexer | t.CPtr, offset: t.CSizeT) -> t.CChar:
|
|||||||
return lx.src[p]
|
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:
|
if lx.pos >= lx.len:
|
||||||
return '\0'
|
return '\0'
|
||||||
return lx.src[lx.pos]
|
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"""
|
"""Advance one character, return the character"""
|
||||||
if lx.pos >= lx.len:
|
if lx.pos >= lx.len:
|
||||||
return '\0'
|
return '\0'
|
||||||
@@ -101,40 +101,40 @@ def _advance(lx: Lexer | t.CPtr) -> t.CChar:
|
|||||||
return ch
|
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 >= 'A' and ch <= 'Z': return 1
|
if ch >= 'A' and ch <= 'Z': return 1
|
||||||
if ch == '_': return 1
|
if ch == '_': return 1
|
||||||
return 0
|
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
|
if ch >= '0' and ch <= '9': return 1
|
||||||
return 0
|
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_alpha(ch): return 1
|
||||||
if _is_digit(ch): return 1
|
if _is_digit(ch): return 1
|
||||||
return 0
|
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 >= '0' and ch <= '9': return 1
|
||||||
if ch >= 'a' and ch <= 'f': return 1
|
if ch >= 'a' and ch <= 'f': return 1
|
||||||
if ch >= 'A' and ch <= 'F': return 1
|
if ch >= 'A' and ch <= 'F': return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _hex_val(ch: t.CChar) -> t.CInt:
|
def _hex_val(ch: t.CChar) -> int:
|
||||||
"""十六进制字符转数值 0-15(供 \xNN 转义解析)"""
|
"""十六进制字符转数值 0-15(供 \xNN 转义解析)"""
|
||||||
if ch >= '0' and ch <= '9': return t.CInt(ch) - 48
|
if ch >= '0' and ch <= '9': return int(ch) - 48
|
||||||
if ch >= 'a' and ch <= 'f': return t.CInt(ch) - 87
|
if ch >= 'a' and ch <= 'f': return int(ch) - 87
|
||||||
if ch >= 'A' and ch <= 'F': return t.CInt(ch) - 55
|
if ch >= 'A' and ch <= 'F': return int(ch) - 55
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _is_space(ch: t.CChar) -> t.CInt:
|
def _is_space(ch: t.CChar) -> int:
|
||||||
if ch == ' ': return 1
|
if ch == ' ': return 1
|
||||||
if ch == '\t': return 1
|
if ch == '\t': return 1
|
||||||
if ch == '\f': return 1
|
if ch == '\f': return 1
|
||||||
@@ -143,7 +143,7 @@ def _is_space(ch: t.CChar) -> t.CInt:
|
|||||||
return 0
|
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"""
|
"""Append token to token list"""
|
||||||
if tok == None: return
|
if tok == None: return
|
||||||
if lx.tokens_head == None:
|
if lx.tokens_head == None:
|
||||||
@@ -154,9 +154,9 @@ def _emit(lx: Lexer | t.CPtr, tok: Token | t.CPtr):
|
|||||||
lx.tokens_tail = tok
|
lx.tokens_tail = tok
|
||||||
|
|
||||||
|
|
||||||
def _make_op_token(lx: Lexer | t.CPtr, op_id: t.CInt, length: t.CInt,
|
def _make_op_token(lx: rowptr[Lexer], op_id: int, length: int,
|
||||||
lineno: t.CInt, col: t.CInt) -> Token | t.CPtr:
|
lineno: int, col: int) -> rowptr[Token]:
|
||||||
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Op, lineno, col)
|
tok: rowptr[Token] = new_token(lx.pool, TokenType.Op, lineno, col)
|
||||||
if tok == None: return None
|
if tok == None: return None
|
||||||
tok.op_subtype = op_id
|
tok.op_subtype = op_id
|
||||||
tok.end_col_offset = col + length
|
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
|
# Indent Handling
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _handle_indent(lx: Lexer | t.CPtr):
|
def _handle_indent(lx: rowptr[Lexer]):
|
||||||
"""Handle line start indent, generate TokenType.Indent/TokenType.Dedent.
|
"""Handle line start indent, generate TokenType.Indent/TokenType.Dedent.
|
||||||
Skip empty lines and comment lines."""
|
Skip empty lines and comment lines."""
|
||||||
# Skip empty lines and comment lines
|
# Skip empty lines and comment lines
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
# Save line start position for non-empty lines
|
# Save line start position for non-empty lines
|
||||||
line_start_pos: t.CSizeT = lx.pos
|
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
|
# Skip whitespace, not across lines
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
ch: t.CChar = lx.src[lx.pos]
|
ch: t.CChar = lx.src[lx.pos]
|
||||||
@@ -219,9 +219,9 @@ def _handle_indent(lx: Lexer | t.CPtr):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Calculate current line indent
|
# Calculate current line indent
|
||||||
indent: t.CInt = 0
|
indent: int = 0
|
||||||
save_pos: t.CSizeT = lx.pos
|
save_pos: t.CSizeT = lx.pos
|
||||||
save_col: t.CInt = lx.col
|
save_col: int = lx.col
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
ch: t.CChar = lx.src[lx.pos]
|
ch: t.CChar = lx.src[lx.pos]
|
||||||
if ch == ' ':
|
if ch == ' ':
|
||||||
@@ -246,7 +246,7 @@ def _handle_indent(lx: Lexer | t.CPtr):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Compare indent with top of indent stack
|
# 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:
|
if indent > top_indent:
|
||||||
# TokenType.Indent
|
# TokenType.Indent
|
||||||
if lx.indent_top + 1 >= LEXER_MAX_INDENT:
|
if lx.indent_top + 1 >= LEXER_MAX_INDENT:
|
||||||
@@ -254,12 +254,12 @@ def _handle_indent(lx: Lexer | t.CPtr):
|
|||||||
return
|
return
|
||||||
lx.indent_top += 1
|
lx.indent_top += 1
|
||||||
lx.indent_stack[lx.indent_top] = indent
|
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)
|
_emit(lx, tok)
|
||||||
else:
|
else:
|
||||||
while indent < lx.indent_stack[lx.indent_top] and lx.indent_top > 0:
|
while indent < lx.indent_stack[lx.indent_top] and lx.indent_top > 0:
|
||||||
lx.indent_top -= 1
|
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)
|
_emit(lx, tok)
|
||||||
lx.at_line_start = 0
|
lx.at_line_start = 0
|
||||||
|
|
||||||
@@ -268,10 +268,10 @@ def _handle_indent(lx: Lexer | t.CPtr):
|
|||||||
# Identifier/Keyword Handling
|
# Identifier/Keyword Handling
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _read_name(lx: Lexer | t.CPtr):
|
def _read_name(lx: rowptr[Lexer]):
|
||||||
start: t.CSizeT = lx.pos
|
start: t.CSizeT = lx.pos
|
||||||
start_lineno: t.CInt = lx.lineno
|
start_lineno: int = lx.lineno
|
||||||
start_col: t.CInt = lx.col
|
start_col: int = lx.col
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
ch: t.CChar = lx.src[lx.pos]
|
ch: t.CChar = lx.src[lx.pos]
|
||||||
if _is_alnum(ch):
|
if _is_alnum(ch):
|
||||||
@@ -280,13 +280,13 @@ def _read_name(lx: Lexer | t.CPtr):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
length: t.CSizeT = lx.pos - start
|
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
|
if tok == None: return
|
||||||
token_set_str(lx.pool, tok, lx.src, start, length)
|
token_set_str(lx.pool, tok, lx.src, start, length)
|
||||||
tok.end_lineno = lx.lineno
|
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
|
# 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:
|
if kw_id:
|
||||||
tok.kw_subtype = kw_id
|
tok.kw_subtype = kw_id
|
||||||
_emit(lx, tok)
|
_emit(lx, tok)
|
||||||
@@ -296,12 +296,12 @@ def _read_name(lx: Lexer | t.CPtr):
|
|||||||
# Number Handling
|
# Number Handling
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _read_number(lx: Lexer | t.CPtr):
|
def _read_number(lx: rowptr[Lexer]):
|
||||||
start: t.CSizeT = lx.pos
|
start: t.CSizeT = lx.pos
|
||||||
start_lineno: t.CInt = lx.lineno
|
start_lineno: int = lx.lineno
|
||||||
start_col: t.CInt = lx.col
|
start_col: int = lx.col
|
||||||
is_float: t.CInt = 0
|
is_float: int = 0
|
||||||
is_complex: t.CInt = 0
|
is_complex: int = 0
|
||||||
|
|
||||||
ch0: t.CChar = lx.src[lx.pos]
|
ch0: t.CChar = lx.src[lx.pos]
|
||||||
# Handle 0x/0o/0b prefix
|
# 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)
|
_emit_number(lx, start, start_lineno, start_col, is_float, is_complex, 0)
|
||||||
|
|
||||||
|
|
||||||
def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT,
|
def _emit_number(lx: rowptr[Lexer], start: t.CSizeT,
|
||||||
start_lineno: t.CInt, start_col: t.CInt,
|
start_lineno: int, start_col: int,
|
||||||
is_float: t.CInt, is_complex: t.CInt, is_hex: t.CInt):
|
is_float: int, is_complex: int, is_hex: int):
|
||||||
length: t.CSizeT = lx.pos - start
|
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
|
if tok == None: return
|
||||||
token_set_str(lx.pool, tok, lx.src, start, length)
|
token_set_str(lx.pool, tok, lx.src, start, length)
|
||||||
tok.is_float = is_float
|
tok.is_float = is_float
|
||||||
tok.is_complex = is_complex
|
tok.is_complex = is_complex
|
||||||
tok.end_lineno = lx.lineno
|
tok.end_lineno = lx.lineno
|
||||||
tok.end_col_offset = start_col + t.CInt(length)
|
tok.end_col_offset = start_col + int(length)
|
||||||
# Parse number
|
# Parse number
|
||||||
if is_float:
|
if is_float:
|
||||||
tok.float_val = string.atof(tok.str_val)
|
tok.float_val = string.atof(tok.str_val)
|
||||||
@@ -422,19 +422,19 @@ def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT,
|
|||||||
# String Handling
|
# String Handling
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _read_string(lx: Lexer | t.CPtr):
|
def _read_string(lx: rowptr[Lexer]):
|
||||||
"""Read string literal.
|
"""Read string literal.
|
||||||
Supports prefixes: r, b, u, f, rb, br, rf, fr (case insensitive)
|
Supports prefixes: r, b, u, f, rb, br, rf, fr (case insensitive)
|
||||||
Supports quotes: ', ", ''',
|
Supports quotes: ', ", ''',
|
||||||
Later we need to support string prefixes like i16/i24"""
|
Later we need to support string prefixes like i16/i24"""
|
||||||
start_lineno: t.CInt = lx.lineno
|
start_lineno: int = lx.lineno
|
||||||
start_col: t.CInt = lx.col
|
start_col: int = lx.col
|
||||||
prefix_start: t.CSizeT = lx.pos
|
prefix_start: t.CSizeT = lx.pos
|
||||||
|
|
||||||
# Read prefix (r/b/u/f)
|
# Read prefix (r/b/u/f)
|
||||||
is_raw: t.CInt = 0
|
is_raw: int = 0
|
||||||
is_bytes: t.CInt = 0
|
is_bytes: int = 0
|
||||||
is_fstring: t.CInt = 0
|
is_fstring: int = 0
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
ch: t.CChar = lx.src[lx.pos]
|
ch: t.CChar = lx.src[lx.pos]
|
||||||
if ch == 'r' or ch == 'R':
|
if ch == 'r' or ch == 'R':
|
||||||
@@ -466,7 +466,7 @@ def _read_string(lx: Lexer | t.CPtr):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Check triple quote
|
# Check triple quote
|
||||||
is_triple: t.CInt = 0
|
is_triple: int = 0
|
||||||
if lx.pos + 2 < lx.len:
|
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:
|
if lx.src[lx.pos] == quote and lx.src[lx.pos + 1] == quote and lx.src[lx.pos + 2] == quote:
|
||||||
is_triple = 1
|
is_triple = 1
|
||||||
@@ -482,7 +482,7 @@ def _read_string(lx: Lexer | t.CPtr):
|
|||||||
# Read string content
|
# Read string content
|
||||||
content_buf_start: t.CSizeT = lx.pos
|
content_buf_start: t.CSizeT = lx.pos
|
||||||
# f-string {} 表达式块嵌套深度(PEP 701 同引号嵌套字符串支持用)
|
# f-string {} 表达式块嵌套深度(PEP 701 同引号嵌套字符串支持用)
|
||||||
fstr_depth: t.CInt = 0
|
fstr_depth: int = 0
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
ch = lx.src[lx.pos]
|
ch = lx.src[lx.pos]
|
||||||
if is_triple:
|
if is_triple:
|
||||||
@@ -582,7 +582,7 @@ def _read_string(lx: Lexer | t.CPtr):
|
|||||||
lx.col += 1
|
lx.col += 1
|
||||||
|
|
||||||
# Create token
|
# 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
|
if tok == None: return
|
||||||
content_len: t.CSizeT = content_end - content_buf_start
|
content_len: t.CSizeT = content_end - content_buf_start
|
||||||
# esc_len: Actual bytes after escaping (used to check single character)
|
# 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]
|
h1: t.CChar = lx.src[content_buf_start + rpos + 1]
|
||||||
h2: t.CChar = lx.src[content_buf_start + rpos + 2]
|
h2: t.CChar = lx.src[content_buf_start + rpos + 2]
|
||||||
if _is_hex(h1) != 0 and _is_hex(h2) != 0:
|
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)
|
conv_buf[wpos] = t.CChar(hex_v)
|
||||||
wpos += 1
|
wpos += 1
|
||||||
rpos += 3
|
rpos += 3
|
||||||
@@ -677,20 +677,20 @@ def _read_string(lx: Lexer | t.CPtr):
|
|||||||
# Operator Matching
|
# Operator Matching
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _read_operator(lx: Lexer | t.CPtr):
|
def _read_operator(lx: rowptr[Lexer]):
|
||||||
"""Greedy match operator"""
|
"""Greedy match operator"""
|
||||||
start_lineno: t.CInt = lx.lineno
|
start_lineno: int = lx.lineno
|
||||||
start_col: t.CInt = lx.col
|
start_col: int = lx.col
|
||||||
remaining: t.CSizeT = lx.len - lx.pos
|
remaining: t.CSizeT = lx.len - lx.pos
|
||||||
|
|
||||||
# Traverse operator table, find longest match
|
# Traverse operator table, find longest match
|
||||||
best_entry: OpEntry | t.CPtr = None
|
best_entry: rowptr[OpEntry] = None
|
||||||
best_len: t.CInt = 0
|
best_len: int = 0
|
||||||
cur: OpEntry | t.CPtr = _op_head
|
cur: rowptr[OpEntry] = _op_head
|
||||||
while cur != None:
|
while cur != None:
|
||||||
if cur.length <= t.CInt(remaining):
|
if cur.length <= int(remaining):
|
||||||
# Compare cur.name with src[pos:pos+cur.length]
|
# Compare cur.name with src[pos:pos+cur.length]
|
||||||
match: t.CInt = 1
|
match: int = 1
|
||||||
i: t.CSizeT = 0
|
i: t.CSizeT = 0
|
||||||
while i < t.CSizeT(cur.length):
|
while i < t.CSizeT(cur.length):
|
||||||
if lx.src[lx.pos + i] != cur.name[i]:
|
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:
|
if lx.paren_depth > 0:
|
||||||
lx.paren_depth -= 1
|
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)
|
start_lineno, start_col)
|
||||||
if tok == None: return
|
if tok == None: return
|
||||||
token_set_str(lx.pool, tok, lx.src, lx.pos, t.CSizeT(best_len))
|
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
|
# 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"""
|
"""Execute tokenization, return token list head"""
|
||||||
if lx == None: return None
|
if lx == None: return None
|
||||||
while lx.pos < lx.len:
|
while lx.pos < lx.len:
|
||||||
@@ -748,11 +748,11 @@ def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr:
|
|||||||
if ch == '\n':
|
if ch == '\n':
|
||||||
if lx.paren_depth > 0:
|
if lx.paren_depth > 0:
|
||||||
# # In bi brackets, generates TokenType.Nl
|
# # 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)
|
_emit(lx, tok)
|
||||||
else:
|
else:
|
||||||
# Logical new line
|
# 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)
|
_emit(lx, tok)
|
||||||
lx.at_line_start = 1
|
lx.at_line_start = 1
|
||||||
lx.pos += 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)
|
# End of file: generate TokenType.NewLine (if there's content)
|
||||||
if lx.tokens_tail != None:
|
if lx.tokens_tail != None:
|
||||||
if lx.tokens_tail.type != TokenType.NewLine and lx.tokens_tail.type != TokenType.Nl:
|
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)
|
_emit(lx, tok)
|
||||||
|
|
||||||
# Generate remaining remaining TokenType.Dedent
|
# Generate remaining remaining TokenType.Dedent
|
||||||
while lx.indent_top > 0:
|
while lx.indent_top > 0:
|
||||||
lx.indent_top -= 1
|
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)
|
_emit(lx, tok)
|
||||||
|
|
||||||
# TokenType.EndMarker
|
# 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)
|
_emit(lx, tok)
|
||||||
|
|
||||||
return lx.tokens_head
|
return lx.tokens_head
|
||||||
+83
-83
@@ -15,29 +15,29 @@ from .base import (
|
|||||||
|
|
||||||
class MatchCase(AST):
|
class MatchCase(AST):
|
||||||
"""MatchCase(pattern: AST, guard: AST)"""
|
"""MatchCase(pattern: AST, guard: AST)"""
|
||||||
pattern: AST | t.CPtr
|
pattern: rowptr[AST]
|
||||||
guard: AST | t.CPtr
|
guard: rowptr[AST]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
pattern: AST | t.CPtr, guard: AST | t.CPtr):
|
pattern: rowptr[AST], guard: rowptr[AST]):
|
||||||
ptr: MatchCase | t.CPtr = pool.alloc(MatchCase.__sizeof__())
|
ptr: rowptr[MatchCase] = pool.alloc(MatchCase.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchCase.__sizeof__())
|
string.memset(ptr, 0, MatchCase.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
pattern: AST | t.CPtr, guard: AST | t.CPtr):
|
pattern: rowptr[AST], guard: rowptr[AST]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
self.guard = guard
|
self.guard = guard
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchCase
|
return ASTKind.MatchCase
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchCase"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchCase(pattern=")
|
pos = _emit(buf, size, pos, "MatchCase(pattern=")
|
||||||
if self.pattern is not None:
|
if self.pattern is not None:
|
||||||
@@ -57,25 +57,25 @@ class MatchCase(AST):
|
|||||||
|
|
||||||
class MatchValue(AST):
|
class MatchValue(AST):
|
||||||
"""MatchValue(value: AST)"""
|
"""MatchValue(value: AST)"""
|
||||||
value: AST | t.CPtr
|
value: rowptr[AST]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
|
def __new__(self, pool: rowptr[memhub.MemManager], value: rowptr[AST]):
|
||||||
ptr: MatchValue | t.CPtr = pool.alloc(MatchValue.__sizeof__())
|
ptr: rowptr[MatchValue] = pool.alloc(MatchValue.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchValue.__sizeof__())
|
string.memset(ptr, 0, MatchValue.__sizeof__())
|
||||||
return ptr
|
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)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchValue
|
return ASTKind.MatchValue
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchValue"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchValue(value=")
|
pos = _emit(buf, size, pos, "MatchValue(value=")
|
||||||
if self.value is not None:
|
if self.value is not None:
|
||||||
@@ -90,25 +90,25 @@ class MatchValue(AST):
|
|||||||
|
|
||||||
class MatchSingleton(AST):
|
class MatchSingleton(AST):
|
||||||
"""MatchSingleton(value: AST)"""
|
"""MatchSingleton(value: AST)"""
|
||||||
value: AST | t.CPtr
|
value: rowptr[AST]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
|
def __new__(self, pool: rowptr[memhub.MemManager], value: rowptr[AST]):
|
||||||
ptr: MatchSingleton | t.CPtr = pool.alloc(MatchSingleton.__sizeof__())
|
ptr: rowptr[MatchSingleton] = pool.alloc(MatchSingleton.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchSingleton.__sizeof__())
|
string.memset(ptr, 0, MatchSingleton.__sizeof__())
|
||||||
return ptr
|
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)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchSingleton
|
return ASTKind.MatchSingleton
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchSingleton"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchSingleton(value=")
|
pos = _emit(buf, size, pos, "MatchSingleton(value=")
|
||||||
if self.value is not None:
|
if self.value is not None:
|
||||||
@@ -122,29 +122,29 @@ class MatchSingleton(AST):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
class MatchSequence(AST):
|
class MatchSequence(AST):
|
||||||
"""MatchSequence(patterns: list[AST | t.CPtr])"""
|
"""MatchSequence(patterns: list[rowptr[AST]])"""
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr
|
patterns: rowptr[list[rowptr[AST]]]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr):
|
patterns: rowptr[list[rowptr[AST]]]):
|
||||||
ptr: MatchSequence | t.CPtr = pool.alloc(MatchSequence.__sizeof__())
|
ptr: rowptr[MatchSequence] = pool.alloc(MatchSequence.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchSequence.__sizeof__())
|
string.memset(ptr, 0, MatchSequence.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr):
|
patterns: rowptr[list[rowptr[AST]]]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.patterns = patterns
|
self.patterns = patterns
|
||||||
_set_parent_list(patterns, self)
|
_set_parent_list(patterns, self)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchSequence
|
return ASTKind.MatchSequence
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchSequence"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchSequence(patterns=")
|
pos = _emit(buf, size, pos, "MatchSequence(patterns=")
|
||||||
pos = _dump_list(self.patterns, buf, size, pos)
|
pos = _dump_list(self.patterns, buf, size, pos)
|
||||||
@@ -157,23 +157,23 @@ class MatchSequence(AST):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
class MatchMapping(AST):
|
class MatchMapping(AST):
|
||||||
"""MatchMapping(keys: list[AST | t.CPtr], patterns: list[AST | t.CPtr], rest: str)"""
|
"""MatchMapping(keys: list[rowptr[AST]], patterns: list[rowptr[AST]], rest: str)"""
|
||||||
keys: list[AST | t.CPtr] | t.CPtr
|
keys: rowptr[list[rowptr[AST]]]
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr
|
patterns: rowptr[list[rowptr[AST]]]
|
||||||
rest: str
|
rest: str
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
keys: list[AST | t.CPtr] | t.CPtr,
|
keys: rowptr[list[rowptr[AST]]],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr,
|
patterns: rowptr[list[rowptr[AST]]],
|
||||||
rest: str):
|
rest: str):
|
||||||
ptr: MatchMapping | t.CPtr = pool.alloc(MatchMapping.__sizeof__())
|
ptr: rowptr[MatchMapping] = pool.alloc(MatchMapping.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchMapping.__sizeof__())
|
string.memset(ptr, 0, MatchMapping.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
keys: list[AST | t.CPtr] | t.CPtr,
|
keys: rowptr[list[rowptr[AST]]],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr,
|
patterns: rowptr[list[rowptr[AST]]],
|
||||||
rest: str):
|
rest: str):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.keys = keys
|
self.keys = keys
|
||||||
@@ -182,13 +182,13 @@ class MatchMapping(AST):
|
|||||||
_set_parent_list(keys, self)
|
_set_parent_list(keys, self)
|
||||||
_set_parent_list(patterns, self)
|
_set_parent_list(patterns, self)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchMapping
|
return ASTKind.MatchMapping
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchMapping"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchMapping(keys=")
|
pos = _emit(buf, size, pos, "MatchMapping(keys=")
|
||||||
pos = _dump_list(self.keys, buf, size, pos)
|
pos = _dump_list(self.keys, buf, size, pos)
|
||||||
@@ -205,28 +205,28 @@ class MatchMapping(AST):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
class MatchClass(AST):
|
class MatchClass(AST):
|
||||||
"""MatchClass(cls: AST, patterns: list[AST | t.CPtr],
|
"""MatchClass(cls: AST, patterns: list[rowptr[AST]],
|
||||||
kwd_attrs: list[AST | t.CPtr], kwd_patterns: list[AST | t.CPtr])"""
|
kwd_attrs: list[rowptr[AST]], kwd_patterns: list[rowptr[AST]])"""
|
||||||
cls: AST | t.CPtr
|
cls: rowptr[AST]
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr
|
patterns: rowptr[list[rowptr[AST]]]
|
||||||
kwd_attrs: list[AST | t.CPtr] | t.CPtr
|
kwd_attrs: rowptr[list[rowptr[AST]]]
|
||||||
kwd_patterns: list[AST | t.CPtr] | t.CPtr
|
kwd_patterns: rowptr[list[rowptr[AST]]]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
cls: AST | t.CPtr,
|
cls: rowptr[AST],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr,
|
patterns: rowptr[list[rowptr[AST]]],
|
||||||
kwd_attrs: list[AST | t.CPtr] | t.CPtr,
|
kwd_attrs: rowptr[list[rowptr[AST]]],
|
||||||
kwd_patterns: list[AST | t.CPtr] | t.CPtr):
|
kwd_patterns: rowptr[list[rowptr[AST]]]):
|
||||||
ptr: MatchClass | t.CPtr = pool.alloc(MatchClass.__sizeof__())
|
ptr: rowptr[MatchClass] = pool.alloc(MatchClass.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchClass.__sizeof__())
|
string.memset(ptr, 0, MatchClass.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
cls: AST | t.CPtr,
|
cls: rowptr[AST],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr,
|
patterns: rowptr[list[rowptr[AST]]],
|
||||||
kwd_attrs: list[AST | t.CPtr] | t.CPtr,
|
kwd_attrs: rowptr[list[rowptr[AST]]],
|
||||||
kwd_patterns: list[AST | t.CPtr] | t.CPtr):
|
kwd_patterns: rowptr[list[rowptr[AST]]]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.cls = cls
|
self.cls = cls
|
||||||
self.patterns = patterns
|
self.patterns = patterns
|
||||||
@@ -236,13 +236,13 @@ class MatchClass(AST):
|
|||||||
_set_parent_list(kwd_attrs, self)
|
_set_parent_list(kwd_attrs, self)
|
||||||
_set_parent_list(kwd_patterns, self)
|
_set_parent_list(kwd_patterns, self)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchClass
|
return ASTKind.MatchClass
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchClass"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchClass(cls=")
|
pos = _emit(buf, size, pos, "MatchClass(cls=")
|
||||||
if self.cls is not None:
|
if self.cls is not None:
|
||||||
@@ -265,23 +265,23 @@ class MatchStar(AST):
|
|||||||
"""MatchStar(name: str)"""
|
"""MatchStar(name: str)"""
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr, name: str):
|
def __new__(self, pool: rowptr[memhub.MemManager], name: str):
|
||||||
ptr: MatchStar | t.CPtr = pool.alloc(MatchStar.__sizeof__())
|
ptr: rowptr[MatchStar] = pool.alloc(MatchStar.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchStar.__sizeof__())
|
string.memset(ptr, 0, MatchStar.__sizeof__())
|
||||||
return ptr
|
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)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.name = _copy_str(pool, name)
|
self.name = _copy_str(pool, name)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchStar
|
return ASTKind.MatchStar
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchStar"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchStar(name='")
|
pos = _emit(buf, size, pos, "MatchStar(name='")
|
||||||
pos = _emit_str(buf, size, pos, self.name)
|
pos = _emit_str(buf, size, pos, self.name)
|
||||||
@@ -295,29 +295,29 @@ class MatchStar(AST):
|
|||||||
|
|
||||||
class MatchAs(AST):
|
class MatchAs(AST):
|
||||||
"""MatchAs(pattern: AST, name: str)"""
|
"""MatchAs(pattern: AST, name: str)"""
|
||||||
pattern: AST | t.CPtr
|
pattern: rowptr[AST]
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
pattern: AST | t.CPtr, name: str):
|
pattern: rowptr[AST], name: str):
|
||||||
ptr: MatchAs | t.CPtr = pool.alloc(MatchAs.__sizeof__())
|
ptr: rowptr[MatchAs] = pool.alloc(MatchAs.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchAs.__sizeof__())
|
string.memset(ptr, 0, MatchAs.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
pattern: AST | t.CPtr, name: str):
|
pattern: rowptr[AST], name: str):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
self.name = _copy_str(pool, name)
|
self.name = _copy_str(pool, name)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchAs
|
return ASTKind.MatchAs
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchAs"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchAs(pattern=")
|
pos = _emit(buf, size, pos, "MatchAs(pattern=")
|
||||||
if self.pattern is not None:
|
if self.pattern is not None:
|
||||||
@@ -333,29 +333,29 @@ class MatchAs(AST):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
class MatchOr(AST):
|
class MatchOr(AST):
|
||||||
"""MatchOr(patterns: list[AST | t.CPtr])"""
|
"""MatchOr(patterns: list[rowptr[AST]])"""
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr
|
patterns: rowptr[list[rowptr[AST]]]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr,
|
def __new__(self, pool: rowptr[memhub.MemManager],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr):
|
patterns: rowptr[list[rowptr[AST]]]):
|
||||||
ptr: MatchOr | t.CPtr = pool.alloc(MatchOr.__sizeof__())
|
ptr: rowptr[MatchOr] = pool.alloc(MatchOr.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, MatchOr.__sizeof__())
|
string.memset(ptr, 0, MatchOr.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
def __init__(self, pool: memhub.MemManager | t.CPtr,
|
def __init__(self, pool: rowptr[memhub.MemManager],
|
||||||
patterns: list[AST | t.CPtr] | t.CPtr):
|
patterns: rowptr[list[rowptr[AST]]]):
|
||||||
_init_ast(self, pool, 0, 0)
|
_init_ast(self, pool, 0, 0)
|
||||||
self.patterns = patterns
|
self.patterns = patterns
|
||||||
_set_parent_list(patterns, self)
|
_set_parent_list(patterns, self)
|
||||||
|
|
||||||
def kind(self) -> t.CInt:
|
def kind(self) -> int:
|
||||||
return ASTKind.MatchOr
|
return ASTKind.MatchOr
|
||||||
|
|
||||||
def type_name(self) -> str:
|
def type_name(self) -> str:
|
||||||
return "MatchOr"
|
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: t.CSizeT) -> t.CSizeT:
|
||||||
pos = _emit(buf, size, pos, "MatchOr(patterns=")
|
pos = _emit(buf, size, pos, "MatchOr(patterns=")
|
||||||
pos = _dump_list(self.patterns, buf, size, pos)
|
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
|
Extern: t.State
|
||||||
# export 函数声明关键字(等价 t.CExport,裸名导出不加 SHA1 头;软判定见 _is_funcdef_kw)
|
# export 函数声明关键字(等价 t.CExport,裸名导出不加 SHA1 头;软判定见 _is_funcdef_kw)
|
||||||
Export: t.State
|
Export: t.State
|
||||||
|
# define 宏函数关键字(与 def 语义一致,返回注解自动追加 t.CDefine 标记
|
||||||
|
# 为宏函数;软判定见 _is_funcdef_kw)
|
||||||
|
Define: t.State
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -144,23 +147,23 @@ class TokOp(t.CEnum):
|
|||||||
# Token stucture
|
# Token stucture
|
||||||
# ============================================================
|
# ============================================================
|
||||||
class Token:
|
class Token:
|
||||||
type: t.CInt # Token type (TokenType.EndMarker / TokenType.NewLine / TokenType.Name / ...)
|
type: int # Token type (TokenType.EndMarker / TokenType.NewLine / TokenType.Name / ...)
|
||||||
op_subtype: t.CInt # Operator subtype (OP_*). Only valid when type == TokenType.Op
|
op_subtype: int # 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
|
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)
|
str_val: str # Token text (NUL‑terminated, allocated from pool)
|
||||||
int_val: t.CInt64T # Integer value (used by TokenType.Number)
|
int_val: int64 # Integer value (used by TokenType.Number)
|
||||||
float_val: t.CDouble # Floating‑point value (used by TokenType.Number)
|
float_val: double # Floating‑point value (used by TokenType.Number)
|
||||||
is_float: t.CInt # 1 = floating‑point number, 0 = integer
|
is_float: int # 1 = floating‑point number, 0 = integer
|
||||||
is_complex: t.CInt # 1 = complex number, 0 = real number
|
is_complex: int # 1 = complex number, 0 = real number
|
||||||
lineno: t.CInt # Starting line number
|
lineno: int # Starting line number
|
||||||
col_offset: t.CInt # Starting column offset
|
col_offset: int # Starting column offset
|
||||||
end_lineno: t.CInt # Ending line number
|
end_lineno: int # Ending line number
|
||||||
end_col_offset: t.CInt # Ending column offset
|
end_col_offset: int # Ending column offset
|
||||||
next: Token | t.CPtr # Next token in linked list
|
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"""
|
"""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:
|
if ptr:
|
||||||
string.memset(ptr, 0, Token.__sizeof__())
|
string.memset(ptr, 0, Token.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
@@ -172,25 +175,25 @@ class Token:
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
class KwEntry:
|
class KwEntry:
|
||||||
name: str
|
name: str
|
||||||
kw_id: t.CInt
|
kw_id: int
|
||||||
next: KwEntry | t.CPtr
|
next: rowptr[KwEntry]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr):
|
def __new__(self, pool: rowptr[memhub.MemManager]):
|
||||||
ptr: KwEntry | t.CPtr = pool.alloc(KwEntry.__sizeof__())
|
ptr: rowptr[KwEntry] = pool.alloc(KwEntry.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, KwEntry.__sizeof__())
|
string.memset(ptr, 0, KwEntry.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
# Global keyword linked list head (lazy initialization)
|
# Global keyword linked list head (lazy initialization)
|
||||||
_kw_head: KwEntry | t.CPtr = None
|
_kw_head: rowptr[KwEntry] = None
|
||||||
_kw_pool: memhub.MemManager | t.CPtr = 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"""
|
"""Register keyword name in the linked list"""
|
||||||
global _kw_head
|
global _kw_head
|
||||||
entry: KwEntry | t.CPtr = KwEntry(pool)
|
entry: rowptr[KwEntry] = KwEntry(pool)
|
||||||
if entry == None: return
|
if entry == None: return
|
||||||
slen: t.CSizeT = string.strlen(name)
|
slen: t.CSizeT = string.strlen(name)
|
||||||
buf: str = pool.alloc(slen + 1)
|
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
|
_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)"""
|
"""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:
|
while cur != None:
|
||||||
if string.strcmp(cur.name, name) == 0:
|
if string.strcmp(cur.name, name) == 0:
|
||||||
return cur.kw_id
|
return cur.kw_id
|
||||||
@@ -212,7 +215,7 @@ def _kw_lookup(name: str) -> t.CInt:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _init_keywords(pool: memhub.MemManager | t.CPtr):
|
def _init_keywords(pool: rowptr[memhub.MemManager]):
|
||||||
"""Initialize keyword linked list (only once)"""
|
"""Initialize keyword linked list (only once)"""
|
||||||
global _kw_head, _kw_pool
|
global _kw_head, _kw_pool
|
||||||
if _kw_head != None: return
|
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, "fn", Keyword.Fn)
|
||||||
_kw_intern(pool, "fun", Keyword.Fun)
|
_kw_intern(pool, "fun", Keyword.Fun)
|
||||||
_kw_intern(pool, "func", Keyword.Func)
|
_kw_intern(pool, "func", Keyword.Func)
|
||||||
_kw_intern(pool, "function", Keyword.Function)
|
_kw_intern(pool, "function", Keyword.Function)
|
||||||
_kw_intern(pool, "extern", Keyword.Extern)
|
_kw_intern(pool, "extern", Keyword.Extern)
|
||||||
_kw_intern(pool, "export", Keyword.Export)
|
_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:
|
class OpEntry:
|
||||||
name: str # Operator text (e.g. "==", "+=")
|
name: str # Operator text (e.g. "==", "+=")
|
||||||
op_id: t.CInt
|
op_id: int
|
||||||
length: t.CInt
|
length: int
|
||||||
next: OpEntry | t.CPtr
|
next: rowptr[OpEntry]
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr):
|
def __new__(self, pool: rowptr[memhub.MemManager]):
|
||||||
ptr: OpEntry | t.CPtr = pool.alloc(OpEntry.__sizeof__())
|
ptr: rowptr[OpEntry] = pool.alloc(OpEntry.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, OpEntry.__sizeof__())
|
string.memset(ptr, 0, OpEntry.__sizeof__())
|
||||||
return ptr
|
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
|
global _op_head
|
||||||
slen: t.CSizeT = string.strlen(name)
|
slen: t.CSizeT = string.strlen(name)
|
||||||
entry: OpEntry | t.CPtr = OpEntry(pool)
|
entry: rowptr[OpEntry] = OpEntry(pool)
|
||||||
if entry == None: return
|
if entry == None: return
|
||||||
buf: str = pool.alloc(slen + 1)
|
buf: str = pool.alloc(slen + 1)
|
||||||
if buf == None: return
|
if buf == None: return
|
||||||
string.memcpy(buf, name, slen + 1)
|
string.memcpy(buf, name, slen + 1)
|
||||||
entry.name = buf
|
entry.name = buf
|
||||||
entry.op_id = op_id
|
entry.op_id = op_id
|
||||||
entry.length = t.CInt(slen)
|
entry.length = int(slen)
|
||||||
entry.next = _op_head
|
entry.next = _op_head
|
||||||
_op_head = entry
|
_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)"""
|
"""Initialize the operator table (register in descending length order for easy greedy matching)"""
|
||||||
global _op_head
|
global _op_head
|
||||||
if _op_head != None: return
|
if _op_head != None: return
|
||||||
@@ -356,7 +360,7 @@ def _init_operators(pool: memhub.MemManager | t.CPtr):
|
|||||||
_op_intern(pool, "~", TokOp.Tilde)
|
_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)"""
|
"""Initialize all lookup tables (idempotent)"""
|
||||||
_init_keywords(pool)
|
_init_keywords(pool)
|
||||||
_init_operators(pool)
|
_init_operators(pool)
|
||||||
@@ -366,10 +370,10 @@ def _init_tables(pool: memhub.MemManager | t.CPtr):
|
|||||||
# Token creation helper functions
|
# Token creation helper functions
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt,
|
def new_token(pool: rowptr[memhub.MemManager], ttype: int, lineno: int,
|
||||||
col_offset: t.CInt) -> Token | t.CPtr:
|
col_offset: int) -> rowptr[Token]:
|
||||||
"""Create a new empty Token and fill in fields later"""
|
"""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
|
if tok == None: return None
|
||||||
tok.type = ttype
|
tok.type = ttype
|
||||||
tok.lineno = lineno
|
tok.lineno = lineno
|
||||||
@@ -379,7 +383,7 @@ def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt,
|
|||||||
return tok
|
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):
|
src: str, start: t.CSizeT, length: t.CSizeT):
|
||||||
"""Copy text from src[start:start + length] to token.str_val
|
"""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
|
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):
|
text: str):
|
||||||
"""Copy a C string to token.str_val"""
|
"""Copy a C string to token.str_val"""
|
||||||
if tok == None or text == None: return
|
if tok == None or text == None: return
|
||||||
|
|||||||
+31
@@ -1,3 +1,4 @@
|
|||||||
|
import stdint as __stdint
|
||||||
import t
|
import t
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -23,3 +24,33 @@ def max(a: double, b: double) -> double:
|
|||||||
if a > b:
|
if a > b:
|
||||||
return a
|
return a
|
||||||
return b
|
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 .__md5 import md5, MD5_DIGEST_LEN
|
||||||
from .__sha1 import sha1, SHA1_DIGEST_LEN
|
from .__sha1 import sha1, SHA1_DIGEST_LEN
|
||||||
from .__sha256 import sha256, SHA256_DIGEST_LEN
|
from .__sha256 import sha256, SHA256_DIGEST_LEN
|
||||||
from .__sha512 import sha512, SHA512_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_DIGEST_LEN: t.CDefine = 16 # Digest output length
|
||||||
|
|
||||||
# MD5 four-round nonlinear functions
|
# 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_F(x: uint32, y: uint32, z: uint32) -> uint32: 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_G(x: uint32, y: uint32, z: uint32) -> uint32: 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_H(x: uint32, y: uint32, z: uint32) -> uint32: return x ^ y ^ z
|
||||||
def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return y ^ (x | ~z)
|
def md5_I(x: uint32, y: uint32, z: uint32) -> uint32: return y ^ (x | ~z)
|
||||||
# Circular left shift
|
# 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 constant table
|
||||||
md5_T: t.CArray[t.CUInt32T, 64] = [
|
md5_T: t.CArray[uint32, 64] = [
|
||||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||||
@@ -39,9 +39,9 @@ md5_S: t.CArray[int, 64] = [
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
@t.Object
|
@t.Object
|
||||||
class md5:
|
class md5:
|
||||||
state: t.CArray[t.CUInt32T, 4] # 4 32-bit state registers
|
state: t.CArray[uint32, 4] # 4 32-bit state registers
|
||||||
count: t.CUInt64T # processed bits
|
count: uint64 # processed bits
|
||||||
buf: t.CArray[t.CUInt8T, MD5_BLOCK_LEN] # Group buffer
|
buf: t.CArray[uint8, MD5_BLOCK_LEN] # Group buffer
|
||||||
# Initialize MD5 context
|
# Initialize MD5 context
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
string.memset(self.buf, 0, MD5_BLOCK_LEN)
|
string.memset(self.buf, 0, MD5_BLOCK_LEN)
|
||||||
@@ -51,34 +51,34 @@ class md5:
|
|||||||
self.state[3] = 0x10325476
|
self.state[3] = 0x10325476
|
||||||
self.count = 0
|
self.count = 0
|
||||||
# MD5 single-group compression transform
|
# MD5 single-group compression transform
|
||||||
def transform(self, block: t.CUInt8T | t.CPtr):
|
def transform(self, block: rowptr[uint8]):
|
||||||
a: t.CUInt32T = self.state[0]
|
a: uint32 = self.state[0]
|
||||||
b: t.CUInt32T = self.state[1]
|
b: uint32 = self.state[1]
|
||||||
c: t.CUInt32T = self.state[2]
|
c: uint32 = self.state[2]
|
||||||
d: t.CUInt32T = self.state[3]
|
d: uint32 = self.state[3]
|
||||||
w: t.CArray[t.CUInt32T, 16]
|
w: t.CArray[uint32, 16]
|
||||||
# Byte order 32-bit words
|
# Byte order 32-bit words
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 0) |
|
w[i] = ((uint32(block[i * 4 + 0]) << 0) |
|
||||||
(t.CUInt32T(block[i * 4 + 1]) << 8) |
|
(uint32(block[i * 4 + 1]) << 8) |
|
||||||
(t.CUInt32T(block[i * 4 + 2]) << 16) |
|
(uint32(block[i * 4 + 2]) << 16) |
|
||||||
(t.CUInt32T(block[i * 4 + 3]) << 24))
|
(uint32(block[i * 4 + 3]) << 24))
|
||||||
# 4-round 51 iterations
|
# 4-round 51 iterations
|
||||||
for i in range(16):
|
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
|
a = d; d = c; c = b
|
||||||
b += md5_rotl(tmp, md5_S[i])
|
b += md5_rotl(tmp, md5_S[i])
|
||||||
# 4-round 51 iterations
|
# 4-round 51 iterations
|
||||||
for i in range(16, 32):
|
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
|
a = d; d = c; c = b
|
||||||
b += md5_rotl(tmp, md5_S[i])
|
b += md5_rotl(tmp, md5_S[i])
|
||||||
for i in range(32, 48):
|
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
|
a = d; d = c; c = b
|
||||||
b += md5_rotl(tmp, md5_S[i])
|
b += md5_rotl(tmp, md5_S[i])
|
||||||
for i in range(48, 64):
|
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
|
a = d; d = c; c = b
|
||||||
b += md5_rotl(tmp, md5_S[i])
|
b += md5_rotl(tmp, md5_S[i])
|
||||||
# Accumulate to state registers
|
# Accumulate to state registers
|
||||||
@@ -88,7 +88,7 @@ class md5:
|
|||||||
self.state[3] += d
|
self.state[3] += d
|
||||||
# Batch input data
|
# Batch input data
|
||||||
def update(self, s: str):
|
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)
|
length: t.CSizeT = len(s)
|
||||||
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
|
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
|
||||||
self.count += length
|
self.count += length
|
||||||
@@ -107,7 +107,7 @@ class md5:
|
|||||||
if length > 0:
|
if length > 0:
|
||||||
string.memcpy(self.buf + idx, data, length)
|
string.memcpy(self.buf + idx, data, length)
|
||||||
# End calculation, output 16-byte digest
|
# 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
|
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
|
||||||
# Pad 0x80 end
|
# Pad 0x80 end
|
||||||
self.buf[idx] = 0x80
|
self.buf[idx] = 0x80
|
||||||
@@ -120,7 +120,7 @@ class md5:
|
|||||||
# Pad 0 to end 8 bytes
|
# Pad 0 to end 8 bytes
|
||||||
string.memset(self.buf + idx, 0, MD5_BLOCK_LEN - 8 - idx)
|
string.memset(self.buf + idx, 0, MD5_BLOCK_LEN - 8 - idx)
|
||||||
# Write total bit count
|
# Write total bit count
|
||||||
bits: t.CUInt64T = self.count << 3
|
bits: uint64 = self.count << 3
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
self.buf[MD5_BLOCK_LEN - 8 + i] = (bits >> (i * 8)) & 0xFF
|
self.buf[MD5_BLOCK_LEN - 8 + i] = (bits >> (i * 8)) & 0xFF
|
||||||
self.transform(self.buf)
|
self.transform(self.buf)
|
||||||
|
|||||||
+24
-24
@@ -9,18 +9,18 @@ import t, c
|
|||||||
SHA1_BLOCK_LEN: t.CDefine = 64
|
SHA1_BLOCK_LEN: t.CDefine = 64
|
||||||
SHA1_DIGEST_LEN: t.CDefine = 20
|
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
|
# 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_f1(b: uint32, c: uint32, d: uint32) -> uint32: 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_f2(b: uint32, c: uint32, d: uint32) -> uint32: 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_f3(b: uint32, c: uint32, d: uint32) -> uint32: return (b & c) | (b & d) | (c & d)
|
||||||
|
|
||||||
# SHA1 Context
|
# SHA1 Context
|
||||||
@t.Object
|
@t.Object
|
||||||
class sha1:
|
class sha1:
|
||||||
state: t.CArray[t.CUInt32T, 5]
|
state: t.CArray[uint32, 5]
|
||||||
count: t.CUInt64T
|
count: uint64
|
||||||
buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN]
|
buf: t.CArray[uint8, SHA1_BLOCK_LEN]
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
string.memset(self.buf, 0, SHA1_BLOCK_LEN)
|
string.memset(self.buf, 0, SHA1_BLOCK_LEN)
|
||||||
self.state[0] = 0x67452301
|
self.state[0] = 0x67452301
|
||||||
@@ -30,25 +30,25 @@ class sha1:
|
|||||||
self.state[4] = 0xc3d2e1f0
|
self.state[4] = 0xc3d2e1f0
|
||||||
self.count = 0
|
self.count = 0
|
||||||
# Single-group compression transform
|
# Single-group compression transform
|
||||||
def transform(self, block: t.CUInt8T | t.CPtr):
|
def transform(self, block: rowptr[uint8]):
|
||||||
w: t.CArray[t.CUInt32T, 80]
|
w: t.CArray[uint32, 80]
|
||||||
data: t.CUInt8T | t.CPtr = block
|
data: rowptr[uint8] = block
|
||||||
# First 16 words
|
# First 16 words
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
w[i] = (((t.CUInt32T(data[i * 4 + 0])) << 24) |
|
w[i] = (((uint32(data[i * 4 + 0])) << 24) |
|
||||||
((t.CUInt32T(data[i * 4 + 1])) << 16) |
|
((uint32(data[i * 4 + 1])) << 16) |
|
||||||
((t.CUInt32T(data[i * 4 + 2])) << 8) |
|
((uint32(data[i * 4 + 2])) << 8) |
|
||||||
((t.CUInt32T(data[i * 4 + 3])) << 0))
|
((uint32(data[i * 4 + 3])) << 0))
|
||||||
# Extend to 80 words
|
# Extend to 80 words
|
||||||
for i in range(16, 80):
|
for i in range(16, 80):
|
||||||
w[i] = sha1_rotl(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16],1)
|
w[i] = sha1_rotl(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16],1)
|
||||||
a: t.CUInt32T = self.state[0]
|
a: uint32 = self.state[0]
|
||||||
b: t.CUInt32T = self.state[1]
|
b: uint32 = self.state[1]
|
||||||
c: t.CUInt32T = self.state[2]
|
c: uint32 = self.state[2]
|
||||||
d: t.CUInt32T = self.state[3]
|
d: uint32 = self.state[3]
|
||||||
e: t.CUInt32T = self.state[4]
|
e: uint32 = self.state[4]
|
||||||
k: t.CUInt32T
|
k: uint32
|
||||||
tmp: t.CUInt32T
|
tmp: uint32
|
||||||
# 4-round iterations
|
# 4-round iterations
|
||||||
for i in range(0, 20):
|
for i in range(0, 20):
|
||||||
k = 0x5a827999
|
k = 0x5a827999
|
||||||
@@ -80,7 +80,7 @@ class sha1:
|
|||||||
self.state[3] += d
|
self.state[3] += d
|
||||||
self.state[4] += e
|
self.state[4] += e
|
||||||
def update(self, s: str):
|
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)
|
length: t.CSizeT = len(s)
|
||||||
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
|
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
|
||||||
self.count += length
|
self.count += length
|
||||||
@@ -98,7 +98,7 @@ class sha1:
|
|||||||
length -= SHA1_BLOCK_LEN
|
length -= SHA1_BLOCK_LEN
|
||||||
if length > 0:
|
if length > 0:
|
||||||
string.memcpy(self.buf + idx, data, length)
|
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
|
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
|
||||||
self.buf[idx] = 0x80
|
self.buf[idx] = 0x80
|
||||||
idx += 1
|
idx += 1
|
||||||
@@ -107,7 +107,7 @@ class sha1:
|
|||||||
self.transform(self.buf)
|
self.transform(self.buf)
|
||||||
idx = 0
|
idx = 0
|
||||||
string.memset(self.buf + idx,0,SHA1_BLOCK_LEN-8-idx)
|
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
|
# SHA1 big-endian write length
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
self.buf[SHA1_BLOCK_LEN - 8 + i] = (bits >> (56 - i * 8)) & 0xFF
|
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_DIGEST_LEN: t.CDefine = 32
|
||||||
|
|
||||||
# SHA256 Constants K
|
# SHA256 Constants K
|
||||||
sha256_K: t.CArray[t.CUInt32T, 64] = [
|
sha256_K: t.CArray[uint32, 64] = [
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
@@ -21,19 +21,19 @@ sha256_K: t.CArray[t.CUInt32T, 64] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# SHA256 Auxiliary Functions
|
# SHA256 Auxiliary Functions
|
||||||
def s0(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ ((x >> 3))
|
def s0(x: uint32) -> uint32: 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 s1(x: uint32) -> uint32: 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 S0(x: uint32) -> uint32: 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 S1(x: uint32) -> uint32: 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 Ch(x: uint32, y: uint32, z: uint32) -> uint32: 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 Maj(x: uint32, y: uint32, z: uint32) -> uint32: return (x & y) ^ (x & z) ^ (y & z)
|
||||||
|
|
||||||
# SHA256 Context
|
# SHA256 Context
|
||||||
@t.Object
|
@t.Object
|
||||||
class sha256:
|
class sha256:
|
||||||
state: t.CArray[t.CUInt32T, 8]
|
state: t.CArray[uint32, 8]
|
||||||
count: t.CUInt64T
|
count: uint64
|
||||||
buf: t.CArray[t.CUInt8T, SHA256_BLOCK_LEN]
|
buf: t.CArray[uint8, SHA256_BLOCK_LEN]
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
string.memset(self, 0, sha256.__sizeof__())
|
string.memset(self, 0, sha256.__sizeof__())
|
||||||
self.state[0] = 0x6a09e667
|
self.state[0] = 0x6a09e667
|
||||||
@@ -47,26 +47,26 @@ class sha256:
|
|||||||
self.count = 0
|
self.count = 0
|
||||||
# string.memset(self.buf, 0, SHA256_BLOCK_LEN)
|
# string.memset(self.buf, 0, SHA256_BLOCK_LEN)
|
||||||
# SHA256 single-group compression transform
|
# SHA256 single-group compression transform
|
||||||
def transform(self, block: t.CUInt8T | t.CPtr):
|
def transform(self, block: rowptr[uint8]):
|
||||||
w: t.CArray[t.CUInt32T, 64]
|
w: t.CArray[uint32, 64]
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 24) |
|
w[i] = ((uint32(block[i * 4 + 0]) << 24) |
|
||||||
(t.CUInt32T(block[i * 4 + 1]) << 16) |
|
(uint32(block[i * 4 + 1]) << 16) |
|
||||||
(t.CUInt32T(block[i * 4 + 2]) << 8 ) |
|
(uint32(block[i * 4 + 2]) << 8 ) |
|
||||||
(t.CUInt32T(block[i * 4 + 3]) << 0 ))
|
(uint32(block[i * 4 + 3]) << 0 ))
|
||||||
# Extend to 64 words
|
# Extend to 64 words
|
||||||
for i in range(16, 64):
|
for i in range(16, 64):
|
||||||
w[i] = w[i-16] + s0(w[i-15]) + w[i-7] + s1(w[i-2])
|
w[i] = w[i-16] + s0(w[i-15]) + w[i-7] + s1(w[i-2])
|
||||||
a: t.CUInt32T = self.state[0]
|
a: uint32 = self.state[0]
|
||||||
b: t.CUInt32T = self.state[1]
|
b: uint32 = self.state[1]
|
||||||
c: t.CUInt32T = self.state[2]
|
c: uint32 = self.state[2]
|
||||||
d: t.CUInt32T = self.state[3]
|
d: uint32 = self.state[3]
|
||||||
e: t.CUInt32T = self.state[4]
|
e: uint32 = self.state[4]
|
||||||
f: t.CUInt32T = self.state[5]
|
f: uint32 = self.state[5]
|
||||||
g: t.CUInt32T = self.state[6]
|
g: uint32 = self.state[6]
|
||||||
h: t.CUInt32T = self.state[7]
|
h: uint32 = self.state[7]
|
||||||
t1: t.CUInt32T
|
t1: uint32
|
||||||
t2: t.CUInt32T
|
t2: uint32
|
||||||
# 64-round iterations
|
# 64-round iterations
|
||||||
for i in range(64):
|
for i in range(64):
|
||||||
t1 = h + S1(e) + Ch(e,f,g) + sha256_K[i] + w[i]
|
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[6] += g
|
||||||
self.state[7] += h
|
self.state[7] += h
|
||||||
def update(self, s: str):
|
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)
|
length: t.CSizeT = len(s)
|
||||||
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
|
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
|
||||||
self.count += length
|
self.count += length
|
||||||
@@ -103,7 +103,7 @@ class sha256:
|
|||||||
length -= SHA256_BLOCK_LEN
|
length -= SHA256_BLOCK_LEN
|
||||||
if length > 0:
|
if length > 0:
|
||||||
string.memcpy(self.buf + idx, data, length)
|
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
|
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
|
||||||
self.buf[idx] = 0x80
|
self.buf[idx] = 0x80
|
||||||
idx += 1
|
idx += 1
|
||||||
@@ -112,7 +112,7 @@ class sha256:
|
|||||||
self.transform(self.buf)
|
self.transform(self.buf)
|
||||||
idx = 0
|
idx = 0
|
||||||
string.memset(self.buf + idx, 0, SHA256_BLOCK_LEN - 8 - idx)
|
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):
|
for i in range(8):
|
||||||
self.buf[SHA256_BLOCK_LEN-8+i] = (bits >> (56 - i*8)) & 0xFF
|
self.buf[SHA256_BLOCK_LEN-8+i] = (bits >> (56 - i*8)) & 0xFF
|
||||||
self.transform(self.buf)
|
self.transform(self.buf)
|
||||||
|
|||||||
+49
-49
@@ -1,4 +1,4 @@
|
|||||||
import t, c
|
import t, c
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
|
||||||
@@ -8,16 +8,16 @@ import string
|
|||||||
SHA512_BLOCK_LEN: t.CDefine = 128
|
SHA512_BLOCK_LEN: t.CDefine = 128
|
||||||
SHA512_DIGEST_LEN: t.CDefine = 64
|
SHA512_DIGEST_LEN: t.CDefine = 64
|
||||||
|
|
||||||
def sha512_ror(x: t.CUInt64T, n: int) -> t.CUInt64T: return (x >> n) | (x << (64 - n))
|
def sha512_ror(x: uint64, n: int) -> uint64: return (x >> n) | (x << (64 - n))
|
||||||
def sha512_shr(x: t.CUInt64T, n: int) -> t.CUInt64T: return x >> n
|
def sha512_shr(x: uint64, n: int) -> uint64: return x >> n
|
||||||
def sha512_Ch (x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: return (x & y) ^ (~x & z)
|
def sha512_Ch (x: uint64, y: uint64, z: uint64) -> uint64: 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_Maj(x: uint64, y: uint64, z: uint64) -> uint64: 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_BigSigma0(x: uint64) -> uint64: 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_BigSigma1(x: uint64) -> uint64: 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_Sigma0(x: uint64) -> uint64: 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_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,
|
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
||||||
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
||||||
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
||||||
@@ -42,9 +42,9 @@ sha512_K: t.CArray[t.CUInt64T, 80] = [
|
|||||||
|
|
||||||
@t.Object
|
@t.Object
|
||||||
class sha512:
|
class sha512:
|
||||||
state: t.CArray[t.CUInt64T, 8]
|
state: t.CArray[uint64, 8]
|
||||||
count: t.CArray[t.CUInt64T, 2]
|
count: t.CArray[uint64, 2]
|
||||||
buf: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]
|
buf: t.CArray[uint8, SHA512_BLOCK_LEN]
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
string.memset(self, 0, sha512.__sizeof__())
|
string.memset(self, 0, sha512.__sizeof__())
|
||||||
self.state[0] = 0x6a09e667f3bcc908
|
self.state[0] = 0x6a09e667f3bcc908
|
||||||
@@ -55,27 +55,27 @@ class sha512:
|
|||||||
self.state[5] = 0x9b05688c2b3e6c1f
|
self.state[5] = 0x9b05688c2b3e6c1f
|
||||||
self.state[6] = 0x1f83d9abfb41bd6b
|
self.state[6] = 0x1f83d9abfb41bd6b
|
||||||
self.state[7] = 0x5be0cd19137e2179
|
self.state[7] = 0x5be0cd19137e2179
|
||||||
def transform(self, block: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]):
|
def transform(self, block: t.CArray[uint8, SHA512_BLOCK_LEN]):
|
||||||
w: t.CArray[t.CUInt64T, 80]
|
w: t.CArray[uint64, 80]
|
||||||
a: t.CUInt64T
|
a: uint64
|
||||||
b: t.CUInt64T
|
b: uint64
|
||||||
c: t.CUInt64T
|
c: uint64
|
||||||
d: t.CUInt64T
|
d: uint64
|
||||||
e: t.CUInt64T
|
e: uint64
|
||||||
f: t.CUInt64T
|
f: uint64
|
||||||
g: t.CUInt64T
|
g: uint64
|
||||||
h: t.CUInt64T
|
h: uint64
|
||||||
t1: t.CUInt64T
|
t1: uint64
|
||||||
t2: t.CUInt64T
|
t2: uint64
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
w[i] = t.CUInt64T(block[i * 8 + 0]) << 56
|
w[i] = uint64(block[i * 8 + 0]) << 56
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 1]) << 48
|
w[i] |= uint64(block[i * 8 + 1]) << 48
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 2]) << 40
|
w[i] |= uint64(block[i * 8 + 2]) << 40
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 3]) << 32
|
w[i] |= uint64(block[i * 8 + 3]) << 32
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 4]) << 24
|
w[i] |= uint64(block[i * 8 + 4]) << 24
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 5]) << 16
|
w[i] |= uint64(block[i * 8 + 5]) << 16
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 6]) << 8
|
w[i] |= uint64(block[i * 8 + 6]) << 8
|
||||||
w[i] |= t.CUInt64T(block[i * 8 + 7]) << 0
|
w[i] |= uint64(block[i * 8 + 7]) << 0
|
||||||
for i in range(16, 80):
|
for i in range(16, 80):
|
||||||
w[i] = sha512_Sigma1(w[i-2]) + w[i-7] + sha512_Sigma0(w[i-15]) + w[i-16]
|
w[i] = sha512_Sigma1(w[i-2]) + w[i-7] + sha512_Sigma0(w[i-15]) + w[i-16]
|
||||||
a = self.state[0]
|
a = self.state[0]
|
||||||
@@ -102,9 +102,9 @@ class sha512:
|
|||||||
self.state[6] += g
|
self.state[6] += g
|
||||||
self.state[7] += h
|
self.state[7] += h
|
||||||
def update(self, s: str):
|
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)
|
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
|
self.count[0] += length
|
||||||
if self.count[0] < length:
|
if self.count[0] < length:
|
||||||
self.count[1] += 1
|
self.count[1] += 1
|
||||||
@@ -122,10 +122,10 @@ class sha512:
|
|||||||
length -= SHA512_BLOCK_LEN
|
length -= SHA512_BLOCK_LEN
|
||||||
if length > 0:
|
if length > 0:
|
||||||
string.memcpy(self.buf + idx, data, length)
|
string.memcpy(self.buf + idx, data, length)
|
||||||
def final(self, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]):
|
def final(self, out: t.CArray[uint8, SHA512_DIGEST_LEN]):
|
||||||
bits_lo: t.CUInt64T = self.count[0] << 3
|
bits_lo: uint64 = self.count[0] << 3
|
||||||
bits_hi: t.CUInt64T = (self.count[1] << 3) | (self.count[0] >> 61)
|
bits_hi: uint64 = (self.count[1] << 3) | (self.count[0] >> 61)
|
||||||
idx: t.CUInt32T = t.CUInt32T(self.count[0] % SHA512_BLOCK_LEN)
|
idx: uint32 = uint32(self.count[0] % SHA512_BLOCK_LEN)
|
||||||
self.buf[idx] = 0x80
|
self.buf[idx] = 0x80
|
||||||
idx += 1
|
idx += 1
|
||||||
if idx > SHA512_BLOCK_LEN - 16:
|
if idx > SHA512_BLOCK_LEN - 16:
|
||||||
@@ -134,16 +134,16 @@ class sha512:
|
|||||||
idx = 0
|
idx = 0
|
||||||
string.memset(self.buf + idx, 0, SHA512_BLOCK_LEN - 16 - idx)
|
string.memset(self.buf + idx, 0, SHA512_BLOCK_LEN - 16 - idx)
|
||||||
for i in range(8):
|
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):
|
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)
|
self.transform(self.buf)
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
out[i * 8 + 0] = t.CUInt8T(self.state[i] >> 56)
|
out[i * 8 + 0] = uint8(self.state[i] >> 56)
|
||||||
out[i * 8 + 1] = t.CUInt8T(self.state[i] >> 48)
|
out[i * 8 + 1] = uint8(self.state[i] >> 48)
|
||||||
out[i * 8 + 2] = t.CUInt8T(self.state[i] >> 40)
|
out[i * 8 + 2] = uint8(self.state[i] >> 40)
|
||||||
out[i * 8 + 3] = t.CUInt8T(self.state[i] >> 32)
|
out[i * 8 + 3] = uint8(self.state[i] >> 32)
|
||||||
out[i * 8 + 4] = t.CUInt8T(self.state[i] >> 24)
|
out[i * 8 + 4] = uint8(self.state[i] >> 24)
|
||||||
out[i * 8 + 5] = t.CUInt8T(self.state[i] >> 16)
|
out[i * 8 + 5] = uint8(self.state[i] >> 16)
|
||||||
out[i * 8 + 6] = t.CUInt8T(self.state[i] >> 8)
|
out[i * 8 + 6] = uint8(self.state[i] >> 8)
|
||||||
out[i * 8 + 7] = t.CUInt8T(self.state[i] >> 0)
|
out[i * 8 + 7] = uint8(self.state[i] >> 0)
|
||||||
+27
-27
@@ -23,17 +23,17 @@ JSON_OBJECT: t.CDefine = 6
|
|||||||
class JsonValue:
|
class JsonValue:
|
||||||
vtype: int
|
vtype: int
|
||||||
bool_val: int
|
bool_val: int
|
||||||
int_val: t.CInt64T
|
int_val: int64
|
||||||
float_val: t.CDouble
|
float_val: double
|
||||||
str_val: str
|
str_val: str
|
||||||
next: 'JsonValue' | t.CPtr
|
next: 'JsonValue' | t.CPtr
|
||||||
key: str
|
key: str
|
||||||
child: 'JsonValue' | t.CPtr
|
child: 'JsonValue' | t.CPtr
|
||||||
child_count: t.CSizeT
|
child_count: t.CSizeT
|
||||||
|
|
||||||
def __new__(self, pool: memhub.MemManager | t.CPtr):
|
def __new__(self, pool: rowptr[memhub.MemManager]):
|
||||||
"""从 mpool 分配 JsonValue 结构体内存并零初始化"""
|
"""从 mpool 分配 JsonValue 结构体内存并零初始化"""
|
||||||
ptr: JsonValue | t.CPtr = pool.alloc(JsonValue.__sizeof__())
|
ptr: rowptr[JsonValue] = pool.alloc(JsonValue.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, JsonValue.__sizeof__())
|
string.memset(ptr, 0, JsonValue.__sizeof__())
|
||||||
return ptr
|
return ptr
|
||||||
@@ -65,10 +65,10 @@ class JsonValue:
|
|||||||
def as_bool(self) -> bool:
|
def as_bool(self) -> bool:
|
||||||
return self.bool_val != 0
|
return self.bool_val != 0
|
||||||
|
|
||||||
def as_int(self) -> t.CInt64T:
|
def as_int(self) -> int64:
|
||||||
return self.int_val
|
return self.int_val
|
||||||
|
|
||||||
def as_float(self) -> t.CDouble:
|
def as_float(self) -> double:
|
||||||
return self.float_val
|
return self.float_val
|
||||||
|
|
||||||
def as_string(self) -> str:
|
def as_string(self) -> str:
|
||||||
@@ -83,7 +83,7 @@ class JsonValue:
|
|||||||
return None
|
return None
|
||||||
if key == None:
|
if key == None:
|
||||||
return None
|
return None
|
||||||
cur: JsonValue | t.CPtr = self.child
|
cur: rowptr[JsonValue] = self.child
|
||||||
while cur != None:
|
while cur != None:
|
||||||
if cur.key != None:
|
if cur.key != None:
|
||||||
if string.strcmp(cur.key, key) == 0:
|
if string.strcmp(cur.key, key) == 0:
|
||||||
@@ -95,7 +95,7 @@ class JsonValue:
|
|||||||
"""Python风格赋值:v["key"] = val"""
|
"""Python风格赋值:v["key"] = val"""
|
||||||
if self.vtype != JSON_OBJECT or key == None or val == None:
|
if self.vtype != JSON_OBJECT or key == None or val == None:
|
||||||
return
|
return
|
||||||
cur: JsonValue | t.CPtr = self.child
|
cur: rowptr[JsonValue] = self.child
|
||||||
while cur != None:
|
while cur != None:
|
||||||
if cur.key != None:
|
if cur.key != None:
|
||||||
if string.strcmp(cur.key, key) == 0:
|
if string.strcmp(cur.key, key) == 0:
|
||||||
@@ -120,7 +120,7 @@ class JsonValue:
|
|||||||
"""按索引取数组元素:v.get_item(0)"""
|
"""按索引取数组元素:v.get_item(0)"""
|
||||||
if self.vtype != JSON_ARRAY and self.vtype != JSON_OBJECT:
|
if self.vtype != JSON_ARRAY and self.vtype != JSON_OBJECT:
|
||||||
return None
|
return None
|
||||||
cur: JsonValue | t.CPtr = self.child
|
cur: rowptr[JsonValue] = self.child
|
||||||
i: t.CSizeT = 0
|
i: t.CSizeT = 0
|
||||||
while cur != None:
|
while cur != None:
|
||||||
if i == index:
|
if i == index:
|
||||||
@@ -137,7 +137,7 @@ class JsonValue:
|
|||||||
if self.child == None:
|
if self.child == None:
|
||||||
self.child = child
|
self.child = child
|
||||||
else:
|
else:
|
||||||
cur: JsonValue | t.CPtr = self.child
|
cur: rowptr[JsonValue] = self.child
|
||||||
while cur.next != None:
|
while cur.next != None:
|
||||||
cur = cur.next
|
cur = cur.next
|
||||||
cur.next = child
|
cur.next = child
|
||||||
@@ -148,35 +148,35 @@ class JsonValue:
|
|||||||
# 构造函数:创建各类 JsonValue(从 mpool 分配)
|
# 构造函数:创建各类 JsonValue(从 mpool 分配)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def null(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
|
def null(pool: rowptr[memhub.MemManager]) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_NULL
|
v.vtype = JSON_NULL
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def bool_val(pool: memhub.MemManager | t.CPtr, val: bool) -> JsonValue | t.CPtr:
|
def bool_val(pool: rowptr[memhub.MemManager], val: bool) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_BOOL
|
v.vtype = JSON_BOOL
|
||||||
v.bool_val = 1 if val else 0
|
v.bool_val = 1 if val else 0
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def int_val(pool: memhub.MemManager | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr:
|
def int_val(pool: rowptr[memhub.MemManager], val: int64) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_INT
|
v.vtype = JSON_INT
|
||||||
v.int_val = val
|
v.int_val = val
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr:
|
def float_val(pool: rowptr[memhub.MemManager], val: double) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_FLOAT
|
v.vtype = JSON_FLOAT
|
||||||
v.float_val = val
|
v.float_val = val
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def string_val(pool: memhub.MemManager | t.CPtr, val: str) -> JsonValue | t.CPtr:
|
def string_val(pool: rowptr[memhub.MemManager], val: str) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_STRING
|
v.vtype = JSON_STRING
|
||||||
if val != None:
|
if val != None:
|
||||||
@@ -187,29 +187,29 @@ def string_val(pool: memhub.MemManager | t.CPtr, val: str) -> JsonValue | t.CPtr
|
|||||||
v.str_val = buf
|
v.str_val = buf
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def array(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
|
def array(pool: rowptr[memhub.MemManager]) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_ARRAY
|
v.vtype = JSON_ARRAY
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def object(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
|
def object(pool: rowptr[memhub.MemManager]) -> rowptr[JsonValue]:
|
||||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
v: rowptr[JsonValue] = JsonValue(pool)
|
||||||
if v == None: return None
|
if v == None: return None
|
||||||
v.vtype = JSON_OBJECT
|
v.vtype = JSON_OBJECT
|
||||||
return v
|
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 == None or item == None: return
|
||||||
if arr.vtype != JSON_ARRAY: return
|
if arr.vtype != JSON_ARRAY: return
|
||||||
arr._append_child(item)
|
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 == None or key == None or val == None: return
|
||||||
if obj.vtype != JSON_OBJECT: return
|
if obj.vtype != JSON_OBJECT: return
|
||||||
cur: JsonValue | t.CPtr = obj.child
|
cur: rowptr[JsonValue] = obj.child
|
||||||
while cur != None:
|
while cur != None:
|
||||||
if cur.key != None:
|
if cur.key != None:
|
||||||
if string.strcmp(cur.key, key) == 0:
|
if string.strcmp(cur.key, key) == 0:
|
||||||
|
|||||||
+19
-19
@@ -13,28 +13,28 @@ class ParseState:
|
|||||||
src: str
|
src: str
|
||||||
pos: t.CSizeT
|
pos: t.CSizeT
|
||||||
len: 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.src = src
|
||||||
self.pos = 0
|
self.pos = 0
|
||||||
self.len = string.strlen(src) if src != None else 0
|
self.len = string.strlen(src) if src != None else 0
|
||||||
self.pool = pool
|
self.pool = pool
|
||||||
|
|
||||||
|
|
||||||
def _peek(s: ParseState | t.CPtr) -> t.CChar:
|
def _peek(s: rowptr[ParseState]) -> t.CChar:
|
||||||
if s.pos >= s.len:
|
if s.pos >= s.len:
|
||||||
return '\0'
|
return '\0'
|
||||||
return s.src[s.pos]
|
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:
|
if s.pos >= s.len:
|
||||||
return '\0'
|
return '\0'
|
||||||
ch: t.CChar = s.src[s.pos]
|
ch: t.CChar = s.src[s.pos]
|
||||||
s.pos += 1
|
s.pos += 1
|
||||||
return ch
|
return ch
|
||||||
|
|
||||||
def _skip_whitespace(s: ParseState | t.CPtr):
|
def _skip_whitespace(s: rowptr[ParseState]):
|
||||||
while s.pos < s.len:
|
while s.pos < s.len:
|
||||||
ch: t.CChar = s.src[s.pos]
|
ch: t.CChar = s.src[s.pos]
|
||||||
if ch == ' ' or ch == '\t' or ch == '\n' or ch == '\r':
|
if ch == ' ' or ch == '\t' or ch == '\n' or ch == '\r':
|
||||||
@@ -42,7 +42,7 @@ def _skip_whitespace(s: ParseState | t.CPtr):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool:
|
def _expect(s: rowptr[ParseState], ch: t.CChar) -> bool:
|
||||||
_skip_whitespace(s)
|
_skip_whitespace(s)
|
||||||
if s.pos >= s.len:
|
if s.pos >= s.len:
|
||||||
return False
|
return False
|
||||||
@@ -52,7 +52,7 @@ def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _parse_string(s: ParseState | t.CPtr) -> str:
|
def _parse_string(s: rowptr[ParseState]) -> str:
|
||||||
if _peek(s) != '"':
|
if _peek(s) != '"':
|
||||||
return None
|
return None
|
||||||
_advance(s)
|
_advance(s)
|
||||||
@@ -109,7 +109,7 @@ def _parse_string(s: ParseState | t.CPtr) -> str:
|
|||||||
return buf
|
return buf
|
||||||
|
|
||||||
|
|
||||||
def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
def _parse_number(s: rowptr[ParseState]) -> rowptr[JsonValue]:
|
||||||
_skip_whitespace(s)
|
_skip_whitespace(s)
|
||||||
is_float: bool = False
|
is_float: bool = False
|
||||||
start: t.CSizeT = s.pos
|
start: t.CSizeT = s.pos
|
||||||
@@ -158,14 +158,14 @@ def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
|||||||
buf[num_len] = '\0'
|
buf[num_len] = '\0'
|
||||||
|
|
||||||
if is_float:
|
if is_float:
|
||||||
val: t.CDouble = string.atof(buf)
|
val: double = string.atof(buf)
|
||||||
return float_val(s.pool, val)
|
return float_val(s.pool, val)
|
||||||
else:
|
else:
|
||||||
ival: t.CInt64T = string.atoll(buf)
|
ival: int64 = string.atoll(buf)
|
||||||
return int_val(s.pool, ival)
|
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)
|
_skip_whitespace(s)
|
||||||
if s.pos >= s.len:
|
if s.pos >= s.len:
|
||||||
return null(s.pool)
|
return null(s.pool)
|
||||||
@@ -209,18 +209,18 @@ def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
|||||||
return null(s.pool)
|
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, '['):
|
if not _expect(s, '['):
|
||||||
return null(s.pool)
|
return null(s.pool)
|
||||||
|
|
||||||
arr: JsonValue | t.CPtr = array(s.pool)
|
arr: rowptr[JsonValue] = array(s.pool)
|
||||||
|
|
||||||
_skip_whitespace(s)
|
_skip_whitespace(s)
|
||||||
if s.pos < s.len and _peek(s) == ']':
|
if s.pos < s.len and _peek(s) == ']':
|
||||||
_advance(s)
|
_advance(s)
|
||||||
return arr
|
return arr
|
||||||
|
|
||||||
item: JsonValue | t.CPtr = _parse_value(s)
|
item: rowptr[JsonValue] = _parse_value(s)
|
||||||
arr._append_child(item)
|
arr._append_child(item)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -237,11 +237,11 @@ def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
|||||||
return arr
|
return arr
|
||||||
|
|
||||||
|
|
||||||
def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
def _parse_object(s: rowptr[ParseState]) -> rowptr[JsonValue]:
|
||||||
if not _expect(s, '{'):
|
if not _expect(s, '{'):
|
||||||
return null(s.pool)
|
return null(s.pool)
|
||||||
|
|
||||||
obj: JsonValue | t.CPtr = object(s.pool)
|
obj: rowptr[JsonValue] = object(s.pool)
|
||||||
|
|
||||||
_skip_whitespace(s)
|
_skip_whitespace(s)
|
||||||
if s.pos < s.len and _peek(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)
|
_skip_whitespace(s)
|
||||||
key: str = _parse_string(s)
|
key: str = _parse_string(s)
|
||||||
_expect(s, ':')
|
_expect(s, ':')
|
||||||
val: JsonValue | t.CPtr = _parse_value(s)
|
val: rowptr[JsonValue] = _parse_value(s)
|
||||||
if key != None and val != None:
|
if key != None and val != None:
|
||||||
klen: t.CSizeT = string.strlen(key)
|
klen: t.CSizeT = string.strlen(key)
|
||||||
kbuf: str = s.pool.alloc(klen + 1)
|
kbuf: str = s.pool.alloc(klen + 1)
|
||||||
@@ -283,9 +283,9 @@ def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
|||||||
return obj
|
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 树"""
|
"""解析 JSON 字符串,返回 JsonValue 树"""
|
||||||
if src == None:
|
if src == None:
|
||||||
return null(pool)
|
return null(pool)
|
||||||
s: ParseState | t.CPtr = ParseState(src, pool)
|
s: rowptr[ParseState] = ParseState(src, pool)
|
||||||
return _parse_value(s)
|
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
|
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:
|
if val == None:
|
||||||
pos = _write_str(buf, pos, "null")
|
pos = _write_str(buf, pos, "null")
|
||||||
return pos
|
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, "[]")
|
pos = _write_str(buf, pos, "[]")
|
||||||
return pos
|
return pos
|
||||||
pos = _write_char(buf, pos, '[')
|
pos = _write_char(buf, pos, '[')
|
||||||
cur: JsonValue | t.CPtr = val.child
|
cur: rowptr[JsonValue] = val.child
|
||||||
first: bool = True
|
first: bool = True
|
||||||
while cur != None:
|
while cur != None:
|
||||||
if not first:
|
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, "{}")
|
pos = _write_str(buf, pos, "{}")
|
||||||
return pos
|
return pos
|
||||||
pos = _write_char(buf, pos, '{')
|
pos = _write_char(buf, pos, '{')
|
||||||
cur2: JsonValue | t.CPtr = val.child
|
cur2: rowptr[JsonValue] = val.child
|
||||||
first2: bool = True
|
first2: bool = True
|
||||||
while cur2 != None:
|
while cur2 != None:
|
||||||
if not first2:
|
if not first2:
|
||||||
@@ -109,7 +109,7 @@ def _write_value(buf: str, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.
|
|||||||
return pos
|
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 字符串"""
|
"""将 JsonValue 序列化为 JSON 字符串"""
|
||||||
buf: str = pool.alloc(4096)
|
buf: str = pool.alloc(4096)
|
||||||
if buf == None:
|
if buf == None:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import t, c
|
import t, c
|
||||||
from stdint import *
|
from stdint import *
|
||||||
|
import stdio
|
||||||
|
import stdlib
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -334,6 +336,37 @@ class GSList[T]:
|
|||||||
"""Append node to the end of the list (O(1))."""
|
"""Append node to the end of the list (O(1))."""
|
||||||
if node is None:
|
if node is None:
|
||||||
return
|
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
|
node.Next = None
|
||||||
if self.Head is None:
|
if self.Head is None:
|
||||||
self.Head = node
|
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
|
@t.NoVTable
|
||||||
class Line(GSListNode[Line]):
|
class Line(GSListNode[Line]):
|
||||||
Buf: t.CChar | t.CPtr # 行文本(NUL 结尾)
|
Buf: str # 行文本(NUL 结尾)
|
||||||
Len: t.CSizeT # 文本长度(不含 NUL)
|
Len: t.CSizeT # 文本长度(不含 NUL)
|
||||||
|
|
||||||
|
|
||||||
@@ -42,9 +42,9 @@ class Line(GSListNode[Line]):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class BasicBlock(GSListNode[BasicBlock]):
|
class BasicBlock(GSListNode[BasicBlock]):
|
||||||
Name: t.CChar | t.CPtr # 块名(如 "entry"/"if.then")
|
Name: str # 块名(如 "entry"/"if.then")
|
||||||
Lines: GSList[Line] | t.CPtr # 指令行链表容器(Head/Tail/Count)
|
Lines: rowptr[GSList[Line]] # 指令行链表容器(Head/Tail/Count)
|
||||||
IsTerminated: t.CInt # 1=已有终止指令(br/ret)
|
IsTerminated: int # 1=已有终止指令(br/ret)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -57,9 +57,9 @@ class BasicBlock(GSListNode[BasicBlock]):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class Param(GSListNode[Param]):
|
class Param(GSListNode[Param]):
|
||||||
Ty: LLVMType | t.CPtr # 参数类型
|
Ty: rowptr[LLVMType] # 参数类型
|
||||||
Name: t.CChar | t.CPtr # 参数名(如 "%0"/"%a")
|
Name: str # 参数名(如 "%0"/"%a")
|
||||||
Attrs: t.CChar | t.CPtr # 参数属性文本(None=无属性)
|
Attrs: str # 参数属性文本(None=无属性)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -74,13 +74,15 @@ class Param(GSListNode[Param]):
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class Function(GSListNode[Function]):
|
class Function(GSListNode[Function]):
|
||||||
Name: t.CChar | t.CPtr # 函数名
|
Name: str # 函数名
|
||||||
RetTy: LLVMType | t.CPtr # 返回类型
|
RetTy: rowptr[LLVMType] # 返回类型
|
||||||
Params: GSList[Param] | t.CPtr # 参数链表容器
|
Params: rowptr[GSList[Param]] # 参数链表容器
|
||||||
Blocks: GSList[BasicBlock] | t.CPtr # 基本块链表容器
|
Blocks: rowptr[GSList[BasicBlock]] # 基本块链表容器
|
||||||
IsDeclared: t.CInt # 1=仅声明(declare), 0=定义(define)
|
IsDeclared: int # 1=仅声明(declare), 0=定义(define)
|
||||||
IsVarArg: t.CInt # 1=变参函数(...)
|
IsVarArg: int # 1=变参函数(...)
|
||||||
Attrs: t.CChar | t.CPtr # 函数属性文本(None=无属性)
|
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 硬编码大小: Next(8) + Buf(8) + Len(8) = 24 字节
|
||||||
LINE_SIZE: t.CDefine = 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 到新分配的缓冲区"""
|
"""创建一个指令行,复制 text 到新分配的缓冲区"""
|
||||||
ptr: Line | t.CPtr = pool.alloc(LINE_SIZE)
|
ptr: rowptr[Line] = pool.alloc(LINE_SIZE)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, LINE_SIZE)
|
string.memset(ptr, 0, LINE_SIZE)
|
||||||
if text is not None:
|
if text is not None:
|
||||||
slen: t.CSizeT = string.strlen(text)
|
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:
|
if buf is not None:
|
||||||
string.strcpy(buf, text)
|
string.strcpy(buf, text)
|
||||||
ptr.Buf = buf
|
ptr.Buf = buf
|
||||||
@@ -104,7 +106,7 @@ def new_line(pool: memhub.MemBuddy | t.CPtr, text: t.CChar | t.CPtr) -> Line | t
|
|||||||
return ptr
|
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 全零)"""
|
"""从 pool 分配并零初始化一个 GSList 容器(Head/Tail/Count 全零)"""
|
||||||
gsl: t.CPtr = pool.alloc(list_size)
|
gsl: t.CPtr = pool.alloc(list_size)
|
||||||
if gsl is None: return None
|
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 字节
|
# BasicBlock 硬编码大小: Next(8) + Name(8) + Lines(8) + IsTerminated(4) = 32 字节
|
||||||
BLOCK_SIZE: t.CDefine = 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
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, BLOCK_SIZE)
|
string.memset(ptr, 0, BLOCK_SIZE)
|
||||||
ptr.Name = name
|
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 硬编码大小: Next(8) + Ty(8) + Name(8) + Attrs(8) = 32 字节
|
||||||
PARAM_SIZE: t.CDefine = 32
|
PARAM_SIZE: t.CDefine = 32
|
||||||
|
|
||||||
def new_param(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
def new_param(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
|
||||||
name: t.CChar | t.CPtr) -> Param | t.CPtr:
|
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
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, PARAM_SIZE)
|
string.memset(ptr, 0, PARAM_SIZE)
|
||||||
ptr.Ty = ty
|
ptr.Ty = ty
|
||||||
@@ -141,13 +143,13 @@ def new_param(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
# Function 硬编码大小: Next(8) + Name(8) + RetTy(8) + Params(8) + Blocks(8) + IsDeclared(4) + IsVarArg(4) + Attrs(8) = 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 = 56
|
FUNC_SIZE: t.CDefine = 72
|
||||||
|
|
||||||
def new_function(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr,
|
def new_function(pool: rowptr[memhub.MemBuddy], name: str,
|
||||||
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
|
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
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, FUNC_SIZE)
|
string.memset(ptr, 0, FUNC_SIZE)
|
||||||
ptr.Name = name
|
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.Blocks = _new_gslist(pool, 24)
|
||||||
ptr.IsDeclared = 0
|
ptr.IsDeclared = 0
|
||||||
ptr.Attrs = None
|
ptr.Attrs = None
|
||||||
|
ptr.AttrGroup = None
|
||||||
|
ptr.AttrGroupId = 0
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# 链表操作(委托 GSList.append)
|
# 链表操作(委托 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
|
if func is None or param is None: return
|
||||||
# 注意:必须先用局部变量 + 类型参数(对齐 function_move_block_to_end 注释),
|
# 注意:必须先用局部变量 + 类型参数(对齐 function_move_block_to_end 注释),
|
||||||
# 链式 func.Params.append() 会被编译器解析成 LinkedNode.append 且 this 前移
|
# 链式 func.Params.append() 会被编译器解析成 LinkedNode.append 且 this 前移
|
||||||
# sizeof(LinkedNode)(兄弟 Mixin 兜底误匹配),写穿容器前 48 字节破坏数据结构。
|
# sizeof(LinkedNode)(兄弟 Mixin 兜底误匹配),写穿容器前 48 字节破坏数据结构。
|
||||||
params: GSList[Param] | t.CPtr = func.Params
|
params: rowptr[GSList[Param]] = func.Params
|
||||||
if params is None: return
|
if params is None: return
|
||||||
params.append(param)
|
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
|
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
|
if blocks is None: return
|
||||||
blocks.append(block)
|
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 文本顺序与控制流顺序一致)。
|
"""将 block 移动到函数块链表末尾(保证 BB 文本顺序与控制流顺序一致)。
|
||||||
|
|
||||||
用于解决 SSA 名非单调问题: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 字段访问读取垃圾值。
|
struct 类型,导致 blocks.Head/Tail/Count 字段访问读取垃圾值。
|
||||||
"""
|
"""
|
||||||
if func is None or block is None: return
|
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
|
if blocks is None: return
|
||||||
|
|
||||||
# 已经是 Tail,无需移动
|
# 已经是 Tail,无需移动
|
||||||
@@ -205,7 +209,7 @@ def function_move_block_to_end(func: Function | t.CPtr, block: BasicBlock | t.CP
|
|||||||
blocks.Head = block.Next
|
blocks.Head = block.Next
|
||||||
else:
|
else:
|
||||||
# 遍历找前驱
|
# 遍历找前驱
|
||||||
prev: BasicBlock | t.CPtr = blocks.Head
|
prev: rowptr[BasicBlock] = blocks.Head
|
||||||
while prev is not None and prev.Next is not block:
|
while prev is not None and prev.Next is not block:
|
||||||
prev = prev.Next
|
prev = prev.Next
|
||||||
if prev is None:
|
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
|
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
|
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
|
if lines is None: return
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
|
|
||||||
def block_set_terminated(block: BasicBlock | t.CPtr, val: t.CInt):
|
def block_set_terminated(block: rowptr[BasicBlock], val: int):
|
||||||
"""设置块的终止标志(供跨模块调用,避免链式属性访问的 opaque 类型问题)"""
|
"""设置块的终止标志(供跨模块调用,避免链式属性访问的 opaque 类型问题)"""
|
||||||
if block is None: return
|
if block is None: return
|
||||||
block.IsTerminated = val
|
block.IsTerminated = val
|
||||||
|
|
||||||
|
|
||||||
def block_get_terminated(block: BasicBlock | t.CPtr) -> t.CInt:
|
def block_get_terminated(block: rowptr[BasicBlock]) -> int:
|
||||||
"""获取块的终止标志(供跨模块调用,避免链式属性访问的 opaque 类型问题)"""
|
"""获取块的终止标志(供跨模块调用,避免链式属性访问的 opaque 类型问题)"""
|
||||||
if block is None:
|
if block is None:
|
||||||
return 1
|
return 1
|
||||||
return block.IsTerminated
|
return block.IsTerminated
|
||||||
|
|
||||||
|
|
||||||
def block_append_text(pool: memhub.MemBuddy | t.CPtr, block: BasicBlock | t.CPtr,
|
def block_append_text(pool: rowptr[memhub.MemBuddy], block: rowptr[BasicBlock],
|
||||||
text: t.CChar | t.CPtr):
|
text: str):
|
||||||
"""创建指令行并追加到基本块"""
|
"""创建指令行并追加到基本块"""
|
||||||
if block is None or text is None: return
|
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:
|
if line is not None:
|
||||||
block_append_line(block, line)
|
block_append_line(block, line)
|
||||||
|
|
||||||
|
|
||||||
def block_insert_text_before_terminator(pool: memhub.MemBuddy | t.CPtr,
|
def block_insert_text_before_terminator(pool: rowptr[memhub.MemBuddy],
|
||||||
block: BasicBlock | t.CPtr,
|
block: rowptr[BasicBlock],
|
||||||
text: t.CChar | t.CPtr):
|
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 is None or text is None: return
|
||||||
if block.Lines 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 line is None: return
|
||||||
# 块未终止:直接追加
|
# 块未终止:直接追加
|
||||||
if block.IsTerminated == 0:
|
if block.IsTerminated == 0:
|
||||||
block_append_line(block, line)
|
block_append_line(block, line)
|
||||||
return
|
return
|
||||||
# 块已终止:在 Tail(终止指令)之前插入
|
# 块已终止:在 Tail(终止指令)之前插入
|
||||||
lines: GSList[Line] | t.CPtr = block.Lines
|
lines: rowptr[GSList[Line]] = block.Lines
|
||||||
if lines.Head is None:
|
if lines.Head is None:
|
||||||
block_append_line(block, line)
|
block_append_line(block, line)
|
||||||
return
|
return
|
||||||
@@ -282,7 +286,7 @@ def block_insert_text_before_terminator(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
lines.Count += 1
|
lines.Count += 1
|
||||||
return
|
return
|
||||||
# 找到 Tail 的前驱节点
|
# 找到 Tail 的前驱节点
|
||||||
prev: Line | t.CPtr = lines.Head
|
prev: rowptr[Line] = lines.Head
|
||||||
while prev is not None and prev.Next is not lines.Tail:
|
while prev is not None and prev.Next is not lines.Tail:
|
||||||
prev = prev.Next
|
prev = prev.Next
|
||||||
if prev is None:
|
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")"""
|
"""设置函数级属性文本(如 "nounwind"/"noinline")"""
|
||||||
if func is None: return
|
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
|
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")"""
|
"""设置参数属性文本(如 "noundef"/"nocapture"/"readonly")"""
|
||||||
if param is None: return
|
if param is None: return
|
||||||
param.Attrs = attrs
|
param.Attrs = attrs
|
||||||
@@ -324,7 +339,7 @@ def param_set_attrs(param: Param | t.CPtr, attrs: t.CChar | t.CPtr):
|
|||||||
# SHA1 命名空间的函数名(如 "4dad2ba72ed7ba09.GSListNode[Param]")含 '['、']',
|
# SHA1 命名空间的函数名(如 "4dad2ba72ed7ba09.GSListNode[Param]")含 '['、']',
|
||||||
# 需要加引号;但纯 hex+点 的名字(如 "abc.def")不需要。
|
# 需要加引号;但纯 hex+点 的名字(如 "abc.def")不需要。
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def _ll_name_needs_quote(name: str) -> t.CInt:
|
def _ll_name_needs_quote(name: str) -> int:
|
||||||
"""检查 LLVM 标识符是否需要加引号(以数字开头或含非合法字符)
|
"""检查 LLVM 标识符是否需要加引号(以数字开头或含非合法字符)
|
||||||
|
|
||||||
LLVM IR 合法字符:a-z, A-Z, 0-9, -, $, ., _
|
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'
|
"""判断字符是否是 '0'-'9'
|
||||||
|
|
||||||
ch 是值类型 (t.CChar = i8),TPC 已修复值类型 is None 处理:
|
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*。
|
# 导致内存损坏。必须显式计算字节偏移:addr = base + idx * 4,再转型为 i32*。
|
||||||
# 参见 HandlesTranslator.py:358 的 t.CUInt64T(ptr) + offset * sizeof 用法。
|
# 参见 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)
|
"""读取 i32 数组 map_arr[idx](显式字节偏移 idx*4)
|
||||||
|
|
||||||
使用 (t.CInt | t.CPtr)(uint64) 强转将字节偏移转为 i32*,再用 c.Deref 解引用。
|
使用 (rowptr[int])(uint64) 强转将字节偏移转为 i32*,再用 c.Deref 解引用。
|
||||||
TPC 已修复类型联合强转(_HandleTypeUnionCastLlvm 添加 fallback),此写法可用。
|
TPC 已修复类型联合强转(_HandleTypeUnionCastLlvm 添加 fallback),此写法可用。
|
||||||
"""
|
"""
|
||||||
if map_arr is None:
|
if map_arr is None:
|
||||||
return -1
|
return -1
|
||||||
byte_off: t.CUInt64T = t.CUInt64T(map_arr) + idx * 4
|
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)
|
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)
|
"""写入 map_arr[idx] = val(i32 数组,显式字节偏移 idx*4)
|
||||||
|
|
||||||
使用 (t.CInt | t.CPtr)(uint64) 强转 + c.DerefAs 解引用赋值。
|
使用 (rowptr[int])(uint64) 强转 + c.DerefAs 解引用赋值。
|
||||||
TPC 已修复类型联合强转,此写法可用。
|
TPC 已修复类型联合强转,此写法可用。
|
||||||
"""
|
"""
|
||||||
if map_arr is None:
|
if map_arr is None:
|
||||||
return
|
return
|
||||||
byte_off: t.CUInt64T = t.CUInt64T(map_arr) + idx * 4
|
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)
|
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 比较返回更大值
|
"""扫描文本,找出 %N(N 为数字)中最大的 N,与 cur_max 比较返回更大值
|
||||||
|
|
||||||
仅匹配 '%' 后紧跟数字的情况,跳过命名 SSA 名(%entry 等)。
|
仅匹配 '%' 后紧跟数字的情况,跳过命名 SSA 名(%entry 等)。
|
||||||
"""
|
"""
|
||||||
result: t.CInt = cur_max
|
result: int = cur_max
|
||||||
p: t.CChar | t.CPtr = text
|
p: str = text
|
||||||
while p is not None and p[0] != '\0':
|
while p is not None and p[0] != '\0':
|
||||||
if p[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:
|
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:
|
if num > result:
|
||||||
result = num
|
result = num
|
||||||
p = p + 1
|
p = p + 1
|
||||||
return result
|
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"""
|
"""遍历所有 BB 指令行,找出最大的 %N 数字;无数字 SSA 名返回 -1"""
|
||||||
max_n: t.CInt = -1
|
max_n: int = -1
|
||||||
if func is None or func.Blocks is None:
|
if func is None or func.Blocks is None:
|
||||||
return max_n
|
return max_n
|
||||||
blk: BasicBlock | t.CPtr = func.Blocks.Head
|
blk: rowptr[BasicBlock] = func.Blocks.Head
|
||||||
blk_steps: t.CSizeT = 0
|
blk_steps: t.CSizeT = 0
|
||||||
while blk is not None:
|
while blk is not None:
|
||||||
blk_steps += 1
|
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)
|
stdio.printf("[IR-DUMP] 链表成环: func blocks(函数名=%s,ssa 扫描终止)\n", func.Name)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
if blk.Lines is not None:
|
if blk.Lines is not None:
|
||||||
line: Line | t.CPtr = blk.Lines.Head
|
line: rowptr[Line] = blk.Lines.Head
|
||||||
line_steps: t.CSizeT = 0
|
line_steps: t.CSizeT = 0
|
||||||
while line is not None:
|
while line is not None:
|
||||||
line_steps += 1
|
line_steps += 1
|
||||||
@@ -465,20 +480,20 @@ def _find_max_ssa_number(func: Function | t.CPtr) -> t.CInt:
|
|||||||
return max_n
|
return max_n
|
||||||
|
|
||||||
|
|
||||||
def _assign_new_numbers(text: t.CChar | t.CPtr,
|
def _assign_new_numbers(text: str,
|
||||||
map_arr: t.CChar | t.CPtr,
|
map_arr: str,
|
||||||
max_n: t.CInt, next_new: t.CInt) -> t.CInt:
|
max_n: int, next_new: int) -> int:
|
||||||
"""扫描文本,对每个 %N(数字),若 map_arr[N]==-1 则分配 next_new
|
"""扫描文本,对每个 %N(数字),若 map_arr[N]==-1 则分配 next_new
|
||||||
|
|
||||||
返回更新后的 next_new。按文本首次出现顺序建立映射。
|
返回更新后的 next_new。按文本首次出现顺序建立映射。
|
||||||
"""
|
"""
|
||||||
result: t.CInt = next_new
|
result: int = next_new
|
||||||
p: t.CChar | t.CPtr = text
|
p: str = text
|
||||||
while p is not None and p[0] != '\0':
|
while p is not None and p[0] != '\0':
|
||||||
if p[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:
|
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 num >= 0 and num <= max_n:
|
||||||
if _map_get_i32(map_arr, num) == -1:
|
if _map_get_i32(map_arr, num) == -1:
|
||||||
_map_set_i32(map_arr, num, result)
|
_map_set_i32(map_arr, num, result)
|
||||||
@@ -487,10 +502,10 @@ def _assign_new_numbers(text: t.CChar | t.CPtr,
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _replace_ssa_numbers(text: t.CChar | t.CPtr,
|
def _replace_ssa_numbers(text: str,
|
||||||
pool: memhub.MemBuddy | t.CPtr,
|
pool: rowptr[memhub.MemBuddy],
|
||||||
map_arr: t.CChar | t.CPtr,
|
map_arr: str,
|
||||||
max_n: t.CInt) -> t.CChar | t.CPtr:
|
max_n: int) -> str:
|
||||||
"""构建新文本,将 %N 替换为映射后的新编号
|
"""构建新文本,将 %N 替换为映射后的新编号
|
||||||
|
|
||||||
逐字符扫描:遇到 %N(数字)查映射表替换,其他字符原样复制。
|
逐字符扫描:遇到 %N(数字)查映射表替换,其他字符原样复制。
|
||||||
@@ -499,29 +514,29 @@ def _replace_ssa_numbers(text: t.CChar | t.CPtr,
|
|||||||
src_len: t.CSizeT = string.strlen(text)
|
src_len: t.CSizeT = string.strlen(text)
|
||||||
# 新缓冲区:最坏情况每个数字变长(位数增加),分配 src_len*2 + 64
|
# 新缓冲区:最坏情况每个数字变长(位数增加),分配 src_len*2 + 64
|
||||||
new_size: t.CSizeT = 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:
|
if new_buf is None:
|
||||||
return None
|
return None
|
||||||
# 一次性分配数字缓冲区(循环中复用)
|
# 一次性分配数字缓冲区(循环中复用)
|
||||||
num_buf: t.CChar | t.CPtr = pool.alloc(16)
|
num_buf: str = pool.alloc(16)
|
||||||
if num_buf is None:
|
if num_buf is None:
|
||||||
new_buf[0] = '\0'
|
new_buf[0] = '\0'
|
||||||
return new_buf
|
return new_buf
|
||||||
|
|
||||||
dst_idx: t.CSizeT = 0
|
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':
|
while src_p is not None and src_p[0] != '\0':
|
||||||
if dst_idx + 16 >= new_size:
|
if dst_idx + 16 >= new_size:
|
||||||
# 缓冲区不足,截断
|
# 缓冲区不足,截断
|
||||||
break
|
break
|
||||||
if src_p[0] == '%':
|
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:
|
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 只有
|
# 先做范围检查再读 map_arr:num 超 max_n 时 map_arr 只有
|
||||||
# (max_n+1)*4 字节,先读后查会越界读远端内存
|
# (max_n+1)*4 字节,先读后查会越界读远端内存
|
||||||
if num >= 0 and num <= max_n:
|
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:
|
if new_num != -1:
|
||||||
# 写入 '%'
|
# 写入 '%'
|
||||||
new_buf[dst_idx] = '%'
|
new_buf[dst_idx] = '%'
|
||||||
@@ -548,7 +563,7 @@ def _replace_ssa_numbers(text: t.CChar | t.CPtr,
|
|||||||
return new_buf
|
return new_buf
|
||||||
|
|
||||||
|
|
||||||
def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
def RenumberSSA(func: rowptr[Function], pool: rowptr[memhub.MemBuddy]):
|
||||||
"""重编号函数内所有数字 SSA 名,确保按文本输出顺序单调递增
|
"""重编号函数内所有数字 SSA 名,确保按文本输出顺序单调递增
|
||||||
|
|
||||||
在 FunctionPrint 序列化函数体之前调用。
|
在 FunctionPrint 序列化函数体之前调用。
|
||||||
@@ -562,7 +577,7 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# 1. 第一遍扫描:找出最大 SSA 编号
|
# 1. 第一遍扫描:找出最大 SSA 编号
|
||||||
max_n: t.CInt = _find_max_ssa_number(func)
|
max_n: int = _find_max_ssa_number(func)
|
||||||
if max_n < 0:
|
if max_n < 0:
|
||||||
return # 无数字 SSA 名
|
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 访问。
|
# 用 i8* 存储(pool.alloc 返回 i8*),通过 _map_get_i32/_map_set_i32 访问。
|
||||||
# 初始化为 -1:每个 i32 元素 4 字节,0xFFFFFFFF = -1(有符号 i32)。
|
# 初始化为 -1:每个 i32 元素 4 字节,0xFFFFFFFF = -1(有符号 i32)。
|
||||||
# 用 memset 一次性填充,避免循环内 ptr[i] 指针索引问题。
|
# 用 memset 一次性填充,避免循环内 ptr[i] 指针索引问题。
|
||||||
map_bytes: t.CSizeT = (max_n + 1) * 4 # t.CInt = 4 字节
|
map_bytes: t.CSizeT = (max_n + 1) * 4 # int = 4 字节
|
||||||
map_arr: t.CChar | t.CPtr = pool.alloc(map_bytes)
|
map_arr: str = pool.alloc(map_bytes)
|
||||||
if map_arr is None:
|
if map_arr is None:
|
||||||
return
|
return
|
||||||
string.memset(map_arr, 0xFF, map_bytes) # 0xFF * 4 = 0xFFFFFFFF = -1
|
string.memset(map_arr, 0xFF, map_bytes) # 0xFF * 4 = 0xFFFFFFFF = -1
|
||||||
|
|
||||||
# 3. 第二遍扫描:按文本顺序分配新编号
|
# 3. 第二遍扫描:按文本顺序分配新编号
|
||||||
next_new: t.CInt = 0
|
next_new: int = 0
|
||||||
blk: BasicBlock | t.CPtr = func.Blocks.Head
|
blk: rowptr[BasicBlock] = func.Blocks.Head
|
||||||
blk_steps: t.CSizeT = 0
|
blk_steps: t.CSizeT = 0
|
||||||
while blk is not None:
|
while blk is not None:
|
||||||
blk_steps += 1
|
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)
|
stdio.printf("[IR-DUMP] 链表成环: func blocks(函数名=%s,ssa 重编号终止)\n", func.Name)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
if blk.Lines is not None:
|
if blk.Lines is not None:
|
||||||
line: Line | t.CPtr = blk.Lines.Head
|
line: rowptr[Line] = blk.Lines.Head
|
||||||
line_steps: t.CSizeT = 0
|
line_steps: t.CSizeT = 0
|
||||||
while line is not None:
|
while line is not None:
|
||||||
line_steps += 1
|
line_steps += 1
|
||||||
@@ -600,10 +615,10 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
|||||||
blk = blk.Next
|
blk = blk.Next
|
||||||
|
|
||||||
# 4. 检查是否有需要重编号的(old != new)
|
# 4. 检查是否有需要重编号的(old != new)
|
||||||
need_renumber: t.CInt = 0
|
need_renumber: int = 0
|
||||||
i: t.CInt = 0
|
i: int = 0
|
||||||
while i <= max_n:
|
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:
|
if v != -1 and v != i:
|
||||||
need_renumber = 1
|
need_renumber = 1
|
||||||
break
|
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)
|
stdio.printf("[IR-DUMP] 链表成环: func blocks(函数名=%s,ssa 替换终止)\n", func.Name)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
if blk.Lines is not None:
|
if blk.Lines is not None:
|
||||||
line: Line | t.CPtr = blk.Lines.Head
|
line: rowptr[Line] = blk.Lines.Head
|
||||||
line_steps = 0
|
line_steps = 0
|
||||||
while line is not None:
|
while line is not None:
|
||||||
line_steps += 1
|
line_steps += 1
|
||||||
@@ -629,7 +644,7 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
|||||||
func.Name, blk.Name)
|
func.Name, blk.Name)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
if line.Buf is not None:
|
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)
|
line.Buf, pool, map_arr, max_n)
|
||||||
if new_buf is not None:
|
if new_buf is not None:
|
||||||
line.Buf = new_buf
|
line.Buf = new_buf
|
||||||
@@ -650,8 +665,8 @@ def RenumberSSA(func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
|||||||
# <instruction>
|
# <instruction>
|
||||||
# }
|
# }
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def FunctionPrint(buf: str, size: t.CSizeT,
|
||||||
func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
func: rowptr[Function], pool: rowptr[memhub.MemBuddy]):
|
||||||
"""将函数 func 序列化为 IR 文本写入 buf"""
|
"""将函数 func 序列化为 IR 文本写入 buf"""
|
||||||
if func is None or buf is None or size == 0: return
|
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 内部会跳过 declare 函数(IsDeclared==1),无需在此判断。
|
||||||
RenumberSSA(func, pool)
|
RenumberSSA(func, pool)
|
||||||
|
|
||||||
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
|
ty_buf: str = pool.alloc(128)
|
||||||
if ty_buf is None: return
|
if ty_buf is None: return
|
||||||
ty_buf[0] = '\0'
|
ty_buf[0] = '\0'
|
||||||
|
|
||||||
@@ -690,10 +705,10 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
_append_cstr(buf, size, "(")
|
_append_cstr(buf, size, "(")
|
||||||
|
|
||||||
# 参数列表(从 GSList[Param].Head 遍历)
|
# 参数列表(从 GSList[Param].Head 遍历)
|
||||||
cur: Param | t.CPtr = None
|
cur: rowptr[Param] = None
|
||||||
if func.Params is not None:
|
if func.Params is not None:
|
||||||
cur = func.Params.Head
|
cur = func.Params.Head
|
||||||
first: t.CInt = 1
|
first: int = 1
|
||||||
cur_steps: t.CSizeT = 0
|
cur_steps: t.CSizeT = 0
|
||||||
while cur is not None:
|
while cur is not None:
|
||||||
cur_steps += 1
|
cur_steps += 1
|
||||||
@@ -735,15 +750,23 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
if func.Attrs is not None:
|
if func.Attrs is not None:
|
||||||
_append_cstr(buf, size, " ")
|
_append_cstr(buf, size, " ")
|
||||||
_append_cstr(buf, size, func.Attrs)
|
_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:
|
if func.IsDeclared == 1:
|
||||||
_append_cstr(buf, size, "\n")
|
_append_cstr(buf, size, "\n")
|
||||||
|
_append_attr_group_def(buf, size, pool, func)
|
||||||
return
|
return
|
||||||
|
|
||||||
# 函数体
|
# 函数体
|
||||||
_append_cstr(buf, size, " {\n")
|
_append_cstr(buf, size, " {\n")
|
||||||
|
|
||||||
blk: BasicBlock | t.CPtr = None
|
blk: rowptr[BasicBlock] = None
|
||||||
if func.Blocks is not None:
|
if func.Blocks is not None:
|
||||||
blk = func.Blocks.Head
|
blk = func.Blocks.Head
|
||||||
blk_steps: t.CSizeT = 0
|
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, blk.Name)
|
||||||
_append_cstr(buf, size, ":\n")
|
_append_cstr(buf, size, ":\n")
|
||||||
# 指令行(从 GSList[Line].Head 遍历)
|
# 指令行(从 GSList[Line].Head 遍历)
|
||||||
line: Line | t.CPtr = None
|
line: rowptr[Line] = None
|
||||||
if blk.Lines is not None:
|
if blk.Lines is not None:
|
||||||
line = blk.Lines.Head
|
line = blk.Lines.Head
|
||||||
has_lines: t.CInt = 0
|
has_lines: int = 0
|
||||||
line_steps: t.CSizeT = 0
|
line_steps: t.CSizeT = 0
|
||||||
while line is not None:
|
while line is not None:
|
||||||
line_steps += 1
|
line_steps += 1
|
||||||
@@ -785,6 +808,21 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
blk = blk.Next
|
blk = blk.Next
|
||||||
|
|
||||||
_append_cstr(buf, size, "}\n")
|
_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_dst: t.CUInt64T = 0
|
||||||
_g_last_pos: t.CSizeT = 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 末尾"""
|
"""将 C 字符串 src 追加到 dst 末尾"""
|
||||||
global _g_last_dst, _g_last_pos
|
global _g_last_dst, _g_last_pos
|
||||||
if dst is None or src is None: return
|
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 限制。
|
# 所有字段。其他模块通过函数调用获取字段值,绕过 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:
|
if func is None:
|
||||||
return None
|
return None
|
||||||
return func.Name
|
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:
|
if func is None:
|
||||||
return None
|
return None
|
||||||
return func.RetTy
|
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:
|
if func is None:
|
||||||
return None
|
return None
|
||||||
return func.Params
|
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)"""
|
"""获取函数参数链表头节点(一步到位,避免调用方访问 GSList.Head)"""
|
||||||
if func is None:
|
if func is None:
|
||||||
return None
|
return None
|
||||||
@@ -864,35 +902,35 @@ def function_get_param_head(func: Function | t.CPtr) -> Param | t.CPtr:
|
|||||||
return func.Params.Head
|
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:
|
if func is None:
|
||||||
return None
|
return None
|
||||||
return func.Next
|
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 定义)"""
|
"""获取函数是否为声明(1=declare 仅声明, 0=define 定义)"""
|
||||||
if func is None:
|
if func is None:
|
||||||
return 0
|
return 0
|
||||||
return func.IsDeclared
|
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:
|
if param is None:
|
||||||
return None
|
return None
|
||||||
return param.Name
|
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:
|
if param is None:
|
||||||
return None
|
return None
|
||||||
return param.Ty
|
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:
|
if param is None:
|
||||||
return None
|
return None
|
||||||
|
|||||||
+88
-86
@@ -25,6 +25,7 @@ from .__function import (
|
|||||||
function_add_param, function_add_block,
|
function_add_param, function_add_block,
|
||||||
block_append_line, block_append_text,
|
block_append_line, block_append_text,
|
||||||
function_set_attrs, param_set_attrs,
|
function_set_attrs, param_set_attrs,
|
||||||
|
function_set_attr_group,
|
||||||
function_get_name, function_get_ret_ty, function_get_params,
|
function_get_name, function_get_ret_ty, function_get_params,
|
||||||
function_get_param_head, function_get_next, function_is_declared,
|
function_get_param_head, function_get_next, function_is_declared,
|
||||||
param_get_name, param_get_ty, param_get_next,
|
param_get_name, param_get_ty, param_get_next,
|
||||||
@@ -33,6 +34,7 @@ from .__function import (
|
|||||||
from .__module import (
|
from .__module import (
|
||||||
LLVMModule, GlobalVariable, NamedTypeNode, new_module, new_global_variable,
|
LLVMModule, GlobalVariable, NamedTypeNode, new_module, new_global_variable,
|
||||||
module_add_function, module_add_global, module_add_named_type,
|
module_add_function, module_add_global, module_add_named_type,
|
||||||
|
module_set_named_type_packed,
|
||||||
module_set_target, module_set_datalayout,
|
module_set_target, module_set_datalayout,
|
||||||
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
|
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
|
||||||
LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT,
|
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 字符串"""
|
"""从 pool 分配并复制一个 C 字符串"""
|
||||||
if src is None: return None
|
if src is None: return None
|
||||||
slen: t.CSizeT = string.strlen(src)
|
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
|
if buf is None: return None
|
||||||
string.strcpy(buf, src)
|
string.strcpy(buf, src)
|
||||||
return buf
|
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,
|
def create_block(pool: rowptr[memhub.MemBuddy], func: rowptr[Function],
|
||||||
name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
|
name: str) -> rowptr[BasicBlock]:
|
||||||
"""创建基本块并添加到函数"""
|
"""创建基本块并添加到函数"""
|
||||||
# 块名与函数参数值名冲突防护:LLVM 中块标签 "entry:" 即值 %entry,
|
# 块名与函数参数值名冲突防护:LLVM 中块标签 "entry:" 即值 %entry,
|
||||||
# 与参数 %entry 重名 → llc "unable to create block named 'entry'"
|
# 与参数 %entry 重名 → llc "unable to create block named 'entry'"
|
||||||
# (CallGenCall._field_byte_offset(self, pool, entry, ...) 根因)。
|
# (CallGenCall._field_byte_offset(self, pool, entry, ...) 根因)。
|
||||||
# 冲突时追加 .1/.2/... 后缀去重(Param.Name 可能带 % 前缀,剥离比较)。
|
# 冲突时追加 .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 \
|
if func is not None and func.Params is not None and name is not None \
|
||||||
and name[0] != '\0':
|
and name[0] != '\0':
|
||||||
cb_len: t.CSizeT = string.strlen(name) + 16
|
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
|
cb_collide: int = 1
|
||||||
while cb_collide != 0:
|
while cb_collide != 0:
|
||||||
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:
|
while cb_p is not None:
|
||||||
cb_pnm: str = param_get_name(cb_p)
|
cb_pnm: str = param_get_name(cb_p)
|
||||||
if cb_pnm is not None:
|
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)
|
viperlib.snprintf(cb_buf, cb_len, "%s.%d", name, cb_k)
|
||||||
use_name = cb_buf
|
use_name = cb_buf
|
||||||
cb_k += 1
|
cb_k += 1
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(pool, use_name)
|
name_dup: str = _str_dup(pool, use_name)
|
||||||
blk: BasicBlock | t.CPtr = new_basic_block(pool, name_dup)
|
blk: rowptr[BasicBlock] = new_basic_block(pool, name_dup)
|
||||||
if blk is not None:
|
if blk is not None:
|
||||||
function_add_block(func, blk)
|
function_add_block(func, blk)
|
||||||
return 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,
|
def const_int(pool: rowptr[memhub.MemBuddy], bits: int,
|
||||||
val: t.CInt64T) -> Value | t.CPtr:
|
val: int64) -> rowptr[Value]:
|
||||||
"""创建整数常量值(自动创建类型 + 名字文本)
|
"""创建整数常量值(自动创建类型 + 名字文本)
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@@ -141,13 +143,13 @@ def const_int(pool: memhub.MemBuddy | t.CPtr, bits: t.CInt,
|
|||||||
val: 整数值
|
val: 整数值
|
||||||
"""
|
"""
|
||||||
# 创建类型
|
# 创建类型
|
||||||
ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
|
ty: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
|
||||||
if ty is None: return None
|
if ty is None: return None
|
||||||
string.memset(ty, 0, LLVMType.__sizeof__())
|
string.memset(ty, 0, LLVMType.__sizeof__())
|
||||||
c.DerefAs(ty, LLVMType.Int(bits))
|
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
|
if name is None: return None
|
||||||
# LLVM i64 字面量范围不含 INT64_MIN(-9223372036854775808):该值必须
|
# LLVM i64 字面量范围不含 INT64_MIN(-9223372036854775808):该值必须
|
||||||
# 用无符号位模式 9223372036854775808 表示(LLVM 接受),否则 opt 解析
|
# 用无符号位模式 9223372036854775808 表示(LLVM 接受),否则 opt 解析
|
||||||
@@ -161,12 +163,12 @@ def const_int(pool: memhub.MemBuddy | t.CPtr, bits: t.CInt,
|
|||||||
return ConstInt(pool, ty, val, name)
|
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 整数常量"""
|
"""便捷: 创建 i32 整数常量"""
|
||||||
return const_int(pool, 32, val)
|
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 整数常量"""
|
"""便捷: 创建 i64 整数常量"""
|
||||||
return const_int(pool, 64, val)
|
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,
|
def create_function(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
|
||||||
name: t.CChar | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
|
name: str, ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
|
||||||
"""创建函数并添加到模块"""
|
"""创建函数并添加到模块"""
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
|
name_dup: str = _str_dup(pool, name)
|
||||||
func: Function | t.CPtr = new_function(pool, name_dup, ret_ty)
|
func: rowptr[Function] = new_function(pool, name_dup, ret_ty)
|
||||||
if func is not None:
|
if func is not None:
|
||||||
module_add_function(mod, func)
|
module_add_function(mod, func)
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
def add_param(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
|
def add_param(pool: rowptr[memhub.MemBuddy], func: rowptr[Function],
|
||||||
ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Param | t.CPtr:
|
ty: rowptr[LLVMType], name: str) -> rowptr[Param]:
|
||||||
"""创建参数并添加到函数"""
|
"""创建参数并添加到函数"""
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
|
name_dup: str = _str_dup(pool, name)
|
||||||
param: Param | t.CPtr = new_param(pool, ty, name_dup)
|
param: rowptr[Param] = new_param(pool, ty, name_dup)
|
||||||
if param is not None:
|
if param is not None:
|
||||||
function_add_param(func, param)
|
function_add_param(func, param)
|
||||||
return param
|
return param
|
||||||
@@ -197,15 +199,15 @@ def add_param(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
# 便捷工厂: 创建函数声明(declare)
|
# 便捷工厂: 创建函数声明(declare)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def create_declare(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
|
def create_declare(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
|
||||||
name: t.CChar | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
|
name: str, ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
|
||||||
"""创建函数声明(declare,无函数体)并添加到模块
|
"""创建函数声明(declare,无函数体)并添加到模块
|
||||||
|
|
||||||
与 create_function 不同,声明不生成函数体,仅生成:
|
与 create_function 不同,声明不生成函数体,仅生成:
|
||||||
declare <ret_ty> @<name>(<params>)
|
declare <ret_ty> @<name>(<params>)
|
||||||
"""
|
"""
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
|
name_dup: str = _str_dup(pool, name)
|
||||||
func: Function | t.CPtr = new_function(pool, name_dup, ret_ty)
|
func: rowptr[Function] = new_function(pool, name_dup, ret_ty)
|
||||||
if func is not None:
|
if func is not None:
|
||||||
func.IsDeclared = 1
|
func.IsDeclared = 1
|
||||||
module_add_function(mod, func)
|
module_add_function(mod, func)
|
||||||
@@ -218,8 +220,8 @@ def create_declare(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
|
|||||||
# 生成 LLVM IR:
|
# 生成 LLVM IR:
|
||||||
# @.str = private unnamed_addr constant [N x i8] c"contents\00"
|
# @.str = private unnamed_addr constant [N x i8] c"contents\00"
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
|
def create_global_string(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
|
||||||
name: t.CChar | t.CPtr, text: t.CChar | t.CPtr) -> GlobalVariable | t.CPtr:
|
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
|
if text is None: return None
|
||||||
slen: t.CSizeT = string.strlen(text)
|
slen: t.CSizeT = string.strlen(text)
|
||||||
count: t.CInt = slen + 1 # 含末尾 NUL
|
count: int = slen + 1 # 含末尾 NUL
|
||||||
|
|
||||||
# 创建 i8 类型
|
# 创建 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
|
if i8_ty is None: return None
|
||||||
string.memset(i8_ty, 0, LLVMType.__sizeof__())
|
string.memset(i8_ty, 0, LLVMType.__sizeof__())
|
||||||
c.DerefAs(i8_ty, LLVMType.Int(8))
|
c.DerefAs(i8_ty, LLVMType.Int(8))
|
||||||
|
|
||||||
# 创建 [count x i8] 数组类型
|
# 创建 [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
|
if arr_ty is None: return None
|
||||||
string.memset(arr_ty, 0, LLVMType.__sizeof__())
|
string.memset(arr_ty, 0, LLVMType.__sizeof__())
|
||||||
c.DerefAs(arr_ty, LLVMType.Array(i8_ty, count))
|
c.DerefAs(arr_ty, LLVMType.Array(i8_ty, count))
|
||||||
|
|
||||||
# 创建全局变量
|
# 创建全局变量
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
|
name_dup: str = _str_dup(pool, name)
|
||||||
gv: GlobalVariable | t.CPtr = new_global_variable(pool, name_dup, arr_ty)
|
gv: rowptr[GlobalVariable] = new_global_variable(pool, name_dup, arr_ty)
|
||||||
if gv is None: return None
|
if gv is None: return None
|
||||||
|
|
||||||
# 设置属性: private + unnamed_addr + constant
|
# 设置属性: private + unnamed_addr + constant
|
||||||
@@ -257,7 +259,7 @@ def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPt
|
|||||||
# 构造初始化值文本: c"contents\00"
|
# 构造初始化值文本: c"contents\00"
|
||||||
# LLVM IR 字符串字面量格式: c"<chars>" 其中 " 和 \ 及非打印字符用 \xx 转义
|
# LLVM IR 字符串字面量格式: c"<chars>" 其中 " 和 \ 及非打印字符用 \xx 转义
|
||||||
# 缓冲区大小: 最坏情况每个字符4字节(\xx)+ c"..." + \00 + "
|
# 缓冲区大小: 最坏情况每个字符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
|
if init_buf is None: return None
|
||||||
pos: t.CSizeT = 0
|
pos: t.CSizeT = 0
|
||||||
init_buf[pos] = 'c'
|
init_buf[pos] = 'c'
|
||||||
@@ -271,8 +273,8 @@ def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPt
|
|||||||
# 需要转义: " → \22, \ → \5c, 非打印字符 → \xx
|
# 需要转义: " → \22, \ → \5c, 非打印字符 → \xx
|
||||||
init_buf[pos] = '\\'
|
init_buf[pos] = '\\'
|
||||||
pos += 1
|
pos += 1
|
||||||
hi: t.CInt = (ch >> 4) & 0x0F
|
hi: int = (ch >> 4) & 0x0F
|
||||||
lo: t.CInt = ch & 0x0F
|
lo: int = ch & 0x0F
|
||||||
if hi < 10:
|
if hi < 10:
|
||||||
init_buf[pos] = 0x30 + hi
|
init_buf[pos] = 0x30 + hi
|
||||||
else:
|
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,
|
def create_global_int(pool: rowptr[memhub.MemBuddy], mod: rowptr[LLVMModule],
|
||||||
name: t.CChar | t.CPtr, bits: t.CInt, val: t.CInt64T) -> GlobalVariable | t.CPtr:
|
name: str, bits: int, val: int64) -> rowptr[GlobalVariable]:
|
||||||
"""创建整数全局变量并添加到模块
|
"""创建整数全局变量并添加到模块
|
||||||
|
|
||||||
生成 LLVM IR:
|
生成 LLVM IR:
|
||||||
@<name> = global i<bits> <val>
|
@<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
|
if ty is None: return None
|
||||||
string.memset(ty, 0, LLVMType.__sizeof__())
|
string.memset(ty, 0, LLVMType.__sizeof__())
|
||||||
c.DerefAs(ty, LLVMType.Int(bits))
|
c.DerefAs(ty, LLVMType.Int(bits))
|
||||||
|
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
|
name_dup: str = _str_dup(pool, name)
|
||||||
gv: GlobalVariable | t.CPtr = new_global_variable(pool, name_dup, ty)
|
gv: rowptr[GlobalVariable] = new_global_variable(pool, name_dup, ty)
|
||||||
if gv is None: return None
|
if gv is None: return None
|
||||||
|
|
||||||
# 构造初始化值文本: "42" (类型由 _print_global 单独打印)
|
# 构造初始化值文本: "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
|
if init_buf is None: return None
|
||||||
viperlib.snprintf(init_buf, 48, "%lld", val)
|
viperlib.snprintf(init_buf, 48, "%lld", val)
|
||||||
gv.Initializer = init_buf
|
gv.Initializer = init_buf
|
||||||
@@ -337,123 +339,123 @@ def create_global_int(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
|
|||||||
# LLVMModuleCore: 模块/函数/值创建核心,封装 pool 避免重复传参
|
# LLVMModuleCore: 模块/函数/值创建核心,封装 pool 避免重复传参
|
||||||
#
|
#
|
||||||
# 用法:
|
# 用法:
|
||||||
# mcore: LLVMModuleCore | t.CPtr = LLVMModuleCore(pool)
|
# mcore: rowptr[LLVMModuleCore] = LLVMModuleCore(pool)
|
||||||
# mod: LLVMModule | t.CPtr = mcore.NewModule("test")
|
# mod: rowptr[LLVMModule] = mcore.NewModule("test")
|
||||||
# func: Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
|
# func: rowptr[Function] = mcore.CreateFunction(mod, "add", ty_i32)
|
||||||
# val: Value | t.CPtr = mcore.ConstInt32(42)
|
# val: rowptr[Value] = mcore.ConstInt32(42)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class LLVMModuleCore:
|
class LLVMModuleCore:
|
||||||
"""模块/函数/值创建核心,封装 pool 避免每次创建都传 pool"""
|
"""模块/函数/值创建核心,封装 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
|
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)
|
return new_module(self.Pool, name)
|
||||||
|
|
||||||
def CreateFunction(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
|
def CreateFunction(self, mod: rowptr[LLVMModule], name: str,
|
||||||
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
|
ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
|
||||||
return create_function(self.Pool, mod, name, ret_ty)
|
return create_function(self.Pool, mod, name, ret_ty)
|
||||||
|
|
||||||
def CreateDeclare(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
|
def CreateDeclare(self, mod: rowptr[LLVMModule], name: str,
|
||||||
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
|
ret_ty: rowptr[LLVMType]) -> rowptr[Function]:
|
||||||
"""创建函数声明(declare,无函数体)"""
|
"""创建函数声明(declare,无函数体)"""
|
||||||
return create_declare(self.Pool, mod, name, ret_ty)
|
return create_declare(self.Pool, mod, name, ret_ty)
|
||||||
|
|
||||||
def AddParam(self, func: Function | t.CPtr, ty: LLVMType | t.CPtr,
|
def AddParam(self, func: rowptr[Function], ty: rowptr[LLVMType],
|
||||||
name: t.CChar | t.CPtr) -> Param | t.CPtr:
|
name: str) -> rowptr[Param]:
|
||||||
return add_param(self.Pool, func, ty, name)
|
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)
|
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)
|
param_set_attrs(param, attrs)
|
||||||
|
|
||||||
def CreateBlock(self, func: Function | t.CPtr,
|
def CreateBlock(self, func: rowptr[Function],
|
||||||
name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
|
name: str) -> rowptr[BasicBlock]:
|
||||||
return create_block(self.Pool, func, name)
|
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)
|
return new_builder(self.Pool, func)
|
||||||
|
|
||||||
# ---- 全局变量 ----
|
# ---- 全局变量 ----
|
||||||
def NewGlobal(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
|
def NewGlobal(self, mod: rowptr[LLVMModule], name: str,
|
||||||
ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
|
ty: rowptr[LLVMType]) -> rowptr[GlobalVariable]:
|
||||||
"""创建全局变量并添加到模块"""
|
"""创建全局变量并添加到模块"""
|
||||||
name_dup: t.CChar | t.CPtr = _str_dup(self.Pool, name)
|
name_dup: str = _str_dup(self.Pool, name)
|
||||||
gv: GlobalVariable | t.CPtr = new_global_variable(self.Pool, name_dup, ty)
|
gv: rowptr[GlobalVariable] = new_global_variable(self.Pool, name_dup, ty)
|
||||||
if gv is not None:
|
if gv is not None:
|
||||||
module_add_global(mod, gv)
|
module_add_global(mod, gv)
|
||||||
return gv
|
return gv
|
||||||
|
|
||||||
def CreateGlobalString(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
|
def CreateGlobalString(self, mod: rowptr[LLVMModule], name: str,
|
||||||
text: t.CChar | t.CPtr) -> GlobalVariable | t.CPtr:
|
text: str) -> rowptr[GlobalVariable]:
|
||||||
"""创建字符串常量全局变量"""
|
"""创建字符串常量全局变量"""
|
||||||
return create_global_string(self.Pool, mod, name, text)
|
return create_global_string(self.Pool, mod, name, text)
|
||||||
|
|
||||||
def CreateGlobalInt(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
|
def CreateGlobalInt(self, mod: rowptr[LLVMModule], name: str,
|
||||||
bits: t.CInt, val: t.CInt64T) -> GlobalVariable | t.CPtr:
|
bits: int, val: int64) -> rowptr[GlobalVariable]:
|
||||||
"""创建带初始化值的整数全局变量"""
|
"""创建带初始化值的整数全局变量"""
|
||||||
return create_global_int(self.Pool, mod, name, bits, val)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
LLVMModulePrint(buf, size, mod, self.Pool, OUTPUT_FULL)
|
||||||
|
|
||||||
# ---- SSA 验证 ----
|
# ---- SSA 验证 ----
|
||||||
def NewVerifyResult(self, buf_size: t.CSizeT) -> VerifyResult | t.CPtr:
|
def NewVerifyResult(self, buf_size: t.CSizeT) -> rowptr[VerifyResult]:
|
||||||
"""创建验证结果对象(buf_size 为错误消息缓冲区大小)"""
|
"""创建验证结果对象(buf_size 为错误消息缓冲区大小)"""
|
||||||
return _new_verify_result(self.Pool, buf_size)
|
return _new_verify_result(self.Pool, buf_size)
|
||||||
|
|
||||||
def VerifyFunction(self, func: Function | t.CPtr,
|
def VerifyFunction(self, func: rowptr[Function],
|
||||||
result: VerifyResult | t.CPtr) -> t.CInt:
|
result: rowptr[VerifyResult]) -> int:
|
||||||
"""验证单个函数的 SSA 正确性,返回错误数(0=通过)"""
|
"""验证单个函数的 SSA 正确性,返回错误数(0=通过)"""
|
||||||
return verify_function(self.Pool, func, result)
|
return verify_function(self.Pool, func, result)
|
||||||
|
|
||||||
def VerifyModule(self, mod: LLVMModule | t.CPtr,
|
def VerifyModule(self, mod: rowptr[LLVMModule],
|
||||||
result: VerifyResult | t.CPtr) -> t.CInt:
|
result: rowptr[VerifyResult]) -> int:
|
||||||
"""验证模块中所有函数的 SSA 正确性,返回错误数(0=通过)"""
|
"""验证模块中所有函数的 SSA 正确性,返回错误数(0=通过)"""
|
||||||
return verify_module(self.Pool, mod, result)
|
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
|
@t.NoVTable
|
||||||
class GlobalVariable(GSListNode[GlobalVariable]):
|
class GlobalVariable(GSListNode[GlobalVariable]):
|
||||||
Name: t.CChar | t.CPtr # 全局变量名(如 ".str" / "my_global")
|
Name: str # 全局变量名(如 ".str" / "my_global")
|
||||||
Ty: LLVMType | t.CPtr # 变量类型
|
Ty: rowptr[LLVMType] # 变量类型
|
||||||
Initializer: t.CVoid | t.CPtr # 初始化值 Value*(None = 无初始化)
|
Initializer: rowptr[t.CVoid] # 初始化值 Value*(None = 无初始化)
|
||||||
IsConstant: t.CInt # 1=constant, 0=variable
|
IsConstant: int # 1=constant, 0=variable
|
||||||
Linkage: t.CChar | t.CPtr # 链接类型("private"/"internal"/"external"/...)
|
Linkage: str # 链接类型("private"/"internal"/"external"/...)
|
||||||
Section: t.CChar | t.CPtr # 段名(None = 默认)
|
Section: str # 段名(None = 默认)
|
||||||
UnnamedAddr: t.CInt # 1=unnamed_addr, 2=local_unnamed_addr, 0=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
|
@t.NoVTable
|
||||||
class NamedTypeNode(GSListNode[NamedTypeNode]):
|
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
|
@t.NoVTable
|
||||||
class LLVMModule:
|
class LLVMModule:
|
||||||
Name: t.CChar | t.CPtr # 模块名
|
Name: str # 模块名
|
||||||
FuncHead: Function | t.CPtr # 函数链表头
|
FuncHead: rowptr[Function] # 函数链表头
|
||||||
FuncTail: Function | t.CPtr # 函数链表尾
|
FuncTail: rowptr[Function] # 函数链表尾
|
||||||
FuncCount: t.CSizeT # 函数计数
|
FuncCount: t.CSizeT # 函数计数
|
||||||
GlobalHead: GlobalVariable | t.CPtr # 全局变量链表头
|
GlobalHead: rowptr[GlobalVariable] # 全局变量链表头
|
||||||
GlobalTail: GlobalVariable | t.CPtr # 全局变量链表尾
|
GlobalTail: rowptr[GlobalVariable] # 全局变量链表尾
|
||||||
GlobalCount: t.CSizeT # 全局变量计数
|
GlobalCount: t.CSizeT # 全局变量计数
|
||||||
TargetTriple: t.CChar | t.CPtr # 目标三元组(如 "x86_64-pc-linux-gnu")
|
TargetTriple: str # 目标三元组(如 "x86_64-pc-linux-gnu")
|
||||||
DataLayout: t.CChar | t.CPtr # 数据布局(如 "e-m:e-p270:32:32-...")
|
DataLayout: str # 数据布局(如 "e-m:e-p270:32:32-...")
|
||||||
NamedTypeHead: NamedTypeNode | t.CPtr # 命名结构体类型链表头
|
NamedTypeHead: rowptr[NamedTypeNode] # 命名结构体类型链表头
|
||||||
NamedTypeTail: NamedTypeNode | t.CPtr # 命名结构体类型链表尾
|
NamedTypeTail: rowptr[NamedTypeNode] # 命名结构体类型链表尾
|
||||||
NamedTypeCount: t.CSizeT # 命名结构体类型计数
|
NamedTypeCount: t.CSizeT # 命名结构体类型计数
|
||||||
# 总计: 12 字段 * 8 = 96 字节(无 vtable)
|
# 总计: 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))"""
|
"""将函数追加到模块函数链表(O(1))"""
|
||||||
if self is None or func is None: return
|
if self is None or func is None: return
|
||||||
func.Next = None
|
func.Next = None
|
||||||
@@ -79,7 +81,7 @@ class LLVMModule:
|
|||||||
self.FuncTail = func
|
self.FuncTail = func
|
||||||
self.FuncCount += 1
|
self.FuncCount += 1
|
||||||
|
|
||||||
def add_global(self, gv: GlobalVariable | t.CPtr):
|
def add_global(self, gv: rowptr[GlobalVariable]):
|
||||||
"""将全局变量追加到模块全局变量链表(O(1))"""
|
"""将全局变量追加到模块全局变量链表(O(1))"""
|
||||||
if self is None or gv is None: return
|
if self is None or gv is None: return
|
||||||
gv.Next = None
|
gv.Next = None
|
||||||
@@ -91,18 +93,18 @@ class LLVMModule:
|
|||||||
self.GlobalCount += 1
|
self.GlobalCount += 1
|
||||||
|
|
||||||
# ---- 目标属性 ----
|
# ---- 目标属性 ----
|
||||||
def set_target(self, triple: t.CChar | t.CPtr):
|
def set_target(self, triple: str):
|
||||||
"""设置目标三元组"""
|
"""设置目标三元组"""
|
||||||
if self is None: return
|
if self is None: return
|
||||||
self.TargetTriple = triple
|
self.TargetTriple = triple
|
||||||
|
|
||||||
def set_datalayout(self, layout: t.CChar | t.CPtr):
|
def set_datalayout(self, layout: str):
|
||||||
"""设置数据布局"""
|
"""设置数据布局"""
|
||||||
if self is None: return
|
if self is None: return
|
||||||
self.DataLayout = layout
|
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" = type { ... } 定义行)
|
||||||
|
|
||||||
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
|
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
|
||||||
@@ -110,12 +112,12 @@ class LLVMModule:
|
|||||||
"""
|
"""
|
||||||
if self is None or pool is None or ty is None:
|
if self is None or pool is None or ty is None:
|
||||||
return
|
return
|
||||||
name: t.CChar | t.CPtr = get_struct_name(ty)
|
name: str = get_struct_name(ty)
|
||||||
if name is None:
|
if name is None:
|
||||||
return
|
return
|
||||||
# 去重检查(opaque 声明可被完整定义替换)
|
# 去重检查(opaque 声明可被完整定义替换)
|
||||||
cur: NamedTypeNode | t.CPtr = self.NamedTypeHead
|
cur: rowptr[NamedTypeNode] = self.NamedTypeHead
|
||||||
cnt_dedup: t.CInt = 0
|
cnt_dedup: int = 0
|
||||||
while cur is not None:
|
while cur is not None:
|
||||||
# 步数守卫:NamedTypeHead 链表成环(内存损坏/插入 bug)会导致
|
# 步数守卫:NamedTypeHead 链表成环(内存损坏/插入 bug)会导致
|
||||||
# 无限遍历挂起(G3 编译 LinkedNode.prepend 挂起根因)。
|
# 无限遍历挂起(G3 编译 LinkedNode.prepend 挂起根因)。
|
||||||
@@ -126,7 +128,7 @@ class LLVMModule:
|
|||||||
name if name is not None else "(null)", cnt_dedup)
|
name if name is not None else "(null)", cnt_dedup)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
if cur.Ty is not None:
|
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 existing_name is not None:
|
||||||
if string.strcmp(existing_name, name) == 0:
|
if string.strcmp(existing_name, name) == 0:
|
||||||
# 已有完整定义则无需替换
|
# 已有完整定义则无需替换
|
||||||
@@ -140,11 +142,12 @@ class LLVMModule:
|
|||||||
return
|
return
|
||||||
cur = cur.Next
|
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:
|
if node is None:
|
||||||
return
|
return
|
||||||
string.memset(node, 0, NAMED_TYPE_NODE_SIZE)
|
string.memset(node, 0, NAMED_TYPE_NODE_SIZE)
|
||||||
node.Ty = ty
|
node.Ty = ty
|
||||||
|
node.IsPacked = 0
|
||||||
# opaque 类型插入链表头部,确保在引用它的完整定义之前声明。
|
# opaque 类型插入链表头部,确保在引用它的完整定义之前声明。
|
||||||
# 例如 TypeRegistry{HashTable*, ...} 中,HashTable 的 opaque 声明
|
# 例如 TypeRegistry{HashTable*, ...} 中,HashTable 的 opaque 声明
|
||||||
# 必须在 TypeRegistry 定义之前,否则 llc 报 "use of undefined type"。
|
# 必须在 TypeRegistry 定义之前,否则 llc 报 "use of undefined type"。
|
||||||
@@ -163,12 +166,12 @@ class LLVMModule:
|
|||||||
self.NamedTypeTail = node
|
self.NamedTypeTail = node
|
||||||
self.NamedTypeCount += 1
|
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=未定义"""
|
"""检查模块中是否已定义指定名称的结构体类型,返回 1=已定义 / 0=未定义"""
|
||||||
if self is None or name is None:
|
if self is None or name is None:
|
||||||
return 0
|
return 0
|
||||||
cur: NamedTypeNode | t.CPtr = self.NamedTypeHead
|
cur: rowptr[NamedTypeNode] = self.NamedTypeHead
|
||||||
cnt_tdm: t.CInt = 0
|
cnt_tdm: int = 0
|
||||||
while cur is not None:
|
while cur is not None:
|
||||||
# 步数守卫:同上,防 NamedTypeHead 链表成环无限遍历
|
# 步数守卫:同上,防 NamedTypeHead 链表成环无限遍历
|
||||||
cnt_tdm += 1
|
cnt_tdm += 1
|
||||||
@@ -177,15 +180,15 @@ class LLVMModule:
|
|||||||
name if name is not None else "(null)")
|
name if name is not None else "(null)")
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
if cur.Ty is not None:
|
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 existing_name is not None:
|
||||||
if string.strcmp(existing_name, name) == 0:
|
if string.strcmp(existing_name, name) == 0:
|
||||||
return 1
|
return 1
|
||||||
cur = cur.Next
|
cur = cur.Next
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def ensure_opaque_for_type(self, pool: memhub.MemBuddy | t.CPtr,
|
def ensure_opaque_for_type(self, pool: rowptr[memhub.MemBuddy],
|
||||||
ty: LLVMType | t.CPtr):
|
ty: rowptr[LLVMType]):
|
||||||
"""为类型中的跨模块结构体引用添加 opaque 声明
|
"""为类型中的跨模块结构体引用添加 opaque 声明
|
||||||
|
|
||||||
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
|
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
|
||||||
@@ -194,8 +197,8 @@ class LLVMModule:
|
|||||||
_scan_type_for_cross_module_refs(pool, self, ty)
|
_scan_type_for_cross_module_refs(pool, self, ty)
|
||||||
|
|
||||||
# ---- 打印 ----
|
# ---- 打印 ----
|
||||||
def PrintModule(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def PrintModule(self, buf: str, size: t.CSizeT,
|
||||||
pool: memhub.MemBuddy | t.CPtr, mode: t.CInt):
|
pool: rowptr[memhub.MemBuddy], mode: int):
|
||||||
"""将模块序列化为 .ll 文本写入 buf"""
|
"""将模块序列化为 .ll 文本写入 buf"""
|
||||||
if self is None or buf is None or size == 0: return
|
if self is None or buf is None or size == 0: return
|
||||||
|
|
||||||
@@ -226,7 +229,7 @@ class LLVMModule:
|
|||||||
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
|
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
|
||||||
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
|
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
|
||||||
# 修复:alloc_buf 返回 viperio.Buf,但 Buf 类型未在 NamedTypeHead 中注册
|
# 修复: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
|
func_scan_steps: t.CSizeT = 0
|
||||||
while func_scan is not None:
|
while func_scan is not None:
|
||||||
func_scan_steps += 1
|
func_scan_steps += 1
|
||||||
@@ -237,7 +240,17 @@ class LLVMModule:
|
|||||||
if func_scan.RetTy is not None:
|
if func_scan.RetTy is not None:
|
||||||
self.ensure_opaque_for_type(pool, func_scan.RetTy)
|
self.ensure_opaque_for_type(pool, func_scan.RetTy)
|
||||||
if func_scan.Params is not None:
|
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
|
param_scan_steps: t.CSizeT = 0
|
||||||
while param_scan is not None:
|
while param_scan is not None:
|
||||||
param_scan_steps += 1
|
param_scan_steps += 1
|
||||||
@@ -246,6 +259,19 @@ class LLVMModule:
|
|||||||
func_scan.Name, func_scan.Params.Count,
|
func_scan.Name, func_scan.Params.Count,
|
||||||
t.CUInt64T(param_scan), t.CUInt64T(param_scan.Next), IR_DUMP_CHAIN_LIMIT)
|
t.CUInt64T(param_scan), t.CUInt64T(param_scan.Next), IR_DUMP_CHAIN_LIMIT)
|
||||||
stdlib.exit(1)
|
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 字段访问
|
# 用访问器(__function.vp 完整类型内)绕开 stub 字段访问
|
||||||
# 陷阱:跨模块 struct 字段访问可能生成错误 GEP/静默跳过,
|
# 陷阱:跨模块 struct 字段访问可能生成错误 GEP/静默跳过,
|
||||||
# 导致 param_scan 永不更新死循环。
|
# 导致 param_scan 永不更新死循环。
|
||||||
@@ -253,10 +279,10 @@ class LLVMModule:
|
|||||||
self.ensure_opaque_for_type(pool, param_get_ty(param_scan))
|
self.ensure_opaque_for_type(pool, param_get_ty(param_scan))
|
||||||
param_scan = param_get_next(param_scan)
|
param_scan = param_get_next(param_scan)
|
||||||
func_scan = func_scan.Next
|
func_scan = func_scan.Next
|
||||||
nt: NamedTypeNode | t.CPtr = self.NamedTypeHead
|
nt: rowptr[NamedTypeNode] = self.NamedTypeHead
|
||||||
# 结构体定义缓冲区:48 字段 × ~50 字节/字段类型名 ≈ 2400 字节,4096 足够
|
# 结构体定义缓冲区:48 字段 × ~50 字节/字段类型名 ≈ 2400 字节,4096 足够
|
||||||
# 在循环外分配一次并复用,减少 pool 碎片
|
# 在循环外分配一次并复用,减少 pool 碎片
|
||||||
ty_buf: t.CChar | t.CPtr = pool.alloc(4096)
|
ty_buf: str = pool.alloc(4096)
|
||||||
nt_steps: t.CSizeT = 0
|
nt_steps: t.CSizeT = 0
|
||||||
while nt is not None:
|
while nt is not None:
|
||||||
nt_steps += 1
|
nt_steps += 1
|
||||||
@@ -267,7 +293,7 @@ class LLVMModule:
|
|||||||
if nt.Ty is not None:
|
if nt.Ty is not None:
|
||||||
if ty_buf is not None:
|
if ty_buf is not None:
|
||||||
ty_buf[0] = '\0'
|
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, ty_buf)
|
||||||
_append_cstr(buf, size, "\n")
|
_append_cstr(buf, size, "\n")
|
||||||
nt = nt.Next
|
nt = nt.Next
|
||||||
@@ -276,7 +302,7 @@ class LLVMModule:
|
|||||||
_append_cstr(buf, size, "\n")
|
_append_cstr(buf, size, "\n")
|
||||||
|
|
||||||
# 全局变量
|
# 全局变量
|
||||||
gv: GlobalVariable | t.CPtr = self.GlobalHead
|
gv: rowptr[GlobalVariable] = self.GlobalHead
|
||||||
gv_steps: t.CSizeT = 0
|
gv_steps: t.CSizeT = 0
|
||||||
if mode == OUTPUT_STUB:
|
if mode == OUTPUT_STUB:
|
||||||
# stub 模式:输出 external global(无初值)
|
# stub 模式:输出 external global(无初值)
|
||||||
@@ -292,7 +318,7 @@ class LLVMModule:
|
|||||||
else:
|
else:
|
||||||
# full 和 text 模式:输出完整全局变量
|
# full 和 text 模式:输出完整全局变量
|
||||||
# text 模式跳过无初值的全局变量(纯声明)
|
# text 模式跳过无初值的全局变量(纯声明)
|
||||||
gv_idx: t.CInt = 0
|
gv_idx: int = 0
|
||||||
while gv is not None:
|
while gv is not None:
|
||||||
gv_steps += 1
|
gv_steps += 1
|
||||||
if gv_steps > IR_DUMP_CHAIN_LIMIT:
|
if gv_steps > IR_DUMP_CHAIN_LIMIT:
|
||||||
@@ -312,8 +338,8 @@ class LLVMModule:
|
|||||||
_append_cstr(buf, size, "\n")
|
_append_cstr(buf, size, "\n")
|
||||||
elif self.GlobalHead is not None and mode == OUTPUT_TEXT:
|
elif self.GlobalHead is not None and mode == OUTPUT_TEXT:
|
||||||
# text 模式下如果输出了全局变量,也加空行
|
# text 模式下如果输出了全局变量,也加空行
|
||||||
had_global: t.CInt = 0
|
had_global: int = 0
|
||||||
gv2: GlobalVariable | t.CPtr = self.GlobalHead
|
gv2: rowptr[GlobalVariable] = self.GlobalHead
|
||||||
gv2_steps: t.CSizeT = 0
|
gv2_steps: t.CSizeT = 0
|
||||||
while gv2 is not None:
|
while gv2 is not None:
|
||||||
gv2_steps += 1
|
gv2_steps += 1
|
||||||
@@ -329,8 +355,8 @@ class LLVMModule:
|
|||||||
_append_cstr(buf, size, "\n")
|
_append_cstr(buf, size, "\n")
|
||||||
|
|
||||||
# 遍历函数
|
# 遍历函数
|
||||||
func: Function | t.CPtr = self.FuncHead
|
func: rowptr[Function] = self.FuncHead
|
||||||
func_idx: t.CInt = 0
|
func_idx: int = 0
|
||||||
func_steps: t.CSizeT = 0
|
func_steps: t.CSizeT = 0
|
||||||
while func is not None:
|
while func is not None:
|
||||||
func_steps += 1
|
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)
|
# 硬编码 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
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, 96)
|
string.memset(ptr, 0, 96)
|
||||||
ptr.Name = name
|
ptr.Name = name
|
||||||
@@ -380,16 +406,16 @@ def new_module(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> LLVMMo
|
|||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
# GlobalVariable 硬编码大小: Next(8) + Name(8) + Ty(8) + Initializer(8) + IsConstant(4) + Linkage(8) + Section(8) + UnnamedAddr(4) = 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 = 64
|
GV_SIZE: t.CDefine = 72
|
||||||
|
|
||||||
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) = 16 字节
|
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) + IsPacked(8) = 24 字节
|
||||||
NAMED_TYPE_NODE_SIZE: t.CDefine = 16
|
NAMED_TYPE_NODE_SIZE: t.CDefine = 24
|
||||||
|
|
||||||
def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
|
def new_global_variable(pool: rowptr[memhub.MemBuddy],
|
||||||
name: t.CChar | t.CPtr, ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
|
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
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, GV_SIZE)
|
string.memset(ptr, 0, GV_SIZE)
|
||||||
ptr.Name = name
|
ptr.Name = name
|
||||||
@@ -399,33 +425,34 @@ def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
ptr.Linkage = "external"
|
ptr.Linkage = "external"
|
||||||
ptr.Section = None
|
ptr.Section = None
|
||||||
ptr.UnnamedAddr = 0
|
ptr.UnnamedAddr = 0
|
||||||
|
ptr.Align = 0
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# 链表操作(嵌入式 Head/Tail/Count,O(1) 追加)
|
# 链表操作(嵌入式 Head/Tail/Count,O(1) 追加)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def module_add_function(mod: LLVMModule | t.CPtr, func: Function | t.CPtr):
|
def module_add_function(mod: rowptr[LLVMModule], func: rowptr[Function]):
|
||||||
return mod.add_function(func)
|
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 字段访问陷阱)"""
|
"""获取模块函数链表头(跨模块访问器,绕 stub 字段访问陷阱)"""
|
||||||
if mod is None:
|
if mod is None:
|
||||||
return None
|
return None
|
||||||
return mod.FuncHead
|
return mod.FuncHead
|
||||||
|
|
||||||
|
|
||||||
def module_add_global(mod: LLVMModule | t.CPtr, gv: GlobalVariable | t.CPtr):
|
def module_add_global(mod: rowptr[LLVMModule], gv: rowptr[GlobalVariable]):
|
||||||
return mod.add_global(gv)
|
mod.add_global(gv)
|
||||||
|
|
||||||
|
|
||||||
def module_set_target(mod: LLVMModule | t.CPtr, triple: t.CChar | t.CPtr):
|
def module_set_target(mod: rowptr[LLVMModule], triple: str):
|
||||||
return mod.set_target(triple)
|
mod.set_target(triple)
|
||||||
|
|
||||||
|
|
||||||
def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
|
def module_set_datalayout(mod: rowptr[LLVMModule], layout: str):
|
||||||
return mod.set_datalayout(layout)
|
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=否
|
# Returns: 1=是 opaque / 0=否
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
|
def _is_opaque_struct(ty: rowptr[LLVMType]) -> int:
|
||||||
"""检查类型是否是 opaque 结构体
|
"""检查类型是否是 opaque 结构体
|
||||||
|
|
||||||
opaque 是跨模块前向声明(仅名称无字段定义),由
|
opaque 是跨模块前向声明(仅名称无字段定义),由
|
||||||
@@ -466,9 +493,36 @@ def _is_opaque_struct(ty: LLVMType | t.CPtr) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
def module_add_named_type(mod: rowptr[LLVMModule], pool: rowptr[memhub.MemBuddy],
|
||||||
ty: LLVMType | t.CPtr):
|
ty: rowptr[LLVMType]):
|
||||||
return mod.add_named_type(pool, ty)
|
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)。
|
# 如果该名称未在模块中定义,则添加 opaque 声明(%"name" = type opaque)。
|
||||||
# 这解决了跨模块结构体引用导致的 llc "use of undefined type" 错误。
|
# 这解决了跨模块结构体引用导致的 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)
|
return mod._is_type_defined_in_module(name)
|
||||||
|
|
||||||
|
|
||||||
def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
|
def _scan_type_for_cross_module_refs(pool: rowptr[memhub.MemBuddy],
|
||||||
mod: LLVMModule | t.CPtr,
|
mod: rowptr[LLVMModule],
|
||||||
ty: LLVMType | t.CPtr,
|
ty: rowptr[LLVMType],
|
||||||
depth: t.CInt = 0):
|
depth: int = 0):
|
||||||
"""递归扫描类型树,为跨模块结构体引用添加 opaque 声明"""
|
"""递归扫描类型树,为跨模块结构体引用添加 opaque 声明"""
|
||||||
if ty is None or mod is None or pool is None:
|
if ty is None or mod is None or pool is None:
|
||||||
return
|
return
|
||||||
@@ -506,13 +560,13 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
# 创建 opaque 类型并添加到模块
|
# 创建 opaque 类型并添加到模块
|
||||||
# fcount=-1 哨兵标记 opaque(区别于空结构体 {},
|
# fcount=-1 哨兵标记 opaque(区别于空结构体 {},
|
||||||
# 后者 fcount==0 是合法完整定义,可 alloca)
|
# 后者 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:
|
if opaque_ty is not None:
|
||||||
module_add_named_type(mod, pool, opaque_ty)
|
module_add_named_type(mod, pool, opaque_ty)
|
||||||
# 递归扫描结构体字段中的跨模块引用
|
# 递归扫描结构体字段中的跨模块引用
|
||||||
# 例如 TypeRegistry{HashTable*, MemManager*} 中的 HashTable 引用
|
# 例如 TypeRegistry{HashTable*, MemManager*} 中的 HashTable 引用
|
||||||
if sfields is not None:
|
if sfields is not None:
|
||||||
fld: ParamNode | t.CPtr = sfields
|
fld: rowptr[ParamNode] = sfields
|
||||||
fld_steps: t.CSizeT = 0
|
fld_steps: t.CSizeT = 0
|
||||||
while fld is not None:
|
while fld is not None:
|
||||||
fld_steps += 1
|
fld_steps += 1
|
||||||
@@ -526,20 +580,9 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
case _:
|
case _:
|
||||||
_scan_type_for_cross_module_refs(pool, mod, pointee, depth + 1)
|
_scan_type_for_cross_module_refs(pool, mod, pointee, depth + 1)
|
||||||
case LLVMType.Struct(sfields2, sfcount2, sname2):
|
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:
|
if sfields2 is not None:
|
||||||
fld2: ParamNode | t.CPtr = sfields2
|
fld2: rowptr[ParamNode] = sfields2
|
||||||
fld2_steps: t.CSizeT = 0
|
fld2_steps: t.CSizeT = 0
|
||||||
while fld2 is not None:
|
while fld2 is not None:
|
||||||
fld2_steps += 1
|
fld2_steps += 1
|
||||||
@@ -557,34 +600,34 @@ def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def module_ensure_opaque_for_type(mod: LLVMModule | t.CPtr,
|
def module_ensure_opaque_for_type(mod: rowptr[LLVMModule],
|
||||||
pool: memhub.MemBuddy | t.CPtr,
|
pool: rowptr[memhub.MemBuddy],
|
||||||
ty: LLVMType | t.CPtr):
|
ty: rowptr[LLVMType]):
|
||||||
return mod.ensure_opaque_for_type(pool, ty)
|
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
|
if gv is None: return
|
||||||
gv.IsConstant = is_const
|
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/... )"""
|
"""设置链接类型 (private/internal/external/... )"""
|
||||||
if gv is None: return
|
if gv is None: return
|
||||||
gv.Linkage = linkage
|
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)"""
|
"""设置 unnamed_addr 属性 (0=none, 1=unnamed_addr, 2=local_unnamed_addr)"""
|
||||||
if gv is None: return
|
if gv is None: return
|
||||||
gv.UnnamedAddr = level
|
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
|
if gv is None: return
|
||||||
gv.Section = section
|
gv.Section = section
|
||||||
@@ -610,17 +653,17 @@ IR_DUMP_CHAIN_LIMIT: t.CDefine = 100000
|
|||||||
#
|
#
|
||||||
# mode: OUTPUT_FULL=完整, OUTPUT_STUB=仅声明, OUTPUT_TEXT=仅代码
|
# mode: OUTPUT_FULL=完整, OUTPUT_STUB=仅声明, OUTPUT_TEXT=仅代码
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def LLVMModulePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def LLVMModulePrint(buf: str, size: t.CSizeT,
|
||||||
mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
mod: rowptr[LLVMModule], pool: rowptr[memhub.MemBuddy],
|
||||||
mode: t.CInt):
|
mode: int):
|
||||||
return mod.PrintModule(buf, size, pool, mode)
|
mod.PrintModule(buf, size, pool, mode)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# 全局变量打印
|
# 全局变量打印
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def _print_global(buf: str, size: t.CSizeT,
|
||||||
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
gv: rowptr[GlobalVariable], pool: rowptr[memhub.MemBuddy]):
|
||||||
"""打印单个全局变量: @<name> = [linkage] [unnamed_addr] [constant] <ty> <init>"""
|
"""打印单个全局变量: @<name> = [linkage] [unnamed_addr] [constant] <ty> <init>"""
|
||||||
if gv is None: return
|
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 ")
|
_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:
|
if ty_buf is not None:
|
||||||
ty_buf[0] = '\0'
|
ty_buf[0] = '\0'
|
||||||
TypePrint(ty_buf, 512, gv.Ty, pool)
|
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, gv.Section)
|
||||||
_append_cstr(buf, size, "\"")
|
_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,无初值)
|
# _print_global_stub - 打印全局变量的声明形式(external global,无初值)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def _print_global_stub(buf: str, size: t.CSizeT,
|
||||||
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
gv: rowptr[GlobalVariable], pool: rowptr[memhub.MemBuddy]):
|
||||||
"""打印全局变量声明: @<name> = external global <ty>"""
|
"""打印全局变量声明: @<name> = external global <ty>"""
|
||||||
if gv is None: return
|
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 ")
|
_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:
|
if ty_buf is not None:
|
||||||
ty_buf[0] = '\0'
|
ty_buf[0] = '\0'
|
||||||
TypePrint(ty_buf, 512, gv.Ty, pool)
|
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_dst: t.CUInt64T = 0
|
||||||
_g_last_pos: t.CSizeT = 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 末尾"""
|
"""将 C 字符串 src 追加到 dst 末尾"""
|
||||||
global _g_last_dst, _g_last_pos
|
global _g_last_dst, _g_last_pos
|
||||||
if dst is None or src is None: return
|
if dst is None or src is None: return
|
||||||
|
|||||||
+142
-127
@@ -11,13 +11,13 @@ from linkedlist import GSListNode
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
# ParamNode: 函数参数类型链表节点
|
# ParamNode: 函数参数类型链表节点
|
||||||
# 继承 GSListNode[ParamNode] 获取强类型 Next: ParamNode|CPtr
|
# 继承 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(理由见 __function.py 的 Line 注释)。
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class ParamNode(GSListNode[ParamNode]):
|
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):
|
class LLVMType(t.REnum):
|
||||||
# 整数类型: i1/i8/i16/i32/i64
|
# 整数类型: i1/i8/i16/i32/i64
|
||||||
class Int:
|
class Int:
|
||||||
Bits: t.CInt
|
Bits: int
|
||||||
|
|
||||||
# 指针类型: pointee*
|
# 指针类型: pointee*
|
||||||
class Ptr:
|
class Ptr:
|
||||||
Pointee: LLVMType | t.CPtr
|
Pointee: rowptr[LLVMType]
|
||||||
|
|
||||||
# 函数类型: ret (params)
|
# 函数类型: ret (params)
|
||||||
class Func:
|
class Func:
|
||||||
Ret: LLVMType | t.CPtr
|
Ret: rowptr[LLVMType]
|
||||||
Params: ParamNode | t.CPtr
|
Params: rowptr[ParamNode]
|
||||||
PCount: t.CInt
|
PCount: int
|
||||||
|
|
||||||
# 数组类型: [N x elem_ty]
|
# 数组类型: [N x elem_ty]
|
||||||
class Array:
|
class Array:
|
||||||
ElemTy: LLVMType | t.CPtr
|
ElemTy: rowptr[LLVMType]
|
||||||
Count: t.CInt
|
Count: int
|
||||||
|
|
||||||
# 结构体类型: {ty1, ty2, ...} 或 %"name" = type {ty1, ty2, ...}
|
# 结构体类型: {ty1, ty2, ...} 或 %"name" = type {ty1, ty2, ...}
|
||||||
# Fields 复用 ParamNode 链表(ParamNode.Ty 即字段类型)
|
# Fields 复用 ParamNode 链表(ParamNode.Ty 即字段类型)
|
||||||
# Name 非 None 时为命名结构体,TypePrint 输出 %"name" 而非 {...}
|
# Name 非 None 时为命名结构体,TypePrint 输出 %"name" 而非 {...}
|
||||||
class Struct:
|
class Struct:
|
||||||
Fields: ParamNode | t.CPtr
|
Fields: rowptr[ParamNode]
|
||||||
FCount: t.CInt
|
FCount: int
|
||||||
Name: t.CChar | t.CPtr
|
Name: str
|
||||||
|
|
||||||
# 浮点类型: half/float/double/fp128
|
# 浮点类型: half/float/double/fp128
|
||||||
class Float:
|
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:
|
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"""
|
"""从 mpool 分配一个零初始化的 LLVMType"""
|
||||||
ptr: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
|
ptr: rowptr[LLVMType] = pool.alloc(LLVMType.__sizeof__())
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, LLVMType.__sizeof__())
|
string.memset(ptr, 0, LLVMType.__sizeof__())
|
||||||
return ptr
|
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:
|
def Int1(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Int(1))
|
c.DerefAs(ptr, LLVMType.Int(1))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Int8(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Int8(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Int(8))
|
c.DerefAs(ptr, LLVMType.Int(8))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Int16(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Int16(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Int(16))
|
c.DerefAs(ptr, LLVMType.Int(16))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Int32(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Int32(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Int(32))
|
c.DerefAs(ptr, LLVMType.Int(32))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Int64(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Int64(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Int(64))
|
c.DerefAs(ptr, LLVMType.Int(64))
|
||||||
return ptr
|
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)
|
"""创建指针类型 Ptr(pointee)
|
||||||
|
|
||||||
LLVM IR 中 **不允许 void* 指针**("pointers to void are invalid"),
|
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)。
|
其他类型正常构造 Ptr(pointee)。
|
||||||
"""
|
"""
|
||||||
# ============== 前置校验: 拦截 Void / None pointee(void* 非法)==============
|
# ============== 前置校验: 拦截 Void / None pointee(void* 非法)==============
|
||||||
safe_pointee: LLVMType | t.CPtr = pointee
|
safe_pointee: rowptr[LLVMType] = pointee
|
||||||
if safe_pointee is None:
|
if safe_pointee is None:
|
||||||
safe_pointee = Int8(pool)
|
safe_pointee = Int8(pool)
|
||||||
else:
|
else:
|
||||||
@@ -139,85 +139,85 @@ def Ptr(pool: memhub.MemBuddy | t.CPtr, pointee: LLVMType | t.CPtr) -> LLVMType
|
|||||||
safe_pointee = Int8(pool)
|
safe_pointee = Int8(pool)
|
||||||
case _:
|
case _:
|
||||||
pass
|
pass
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Ptr(safe_pointee))
|
c.DerefAs(ptr, LLVMType.Ptr(safe_pointee))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Func(pool: memhub.MemBuddy | t.CPtr, ret: LLVMType | t.CPtr,
|
def Func(pool: rowptr[memhub.MemBuddy], ret: rowptr[LLVMType],
|
||||||
params: ParamNode | t.CPtr, count: t.CInt) -> LLVMType | t.CPtr:
|
params: rowptr[ParamNode], count: int) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Func(ret, params, count))
|
c.DerefAs(ptr, LLVMType.Func(ret, params, count))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Void(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Void(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Void())
|
c.DerefAs(ptr, LLVMType.Void())
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Array(pool: memhub.MemBuddy | t.CPtr, elem_ty: LLVMType | t.CPtr,
|
def Array(pool: rowptr[memhub.MemBuddy], elem_ty: rowptr[LLVMType],
|
||||||
count: t.CInt) -> LLVMType | t.CPtr:
|
count: int) -> rowptr[LLVMType]:
|
||||||
"""创建数组类型 [count x elem_ty]"""
|
"""创建数组类型 [count x elem_ty]"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Array(elem_ty, count))
|
c.DerefAs(ptr, LLVMType.Array(elem_ty, count))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Struct(pool: memhub.MemBuddy | t.CPtr, fields: ParamNode | t.CPtr,
|
def Struct(pool: rowptr[memhub.MemBuddy], fields: rowptr[ParamNode],
|
||||||
fcount: t.CInt, name: t.CChar | t.CPtr) -> LLVMType | t.CPtr:
|
fcount: int, name: str) -> rowptr[LLVMType]:
|
||||||
"""创建结构体类型 {ty1, ty2, ...}
|
"""创建结构体类型 {ty1, ty2, ...}
|
||||||
|
|
||||||
fields 为 ParamNode 链表头,fcount 为字段数量。
|
fields 为 ParamNode 链表头,fcount 为字段数量。
|
||||||
name 非 None 时为命名结构体(如 "sha1.ClassName"),TypePrint 输出 %"name"。
|
name 非 None 时为命名结构体(如 "sha1.ClassName"),TypePrint 输出 %"name"。
|
||||||
name 为 None 时为匿名结构体,TypePrint 输出 {ty1, ty2, ...}。
|
name 为 None 时为匿名结构体,TypePrint 输出 {ty1, ty2, ...}。
|
||||||
"""
|
"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Struct(fields, fcount, name))
|
c.DerefAs(ptr, LLVMType.Struct(fields, fcount, name))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Half(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Half(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
"""创建半精度浮点类型 half (16-bit)"""
|
"""创建半精度浮点类型 half (16-bit)"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Float(16))
|
c.DerefAs(ptr, LLVMType.Float(16))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Float(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Float(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
"""创建单精度浮点类型 float (32-bit)"""
|
"""创建单精度浮点类型 float (32-bit)"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Float(32))
|
c.DerefAs(ptr, LLVMType.Float(32))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Double(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Double(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
"""创建双精度浮点类型 double (64-bit)"""
|
"""创建双精度浮点类型 double (64-bit)"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Float(64))
|
c.DerefAs(ptr, LLVMType.Float(64))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def FP128(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def FP128(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
"""创建四精度浮点类型 fp128 (128-bit)"""
|
"""创建四精度浮点类型 fp128 (128-bit)"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Float(128))
|
c.DerefAs(ptr, LLVMType.Float(128))
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def Label(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
def Label(pool: rowptr[memhub.MemBuddy]) -> rowptr[LLVMType]:
|
||||||
"""创建标签类型 label"""
|
"""创建标签类型 label"""
|
||||||
ptr: LLVMType | t.CPtr = _new_type(pool)
|
ptr: rowptr[LLVMType] = _new_type(pool)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
c.DerefAs(ptr, LLVMType.Label())
|
c.DerefAs(ptr, LLVMType.Label())
|
||||||
return ptr
|
return ptr
|
||||||
@@ -229,9 +229,9 @@ def Label(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
|
|||||||
# ParamNode 硬编码大小: Next(8) + Ty(8) = 16 字节
|
# ParamNode 硬编码大小: Next(8) + Ty(8) = 16 字节
|
||||||
PNODE_SIZE: t.CDefine = 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 设为给定类型指针"""
|
"""创建一个参数节点,Ty 设为给定类型指针"""
|
||||||
ptr: ParamNode | t.CPtr = pool.alloc(PNODE_SIZE)
|
ptr: rowptr[ParamNode] = pool.alloc(PNODE_SIZE)
|
||||||
if ptr is None: return None
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, PNODE_SIZE)
|
string.memset(ptr, 0, PNODE_SIZE)
|
||||||
ptr.Ty = ty
|
ptr.Ty = ty
|
||||||
@@ -239,8 +239,8 @@ def new_param_node(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Par
|
|||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def param_list_append(head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
|
def param_list_append(head: rowptr[ParamNode], tail: rowptr[ParamNode],
|
||||||
node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
|
node: rowptr[ParamNode]) -> rowptr[ParamNode]:
|
||||||
"""将 node 追加到参数链表尾部,返回 head 和更新后的 tail"""
|
"""将 node 追加到参数链表尾部,返回 head 和更新后的 tail"""
|
||||||
if node is None: return head
|
if node is None: return head
|
||||||
node.Next = None
|
node.Next = None
|
||||||
@@ -258,28 +258,28 @@ def param_list_append(head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
|
|||||||
# 导致 TransPyC 静默跳过字段访问。这些访问器在拥有完整类型定义的
|
# 导致 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:
|
if node is None:
|
||||||
return 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:
|
if node is None:
|
||||||
return None
|
return None
|
||||||
return node.Next
|
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:
|
if node is None:
|
||||||
return
|
return
|
||||||
node.Ty = ty
|
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:
|
if node is None:
|
||||||
return
|
return
|
||||||
@@ -290,77 +290,77 @@ def paramnode_set_next(node: ParamNode | t.CPtr, nxt: ParamNode | t.CPtr):
|
|||||||
# LLVMTypeCore: 类型创建核心,封装 pool 避免重复传参
|
# LLVMTypeCore: 类型创建核心,封装 pool 避免重复传参
|
||||||
#
|
#
|
||||||
# 用法:
|
# 用法:
|
||||||
# core: LLVMTypeCore | t.CPtr = LLVMTypeCore(pool)
|
# core: rowptr[LLVMTypeCore] = LLVMTypeCore(pool)
|
||||||
# ty_i32: LLVMType | t.CPtr = core.Int32()
|
# ty_i32: rowptr[LLVMType] = core.Int32()
|
||||||
# ty_ptr: LLVMType | t.CPtr = core.Ptr(ty_i32)
|
# ty_ptr: rowptr[LLVMType] = core.Ptr(ty_i32)
|
||||||
# ty_void: LLVMType | t.CPtr = core.Void()
|
# ty_void: rowptr[LLVMType] = core.Void()
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class LLVMTypeCore:
|
class LLVMTypeCore:
|
||||||
"""类型创建核心,封装 pool 避免每次创建类型都传 pool"""
|
"""类型创建核心,封装 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
|
self.Pool = pool
|
||||||
|
|
||||||
def Int1(self) -> LLVMType | t.CPtr:
|
def Int1(self) -> rowptr[LLVMType]:
|
||||||
return Int1(self.Pool)
|
return Int1(self.Pool)
|
||||||
|
|
||||||
def Int8(self) -> LLVMType | t.CPtr:
|
def Int8(self) -> rowptr[LLVMType]:
|
||||||
return Int8(self.Pool)
|
return Int8(self.Pool)
|
||||||
|
|
||||||
def Int16(self) -> LLVMType | t.CPtr:
|
def Int16(self) -> rowptr[LLVMType]:
|
||||||
return Int16(self.Pool)
|
return Int16(self.Pool)
|
||||||
|
|
||||||
def Int32(self) -> LLVMType | t.CPtr:
|
def Int32(self) -> rowptr[LLVMType]:
|
||||||
return Int32(self.Pool)
|
return Int32(self.Pool)
|
||||||
|
|
||||||
def Int64(self) -> LLVMType | t.CPtr:
|
def Int64(self) -> rowptr[LLVMType]:
|
||||||
return Int64(self.Pool)
|
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)
|
return Ptr(self.Pool, pointee)
|
||||||
|
|
||||||
def Func(self, ret: LLVMType | t.CPtr, params: ParamNode | t.CPtr,
|
def Func(self, ret: rowptr[LLVMType], params: rowptr[ParamNode],
|
||||||
count: t.CInt) -> LLVMType | t.CPtr:
|
count: int) -> rowptr[LLVMType]:
|
||||||
return Func(self.Pool, ret, params, count)
|
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)
|
return Array(self.Pool, elem_ty, count)
|
||||||
|
|
||||||
def Struct(self, fields: ParamNode | t.CPtr, fcount: t.CInt,
|
def Struct(self, fields: rowptr[ParamNode], fcount: int,
|
||||||
name: t.CChar | t.CPtr = None) -> LLVMType | t.CPtr:
|
name: str = None) -> rowptr[LLVMType]:
|
||||||
return Struct(self.Pool, fields, fcount, name)
|
return Struct(self.Pool, fields, fcount, name)
|
||||||
|
|
||||||
def Void(self) -> LLVMType | t.CPtr:
|
def Void(self) -> rowptr[LLVMType]:
|
||||||
return Void(self.Pool)
|
return Void(self.Pool)
|
||||||
|
|
||||||
def Half(self) -> LLVMType | t.CPtr:
|
def Half(self) -> rowptr[LLVMType]:
|
||||||
return Half(self.Pool)
|
return Half(self.Pool)
|
||||||
|
|
||||||
def Float(self) -> LLVMType | t.CPtr:
|
def Float(self) -> rowptr[LLVMType]:
|
||||||
return Float(self.Pool)
|
return Float(self.Pool)
|
||||||
|
|
||||||
def Double(self) -> LLVMType | t.CPtr:
|
def Double(self) -> rowptr[LLVMType]:
|
||||||
return Double(self.Pool)
|
return Double(self.Pool)
|
||||||
|
|
||||||
def FP128(self) -> LLVMType | t.CPtr:
|
def FP128(self) -> rowptr[LLVMType]:
|
||||||
return FP128(self.Pool)
|
return FP128(self.Pool)
|
||||||
|
|
||||||
def Label(self) -> LLVMType | t.CPtr:
|
def Label(self) -> rowptr[LLVMType]:
|
||||||
return Label(self.Pool)
|
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)
|
return new_param_node(self.Pool, ty)
|
||||||
|
|
||||||
# ---- 链表辅助 ----
|
# ---- 链表辅助 ----
|
||||||
def ParamListAppend(self, head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
|
def ParamListAppend(self, head: rowptr[ParamNode], tail: rowptr[ParamNode],
|
||||||
node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
|
node: rowptr[ParamNode]) -> rowptr[ParamNode]:
|
||||||
"""将 node 追加到参数/字段链表,返回新的 tail"""
|
"""将 node 追加到参数/字段链表,返回新的 tail"""
|
||||||
return param_list_append(head, tail, node)
|
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)
|
TypePrint(buf, size, ty, self.Pool)
|
||||||
|
|
||||||
|
|
||||||
@@ -378,8 +378,8 @@ class LLVMTypeCore:
|
|||||||
#
|
#
|
||||||
# pool 用于复杂类型(Array/Struct/Func)递归打印子类型时分配临时缓冲区。
|
# pool 用于复杂类型(Array/Struct/Func)递归打印子类型时分配临时缓冲区。
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def TypePrint(buf: str, size: t.CSizeT,
|
||||||
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
ty: rowptr[LLVMType], pool: rowptr[memhub.MemBuddy]):
|
||||||
"""将类型 ty 序列化为 IR 文本写入 buf(容量 size)
|
"""将类型 ty 序列化为 IR 文本写入 buf(容量 size)
|
||||||
|
|
||||||
pool 用于递归打印子类型时分配临时缓冲区。
|
pool 用于递归打印子类型时分配临时缓冲区。
|
||||||
@@ -392,9 +392,9 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
# 造成 OOM(单文件暴涨 900MB 根因)。超过 100 层即停止打印。
|
# 造成 OOM(单文件暴涨 900MB 根因)。超过 100 层即停止打印。
|
||||||
TYPEPRINT_MAX_DEPTH: t.CDefine = 100
|
TYPEPRINT_MAX_DEPTH: t.CDefine = 100
|
||||||
|
|
||||||
def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def _TypePrintDepth(buf: str, size: t.CSizeT,
|
||||||
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
ty: rowptr[LLVMType], pool: rowptr[memhub.MemBuddy],
|
||||||
depth: t.CInt):
|
depth: int):
|
||||||
"""带递归深度上限的 TypePrint 内部实现"""
|
"""带递归深度上限的 TypePrint 内部实现"""
|
||||||
if ty is None or buf is None or size == 0:
|
if ty is None or buf is None or size == 0:
|
||||||
return
|
return
|
||||||
@@ -422,7 +422,7 @@ def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
# 类型名含 sha1 前缀可超 40 字符(如
|
# 类型名含 sha1 前缀可超 40 字符(如
|
||||||
# "bbdf3bbd4c3bc28c.CONSOLE_SCREEN_BUFFER_INFO"=42),
|
# "bbdf3bbd4c3bc28c.CONSOLE_SCREEN_BUFFER_INFO"=42),
|
||||||
# 原 40 字节截断会产生未定义类型引用(llc: undefined type)。
|
# 原 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:
|
if sn_cp is not None:
|
||||||
string.strncpy(sn_cp, sname, 255)
|
string.strncpy(sn_cp, sname, 255)
|
||||||
sn_cp[255] = '\0'
|
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)
|
viperlib.snprintf(buf, size, "[%d x ", count)
|
||||||
# SHA1 限定类型名(如 %"21a7fcfc665f75ef.NamedTypeNode")可达 ~50 字节,
|
# SHA1 限定类型名(如 %"21a7fcfc665f75ef.NamedTypeNode")可达 ~50 字节,
|
||||||
# 嵌套指针/数组更易超过 128,使用 512 字节避免截断
|
# 嵌套指针/数组更易超过 128,使用 512 字节避免截断
|
||||||
tmp: t.CChar | t.CPtr = pool.alloc(512)
|
tmp: str = pool.alloc(512)
|
||||||
if tmp is not None:
|
if tmp is not None:
|
||||||
_TypePrintDepth(tmp, 512, elem_ty, pool, depth + 1)
|
_TypePrintDepth(tmp, 512, elem_ty, pool, depth + 1)
|
||||||
_strappend(buf, size, tmp)
|
_strappend(buf, size, tmp)
|
||||||
@@ -471,11 +471,11 @@ def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
# ret (ty1, ty2, ...)
|
# ret (ty1, ty2, ...)
|
||||||
_TypePrintDepth(buf, size, ret, pool, depth + 1)
|
_TypePrintDepth(buf, size, ret, pool, depth + 1)
|
||||||
_strappend(buf, size, " (")
|
_strappend(buf, size, " (")
|
||||||
cur2: ParamNode | t.CPtr = params
|
cur2: rowptr[ParamNode] = params
|
||||||
first2: t.CInt = 1
|
first2: int = 1
|
||||||
_pc2: t.CInt = 0
|
_pc2: int = 0
|
||||||
# 函数参数类型可能为 SHA1 限定命名结构体指针,512 字节避免截断
|
# 函数参数类型可能为 SHA1 限定命名结构体指针,512 字节避免截断
|
||||||
tmp3: t.CChar | t.CPtr = pool.alloc(512)
|
tmp3: str = pool.alloc(512)
|
||||||
while cur2 is not None:
|
while cur2 is not None:
|
||||||
# 悬空保护:参数链若被 reset 回收后内容复用,可能成环无限循环
|
# 悬空保护:参数链若被 reset 回收后内容复用,可能成环无限循环
|
||||||
_pc2 += 1
|
_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)"""
|
"""将 src 追加到 dst 末尾(不超过 dst_size)"""
|
||||||
if dst is None or src is None: return
|
if dst is None or src is None: return
|
||||||
dlen: t.CSizeT = string.strlen(dst)
|
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(命名结构体定义行)复用
|
# 供 TypePrint(匿名结构体)和 PrintStructDefinition(命名结构体定义行)复用
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def _print_struct_body(buf: str, size: t.CSizeT,
|
||||||
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
|
fields: rowptr[ParamNode], pool: rowptr[memhub.MemBuddy],
|
||||||
depth: t.CInt = 0):
|
depth: int = 0, packed: int = 0):
|
||||||
"""打印 {ty1, ty2, ...} 到 buf(追加模式,不覆盖已有内容)
|
"""打印 {ty1, ty2, ...} 到 buf(追加模式,不覆盖已有内容)
|
||||||
|
|
||||||
直接在 buf 当前末尾写入字段类型,避免 pool.alloc 返回与 buf 重叠的内存
|
直接在 buf 当前末尾写入字段类型,避免 pool.alloc 返回与 buf 重叠的内存
|
||||||
导致 TypePrint 写入 tmp 时覆盖 buf 已有内容。
|
导致 TypePrint 写入 tmp 时覆盖 buf 已有内容。
|
||||||
|
packed=1 时输出 <{ty1, ty2, ...}>(LLVM packed struct,无字段填充)。
|
||||||
"""
|
"""
|
||||||
if buf is None or size == 0:
|
if buf is None or size == 0:
|
||||||
return
|
return
|
||||||
_strappend(buf, size, "{")
|
if packed != 0:
|
||||||
cur: ParamNode | t.CPtr = fields
|
_strappend(buf, size, "<{")
|
||||||
first: t.CInt = 1
|
else:
|
||||||
fidx: t.CInt = 0
|
_strappend(buf, size, "{")
|
||||||
|
cur: rowptr[ParamNode] = fields
|
||||||
|
first: int = 1
|
||||||
|
fidx: int = 0
|
||||||
while cur is not None:
|
while cur is not None:
|
||||||
# 悬空保护:ParamNode 链若被 reset 回收后内容复用,Next 指针可能成环或
|
# 悬空保护:ParamNode 链若被 reset 回收后内容复用,Next 指针可能成环或
|
||||||
# 指向垃圾,无限循环。最多打印 200 个字段即停止,防止 OOM。
|
# 指向垃圾,无限循环。最多打印 200 个字段即停止,防止 OOM。
|
||||||
if fidx >= 200:
|
if fidx >= 200:
|
||||||
_strappend(buf, size, "...}")
|
if packed != 0:
|
||||||
|
_strappend(buf, size, "...}>")
|
||||||
|
else:
|
||||||
|
_strappend(buf, size, "...}")
|
||||||
return
|
return
|
||||||
if first == 0:
|
if first == 0:
|
||||||
_strappend(buf, size, ", ")
|
_strappend(buf, size, ", ")
|
||||||
@@ -567,7 +574,10 @@ def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
cur = cur.Next
|
cur = cur.Next
|
||||||
first = 0
|
first = 0
|
||||||
fidx += 1
|
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, ... }
|
# 输出格式: %"name" = type { ty1, ty2, ... }
|
||||||
# 供 LLVMModulePrint 在全局变量/函数之前输出类型定义
|
# 供 LLVMModulePrint 在全局变量/函数之前输出类型定义
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def PrintStructDefinition(buf: str, size: t.CSizeT,
|
||||||
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
ty: rowptr[LLVMType], pool: rowptr[memhub.MemBuddy],
|
||||||
|
packed: int = 0):
|
||||||
"""打印命名结构体类型定义行 %"name" = type { ty1, ty2, ... }
|
"""打印命名结构体类型定义行 %"name" = type { ty1, ty2, ... }
|
||||||
|
|
||||||
当 fcount == -1(哨兵)时输出 opaque 声明: %"name" = type opaque。
|
当 fcount == -1(哨兵)时输出 opaque 声明: %"name" = type opaque。
|
||||||
空结构体(fcount==0, fields==None,无字段类)是完整定义,输出 "= type {}"。
|
空结构体(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:
|
if ty is None or buf is None or size == 0:
|
||||||
return
|
return
|
||||||
@@ -595,7 +607,7 @@ def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
viperlib.snprintf(buf, size, "%%\"%s\" = type opaque", name)
|
viperlib.snprintf(buf, size, "%%\"%s\" = type opaque", name)
|
||||||
else:
|
else:
|
||||||
viperlib.snprintf(buf, size, "%%\"%s\" = type ", name)
|
viperlib.snprintf(buf, size, "%%\"%s\" = type ", name)
|
||||||
_print_struct_body(buf, size, fields, pool)
|
_print_struct_body(buf, size, fields, pool, 0, packed)
|
||||||
case _:
|
case _:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -606,7 +618,7 @@ def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
# 返回 Name 字段(如 "sha1.ClassName"),非 Struct 类型或匿名 Struct 返回 None
|
# 返回 Name 字段(如 "sha1.ClassName"),非 Struct 类型或匿名 Struct 返回 None
|
||||||
# 供 module_add_named_type 检查是否为命名结构体及去重
|
# 供 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"""
|
"""获取命名结构体的名称,非命名结构体返回 None"""
|
||||||
if ty is None:
|
if ty is None:
|
||||||
return None
|
return None
|
||||||
@@ -617,7 +629,7 @@ def get_struct_name(ty: LLVMType | t.CPtr) -> t.CChar | t.CPtr:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_struct_fields(ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
|
def get_struct_fields(ty: rowptr[LLVMType]) -> rowptr[ParamNode]:
|
||||||
"""获取结构体的字段链表(供跨模块重建 Struct 类型用)"""
|
"""获取结构体的字段链表(供跨模块重建 Struct 类型用)"""
|
||||||
if ty is None:
|
if ty is None:
|
||||||
return None
|
return None
|
||||||
@@ -628,7 +640,7 @@ def get_struct_fields(ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_struct_fcount(ty: LLVMType | t.CPtr) -> t.CInt:
|
def get_struct_fcount(ty: rowptr[LLVMType]) -> int:
|
||||||
"""获取结构体的字段数量(供跨模块重建 Struct 类型用)"""
|
"""获取结构体的字段数量(供跨模块重建 Struct 类型用)"""
|
||||||
if ty is None:
|
if ty is None:
|
||||||
return 0
|
return 0
|
||||||
@@ -656,14 +668,14 @@ def get_struct_fcount(ty: LLVMType | t.CPtr) -> t.CInt:
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
DEEPCOPY_MAX_DEPTH: t.CDefine = 64
|
DEEPCOPY_MAX_DEPTH: t.CDefine = 64
|
||||||
|
|
||||||
def DeepCopyType(pool: memhub.MemBuddy | t.CPtr,
|
def DeepCopyType(pool: rowptr[memhub.MemBuddy],
|
||||||
ty: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
|
ty: rowptr[LLVMType]) -> rowptr[LLVMType]:
|
||||||
"""深拷贝 LLVMType 到 stdlib 区(深度限制防自引用递归),失败返回 None"""
|
"""深拷贝 LLVMType 到 stdlib 区(深度限制防自引用递归),失败返回 None"""
|
||||||
return _DeepCopyDepth(pool, ty, 0)
|
return _DeepCopyDepth(pool, ty, 0)
|
||||||
|
|
||||||
|
|
||||||
def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
|
def _DeepCopyDepth(pool: rowptr[memhub.MemBuddy],
|
||||||
ty: LLVMType | t.CPtr, depth: t.CInt) -> LLVMType | t.CPtr:
|
ty: rowptr[LLVMType], depth: int) -> rowptr[LLVMType]:
|
||||||
"""带深度上限的深拷贝实现
|
"""带深度上限的深拷贝实现
|
||||||
|
|
||||||
分配源用传入的 pool 参数(调用方决定):传主 pool 为瞬时拷贝
|
分配源用传入的 pool 参数(调用方决定):传主 pool 为瞬时拷贝
|
||||||
@@ -672,7 +684,7 @@ def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
"""
|
"""
|
||||||
if ty is None:
|
if ty is None:
|
||||||
return 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:
|
if new_ty is None:
|
||||||
return None
|
return None
|
||||||
string.memset(new_ty, 0, LLVMType.__sizeof__())
|
string.memset(new_ty, 0, LLVMType.__sizeof__())
|
||||||
@@ -716,25 +728,28 @@ def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
_DeepCopyParamChain(pool, fields, depth + 1),
|
_DeepCopyParamChain(pool, fields, depth + 1),
|
||||||
fcount, _DeepCopyStr(pool, name)))
|
fcount, _DeepCopyStr(pool, name)))
|
||||||
case _:
|
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 None
|
||||||
return new_ty
|
return new_ty
|
||||||
|
|
||||||
|
|
||||||
def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
|
def _DeepCopyParamChain(pool: rowptr[memhub.MemBuddy],
|
||||||
head: ParamNode | t.CPtr, depth: t.CInt) -> ParamNode | t.CPtr:
|
head: rowptr[ParamNode], depth: int) -> rowptr[ParamNode]:
|
||||||
"""深拷贝 ParamNode 链表到 stdlib"""
|
"""深拷贝 ParamNode 链表到 stdlib"""
|
||||||
if head is None:
|
if head is None:
|
||||||
return None
|
return None
|
||||||
first: ParamNode | t.CPtr = None
|
first: rowptr[ParamNode] = None
|
||||||
prev: ParamNode | t.CPtr = None
|
prev: rowptr[ParamNode] = None
|
||||||
cur: ParamNode | t.CPtr = head
|
cur: rowptr[ParamNode] = head
|
||||||
guard: t.CInt = 0
|
guard: int = 0
|
||||||
while cur is not None:
|
while cur is not None:
|
||||||
guard += 1
|
guard += 1
|
||||||
if guard > 512:
|
if guard > 512:
|
||||||
break
|
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:
|
if node is None:
|
||||||
break
|
break
|
||||||
string.memset(node, 0, PNODE_SIZE)
|
string.memset(node, 0, PNODE_SIZE)
|
||||||
@@ -749,12 +764,12 @@ def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
return first
|
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"""
|
"""深拷贝字符串到 stdlib"""
|
||||||
if s is None:
|
if s is None:
|
||||||
return None
|
return None
|
||||||
slen: t.CSizeT = string.strlen(s)
|
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:
|
if copy is None:
|
||||||
return None
|
return None
|
||||||
string.strcpy(copy, s)
|
string.strcpy(copy, s)
|
||||||
|
|||||||
+31
-31
@@ -19,10 +19,10 @@ from .__types import LLVMType, TypePrint
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class Value(GSListNode[Value]):
|
class Value(GSListNode[Value]):
|
||||||
Ty: LLVMType | t.CPtr # 值的类型
|
Ty: rowptr[LLVMType] # 值的类型
|
||||||
Name: t.CChar | t.CPtr # SSA 名("%0"/"%result")或常量文本("42"/"1.5e+00")
|
Name: str # SSA 名("%0"/"%result")或常量文本("42"/"1.5e+00")
|
||||||
IsConst: t.CInt # 1=常量字面量, 0=SSA 临时值
|
IsConst: int # 1=常量字面量, 0=SSA 临时值
|
||||||
IntVal: t.CInt64T # 整数常量值(当 IsConst=1 时使用)
|
IntVal: int64 # 整数常量值(当 IsConst=1 时使用)
|
||||||
FloatVal: t.CDouble # 浮点常量值(当 IsConst=1 且 Ty 为 Float 时使用)
|
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 硬编码大小: Next(8) + Ty(8) + Name(8) + IsConst(4) + IntVal(8) + FloatVal(8) = 48 字节
|
||||||
VALUE_SIZE: t.CDefine = 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"""
|
"""从 mpool 分配一个零初始化的 Value"""
|
||||||
ptr: Value | t.CPtr = pool.alloc(VALUE_SIZE)
|
ptr: rowptr[Value] = pool.alloc(VALUE_SIZE)
|
||||||
if ptr:
|
if ptr:
|
||||||
string.memset(ptr, 0, VALUE_SIZE)
|
string.memset(ptr, 0, VALUE_SIZE)
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
def ConstInt(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
|
||||||
val: t.CInt64T, name: t.CChar | t.CPtr) -> Value | t.CPtr:
|
val: int64, name: str) -> rowptr[Value]:
|
||||||
"""创建整数常量值
|
"""创建整数常量值
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@@ -49,7 +49,7 @@ def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
val: 整数值
|
val: 整数值
|
||||||
name: 常量文本(如 "42"),由调用方提供
|
name: 常量文本(如 "42"),由调用方提供
|
||||||
"""
|
"""
|
||||||
v: Value | t.CPtr = new_value(pool)
|
v: rowptr[Value] = new_value(pool)
|
||||||
if v is None: return None
|
if v is None: return None
|
||||||
v.Ty = ty
|
v.Ty = ty
|
||||||
v.Name = name
|
v.Name = name
|
||||||
@@ -58,10 +58,10 @@ def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def ConstNull(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
def ConstNull(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
|
||||||
name: t.CChar | t.CPtr) -> Value | t.CPtr:
|
name: str) -> rowptr[Value]:
|
||||||
"""创建 null 指针常量"""
|
"""创建 null 指针常量"""
|
||||||
v: Value | t.CPtr = new_value(pool)
|
v: rowptr[Value] = new_value(pool)
|
||||||
if v is None: return None
|
if v is None: return None
|
||||||
v.Ty = ty
|
v.Ty = ty
|
||||||
v.Name = name
|
v.Name = name
|
||||||
@@ -70,9 +70,9 @@ def ConstNull(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
return v
|
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 常量(零初始化聚合类型:结构体/数组)"""
|
"""创建 zeroinitializer 常量(零初始化聚合类型:结构体/数组)"""
|
||||||
v: Value | t.CPtr = new_value(pool)
|
v: rowptr[Value] = new_value(pool)
|
||||||
if v is None: return None
|
if v is None: return None
|
||||||
v.Ty = ty
|
v.Ty = ty
|
||||||
v.Name = "zeroinitializer"
|
v.Name = "zeroinitializer"
|
||||||
@@ -81,8 +81,8 @@ def ConstZero(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Value |
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
def ConstFloat(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
|
||||||
val: t.CDouble) -> Value | t.CPtr:
|
val: t.CDouble) -> rowptr[Value]:
|
||||||
"""创建浮点常量值
|
"""创建浮点常量值
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@@ -90,7 +90,7 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
val: 浮点数值
|
val: 浮点数值
|
||||||
名字自动格式化为 LLVM IR 科学计数法文本(如 "1.500000e+00")。
|
名字自动格式化为 LLVM IR 科学计数法文本(如 "1.500000e+00")。
|
||||||
"""
|
"""
|
||||||
v: Value | t.CPtr = new_value(pool)
|
v: rowptr[Value] = new_value(pool)
|
||||||
if v is None: return None
|
if v is None: return None
|
||||||
v.Ty = ty
|
v.Ty = ty
|
||||||
v.IsConst = 1
|
v.IsConst = 1
|
||||||
@@ -102,13 +102,13 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
# 导致 add_scalar[0]==11 等浮点常量比较失败)。位模式无精度损失。
|
# 导致 add_scalar[0]==11 等浮点常量比较失败)。位模式无精度损失。
|
||||||
# 原 %e 默认 6 位小数还会截断精度(3.1415926535897931 -> 3.141593e+00)。
|
# 原 %e 默认 6 位小数还会截断精度(3.1415926535897931 -> 3.141593e+00)。
|
||||||
# 用 CRT stdio.snprintf: viperlib 自实现 %g 有小数位反转 bug。
|
# 用 CRT stdio.snprintf: viperlib 自实现 %g 有小数位反转 bug。
|
||||||
f_bits: t.CInt = 64
|
f_bits: int = 64
|
||||||
match ty:
|
match ty:
|
||||||
case LLVMType.Float(ftb):
|
case LLVMType.Float(ftb):
|
||||||
f_bits = ftb
|
f_bits = ftb
|
||||||
fv_bits: t.CUInt64T = 0
|
fv_bits: t.CUInt64T = 0
|
||||||
c.Load(c.Addr(fv_bits), c.Addr(val))
|
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 name_buf is not None:
|
||||||
if f_bits == 32:
|
if f_bits == 32:
|
||||||
stdio.snprintf(name_buf, 32, "0x%08x", t.CUInt32T(fv_bits))
|
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
|
return v
|
||||||
|
|
||||||
|
|
||||||
def SSAValue(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
def SSAValue(pool: rowptr[memhub.MemBuddy], ty: rowptr[LLVMType],
|
||||||
name: t.CChar | t.CPtr) -> Value | t.CPtr:
|
name: str) -> rowptr[Value]:
|
||||||
"""创建 SSA 临时值
|
"""创建 SSA 临时值
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
ty: 值类型
|
ty: 值类型
|
||||||
name: SSA 名(如 "%0"/"%result"),由调用方提供
|
name: SSA 名(如 "%0"/"%result"),由调用方提供
|
||||||
"""
|
"""
|
||||||
v: Value | t.CPtr = new_value(pool)
|
v: rowptr[Value] = new_value(pool)
|
||||||
if v is None: return None
|
if v is None: return None
|
||||||
v.Ty = ty
|
v.Ty = ty
|
||||||
v.Name = name
|
v.Name = name
|
||||||
@@ -142,8 +142,8 @@ def SSAValue(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
|
|||||||
# ConstInt(i32, 42, "42") -> "i32 42"
|
# ConstInt(i32, 42, "42") -> "i32 42"
|
||||||
# SSAValue(i32, "%0") -> "i32 %0"
|
# SSAValue(i32, "%0") -> "i32 %0"
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def ValuePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
def ValuePrint(buf: str, size: t.CSizeT,
|
||||||
val: Value | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
|
val: rowptr[Value], pool: rowptr[memhub.MemBuddy]):
|
||||||
"""将值 val 序列化为 IR 文本写入 buf
|
"""将值 val 序列化为 IR 文本写入 buf
|
||||||
|
|
||||||
格式: <type> <name>
|
格式: <type> <name>
|
||||||
@@ -171,42 +171,42 @@ def ValuePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
|
|||||||
# 导致 TransPyC 静默跳过字段访问(不生成 GEP,不报错)。
|
# 导致 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:
|
if val is None:
|
||||||
return None
|
return None
|
||||||
return val.Ty
|
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:
|
if val is None:
|
||||||
return None
|
return None
|
||||||
return val.Next
|
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:
|
if val is None:
|
||||||
return
|
return
|
||||||
val.Ty = ty
|
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:
|
if val is None:
|
||||||
return
|
return
|
||||||
val.Next = nxt
|
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:
|
if val is None:
|
||||||
return
|
return
|
||||||
val.Name = name
|
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:
|
if val is None:
|
||||||
return
|
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 末尾"""
|
"""将 src 追加到 dst 末尾"""
|
||||||
if dst is None or src is None: return
|
if dst is None or src is None: return
|
||||||
dlen: t.CSizeT = string.strlen(dst)
|
dlen: t.CSizeT = string.strlen(dst)
|
||||||
|
|||||||
+67
-67
@@ -33,33 +33,33 @@ VERIFY_ERR_PHI_NOT_FIRST: t.CDefine = 4
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
@t.NoVTable
|
@t.NoVTable
|
||||||
class NameEntry(GSListNode[NameEntry]):
|
class NameEntry(GSListNode[NameEntry]):
|
||||||
Name: t.CChar | t.CPtr # SSA 名(如 "%0"/"%result")
|
Name: str # SSA 名(如 "%0"/"%result")
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# VerifyResult: 验证结果
|
# VerifyResult: 验证结果
|
||||||
# ============================================================
|
# ============================================================
|
||||||
class VerifyResult:
|
class VerifyResult:
|
||||||
ErrorCount: t.CInt # 错误总数
|
ErrorCount: int # 错误总数
|
||||||
WarningCount: t.CInt # 警告总数
|
WarningCount: int # 警告总数
|
||||||
ErrorCode: t.CInt # 第一个错误码
|
ErrorCode: int # 第一个错误码
|
||||||
ErrorBuf: t.CChar | t.CPtr # 错误消息缓冲区
|
ErrorBuf: str # 错误消息缓冲区
|
||||||
ErrorBufSize: t.CSizeT # 缓冲区大小
|
ErrorBufSize: t.CSizeT # 缓冲区大小
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# 辅助函数
|
# 辅助函数
|
||||||
# ============================================================
|
# ============================================================
|
||||||
def _new_verify_result(pool: memhub.MemBuddy | t.CPtr,
|
def _new_verify_result(pool: rowptr[memhub.MemBuddy],
|
||||||
buf_size: t.CSizeT) -> VerifyResult | t.CPtr:
|
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
|
if ptr is None: return None
|
||||||
string.memset(ptr, 0, VerifyResult.__sizeof__())
|
string.memset(ptr, 0, VerifyResult.__sizeof__())
|
||||||
ptr.ErrorCount = 0
|
ptr.ErrorCount = 0
|
||||||
ptr.WarningCount = 0
|
ptr.WarningCount = 0
|
||||||
ptr.ErrorCode = VERIFY_OK
|
ptr.ErrorCode = VERIFY_OK
|
||||||
buf: t.CChar | t.CPtr = pool.alloc(buf_size)
|
buf: str = pool.alloc(buf_size)
|
||||||
if buf is not None:
|
if buf is not None:
|
||||||
buf[0] = '\0'
|
buf[0] = '\0'
|
||||||
ptr.ErrorBuf = buf
|
ptr.ErrorBuf = buf
|
||||||
@@ -67,7 +67,7 @@ def _new_verify_result(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
return ptr
|
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
|
if result is None: return
|
||||||
result.ErrorCount += 1
|
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_dst: t.CUInt64T = 0
|
||||||
_g_last_pos: t.CSizeT = 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 末尾"""
|
"""将 src 追加到 dst 末尾"""
|
||||||
global _g_last_dst, _g_last_pos
|
global _g_last_dst, _g_last_pos
|
||||||
if dst is None or src is None: return
|
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 名表操作
|
# 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
|
if gsl is None: return None
|
||||||
string.memset(gsl, 0, 24)
|
string.memset(gsl, 0, 24)
|
||||||
return gsl
|
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 字节
|
# NameEntry 硬编码大小: Next(8) + Name(8) = 16 字节
|
||||||
NENTRY_SIZE: t.CDefine = 16
|
NENTRY_SIZE: t.CDefine = 16
|
||||||
|
|
||||||
def _name_table_add(table: GSList[NameEntry] | t.CPtr,
|
def _name_table_add(table: rowptr[GSList[NameEntry]],
|
||||||
pool: memhub.MemBuddy | t.CPtr,
|
pool: rowptr[memhub.MemBuddy],
|
||||||
name: t.CChar | t.CPtr) -> t.CInt:
|
name: str) -> int:
|
||||||
"""添加名到表。返回 1=重复, 0=成功添加"""
|
"""添加名到表。返回 1=重复, 0=成功添加"""
|
||||||
if table is None or name is None: return 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:
|
while cur is not None:
|
||||||
if string.strcmp(cur.Name, name) == 0:
|
if string.strcmp(cur.Name, name) == 0:
|
||||||
return 1
|
return 1
|
||||||
cur = cur.Next
|
cur = cur.Next
|
||||||
# 添加新条目
|
# 添加新条目
|
||||||
entry: NameEntry | t.CPtr = pool.alloc(NENTRY_SIZE)
|
entry: rowptr[NameEntry] = pool.alloc(NENTRY_SIZE)
|
||||||
if entry is None: return 0
|
if entry is None: return 0
|
||||||
string.memset(entry, 0, NENTRY_SIZE)
|
string.memset(entry, 0, NENTRY_SIZE)
|
||||||
entry.Name = name
|
entry.Name = name
|
||||||
@@ -146,11 +146,11 @@ def _name_table_add(table: GSList[NameEntry] | t.CPtr,
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _name_table_contains(table: GSList[NameEntry] | t.CPtr,
|
def _name_table_contains(table: rowptr[GSList[NameEntry]],
|
||||||
name: t.CChar | t.CPtr) -> t.CInt:
|
name: str) -> int:
|
||||||
"""检查名是否在表中。返回 1=存在, 0=不存在"""
|
"""检查名是否在表中。返回 1=存在, 0=不存在"""
|
||||||
if table is None or name is None: return 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:
|
while cur is not None:
|
||||||
if string.strcmp(cur.Name, name) == 0:
|
if string.strcmp(cur.Name, name) == 0:
|
||||||
return 1
|
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._]"""
|
"""判断字符是否为 SSA 名字符 [a-zA-Z0-9._]"""
|
||||||
if ch >= 'a' and ch <= 'z': return 1
|
if ch >= 'a' and ch <= 'z': return 1
|
||||||
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
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
|
def _extract_def_name(pool: rowptr[memhub.MemBuddy],
|
||||||
text: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
|
text: str) -> str:
|
||||||
"""从定义行提取被定义的 SSA 名。
|
"""从定义行提取被定义的 SSA 名。
|
||||||
|
|
||||||
定义行格式: "%<name> = <instruction>"
|
定义行格式: "%<name> = <instruction>"
|
||||||
@@ -180,14 +180,14 @@ def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
if text is None: return None
|
if text is None: return None
|
||||||
if text[0] != '%': return None
|
if text[0] != '%': return None
|
||||||
# 扫描 " = " 模式
|
# 扫描 " = " 模式
|
||||||
i: t.CInt = 1
|
i: int = 1
|
||||||
while text[i] != '\0':
|
while text[i] != '\0':
|
||||||
if text[i] == ' ' and text[i + 1] == '=' and text[i + 2] == ' ':
|
if text[i] == ' ' and text[i + 1] == '=' and text[i + 2] == ' ':
|
||||||
# 找到 " = " 在位置 i
|
# 找到 " = " 在位置 i
|
||||||
name_len: t.CInt = i
|
name_len: int = i
|
||||||
name: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
name: str = pool.alloc(name_len + 1)
|
||||||
if name is None: return None
|
if name is None: return None
|
||||||
j: t.CInt = 0
|
j: int = 0
|
||||||
while j < name_len:
|
while j < name_len:
|
||||||
name[j] = text[j]
|
name[j] = text[j]
|
||||||
j += 1
|
j += 1
|
||||||
@@ -197,7 +197,7 @@ def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
return None
|
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 text is None: return 0
|
||||||
if string.strncmp(text, "ret", 3) == 0: return 1
|
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
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _is_phi(text: t.CChar | t.CPtr) -> t.CInt:
|
def _is_phi(text: str) -> int:
|
||||||
"""判断文本是否为 phi 指令"""
|
"""判断文本是否为 phi 指令"""
|
||||||
if text is None: return 0
|
if text is None: return 0
|
||||||
if string.strstr(text, " = phi ") is not None: return 1
|
if string.strstr(text, " = phi ") is not None: return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _check_uses_in_line(table: GSList[NameEntry] | t.CPtr,
|
def _check_uses_in_line(table: rowptr[GSList[NameEntry]],
|
||||||
text: t.CChar | t.CPtr,
|
text: str,
|
||||||
def_name: t.CChar | t.CPtr) -> t.CInt:
|
def_name: str) -> int:
|
||||||
"""检查行中所有 SSA 名使用是否已定义。
|
"""检查行中所有 SSA 名使用是否已定义。
|
||||||
|
|
||||||
跳过 def_name(定义位置的名字)。
|
跳过 def_name(定义位置的名字)。
|
||||||
返回未定义使用数量。
|
返回未定义使用数量。
|
||||||
"""
|
"""
|
||||||
if text is None: return 0
|
if text is None: return 0
|
||||||
i: t.CInt = 0
|
i: int = 0
|
||||||
undef_count: t.CInt = 0
|
undef_count: int = 0
|
||||||
while text[i] != '\0':
|
while text[i] != '\0':
|
||||||
if text[i] == '%':
|
if text[i] == '%':
|
||||||
# 提取名
|
# 提取名
|
||||||
name_start: t.CInt = i
|
name_start: int = i
|
||||||
i += 1
|
i += 1
|
||||||
while text[i] != '\0' and _is_char_name(text[i]) == 1:
|
while text[i] != '\0' and _is_char_name(text[i]) == 1:
|
||||||
i += 1
|
i += 1
|
||||||
name_len: t.CInt = i - name_start
|
name_len: int = i - name_start
|
||||||
if name_len > 1:
|
if name_len > 1:
|
||||||
# 构建临时名串进行比较
|
# 构建临时名串进行比较
|
||||||
# 由于无法在栈上分配,用 strstr 进行简化检查
|
# 由于无法在栈上分配,用 strstr 进行简化检查
|
||||||
@@ -251,13 +251,13 @@ def _check_uses_in_line(table: GSList[NameEntry] | t.CPtr,
|
|||||||
return undef_count
|
return undef_count
|
||||||
|
|
||||||
|
|
||||||
def _name_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
|
def _name_matches_at(text: str, start: int, length: int,
|
||||||
table: GSList[NameEntry] | t.CPtr) -> t.CInt:
|
table: rowptr[GSList[NameEntry]]) -> int:
|
||||||
"""检查 text[start:start+length] 是否匹配名表中的某个条目。
|
"""检查 text[start:start+length] 是否匹配名表中的某个条目。
|
||||||
返回 1=匹配, 0=不匹配
|
返回 1=匹配, 0=不匹配
|
||||||
"""
|
"""
|
||||||
if table is None: return 0
|
if table is None: return 0
|
||||||
cur: NameEntry | t.CPtr = table.Head
|
cur: rowptr[NameEntry] = table.Head
|
||||||
while cur is not None:
|
while cur is not None:
|
||||||
if cur.Name is not None:
|
if cur.Name is not None:
|
||||||
if _str_matches_at(text, start, length, cur.Name) == 1:
|
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
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _str_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
|
def _str_matches_at(text: str, start: int, length: int,
|
||||||
target: t.CChar | t.CPtr) -> t.CInt:
|
target: str) -> int:
|
||||||
"""检查 text[start:start+length] 是否等于 target 字符串。
|
"""检查 text[start:start+length] 是否等于 target 字符串。
|
||||||
返回 1=匹配, 0=不匹配
|
返回 1=匹配, 0=不匹配
|
||||||
"""
|
"""
|
||||||
if text is None or target is None: return 0
|
if text is None or target is None: return 0
|
||||||
# 检查 target 长度
|
# 检查 target 长度
|
||||||
target_len: t.CInt = string.strlen(target)
|
target_len: t.CSizeT = string.strlen(target)
|
||||||
if target_len != length: return 0
|
if target_len != length: return 0
|
||||||
i: t.CInt = 0
|
i: t.CSizeT = 0
|
||||||
while i < length:
|
while i < length:
|
||||||
if text[start + i] != target[i]: return 0
|
if text[start + i] != target[i]: return 0
|
||||||
i += 1
|
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,
|
def verify_function(pool: rowptr[memhub.MemBuddy],
|
||||||
func: Function | t.CPtr,
|
func: rowptr[Function],
|
||||||
result: VerifyResult | t.CPtr) -> t.CInt:
|
result: rowptr[VerifyResult]) -> int:
|
||||||
"""验证函数的 SSA 正确性。
|
"""验证函数的 SSA 正确性。
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@@ -300,11 +300,11 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
if func is None or result is None: return 1
|
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
|
if name_table is None: return 1
|
||||||
|
|
||||||
# 1. 将函数参数加入名表(参数是已定义的)
|
# 1. 将函数参数加入名表(参数是已定义的)
|
||||||
param: Param | t.CPtr = None
|
param: rowptr[Param] = None
|
||||||
if func.Params is not None:
|
if func.Params is not None:
|
||||||
param = func.Params.Head
|
param = func.Params.Head
|
||||||
while param is not None:
|
while param is not None:
|
||||||
@@ -313,13 +313,13 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
param = param.Next
|
param = param.Next
|
||||||
|
|
||||||
# 1b. 将基本块名加入名表(块标签如 %then 是 br/phi 的合法引用目标)
|
# 1b. 将基本块名加入名表(块标签如 %then 是 br/phi 的合法引用目标)
|
||||||
blk_iter: BasicBlock | t.CPtr = None
|
blk_iter: rowptr[BasicBlock] = None
|
||||||
if func.Blocks is not None:
|
if func.Blocks is not None:
|
||||||
blk_iter = func.Blocks.Head
|
blk_iter = func.Blocks.Head
|
||||||
while blk_iter is not None:
|
while blk_iter is not None:
|
||||||
if blk_iter.Name is not None:
|
if blk_iter.Name is not None:
|
||||||
blk_name_len: t.CSizeT = string.strlen(blk_iter.Name)
|
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:
|
if blk_ref is not None:
|
||||||
# 构造 "%<name>" 字符串
|
# 构造 "%<name>" 字符串
|
||||||
blk_ref[0] = '%'
|
blk_ref[0] = '%'
|
||||||
@@ -332,15 +332,15 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
blk_iter = blk_iter.Next
|
blk_iter = blk_iter.Next
|
||||||
|
|
||||||
# 2. 遍历所有块
|
# 2. 遍历所有块
|
||||||
blk: BasicBlock | t.CPtr = None
|
blk: rowptr[BasicBlock] = None
|
||||||
if func.Blocks is not None:
|
if func.Blocks is not None:
|
||||||
blk = func.Blocks.Head
|
blk = func.Blocks.Head
|
||||||
while blk is not None:
|
while blk is not None:
|
||||||
# 检查终止指令
|
# 检查终止指令
|
||||||
if blk.IsTerminated == 0:
|
if blk.IsTerminated == 0:
|
||||||
# 进一步检查最后一行是否为终止指令
|
# 进一步检查最后一行是否为终止指令
|
||||||
has_term: t.CInt = 0
|
has_term: int = 0
|
||||||
line_check: Line | t.CPtr = None
|
line_check: rowptr[Line] = None
|
||||||
if blk.Lines is not None:
|
if blk.Lines is not None:
|
||||||
line_check = blk.Lines.Head
|
line_check = blk.Lines.Head
|
||||||
while line_check is not None:
|
while line_check is not None:
|
||||||
@@ -349,27 +349,27 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
has_term = 1
|
has_term = 1
|
||||||
line_check = line_check.Next
|
line_check = line_check.Next
|
||||||
if has_term == 0:
|
if has_term == 0:
|
||||||
blk_name: t.CChar | t.CPtr = "<unnamed>"
|
blk_name: str = "<unnamed>"
|
||||||
if blk.Name is not None:
|
if blk.Name is not None:
|
||||||
blk_name = blk.Name
|
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:
|
if err_buf is not None:
|
||||||
viperlib.snprintf(err_buf, 128, "ERROR: block '%s' missing terminator", blk_name)
|
viperlib.snprintf(err_buf, 128, "ERROR: block '%s' missing terminator", blk_name)
|
||||||
_report_error(result, VERIFY_ERR_NO_TERMINATOR, err_buf)
|
_report_error(result, VERIFY_ERR_NO_TERMINATOR, err_buf)
|
||||||
|
|
||||||
# 遍历块内指令行
|
# 遍历块内指令行
|
||||||
seen_non_phi: t.CInt = 0
|
seen_non_phi: int = 0
|
||||||
line: Line | t.CPtr = None
|
line: rowptr[Line] = None
|
||||||
if blk.Lines is not None:
|
if blk.Lines is not None:
|
||||||
line = blk.Lines.Head
|
line = blk.Lines.Head
|
||||||
while line is not None:
|
while line is not None:
|
||||||
if line.Buf is not None:
|
if line.Buf is not None:
|
||||||
text: t.CChar | t.CPtr = line.Buf
|
text: str = line.Buf
|
||||||
|
|
||||||
# 检查 phi 位置
|
# 检查 phi 位置
|
||||||
if _is_phi(text) == 1:
|
if _is_phi(text) == 1:
|
||||||
if seen_non_phi == 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:
|
if phi_err is not None:
|
||||||
viperlib.snprintf(phi_err, 128, "ERROR: phi not at block start")
|
viperlib.snprintf(phi_err, 128, "ERROR: phi not at block start")
|
||||||
_report_error(result, VERIFY_ERR_PHI_NOT_FIRST, phi_err)
|
_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
|
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:
|
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:
|
if dup == 1:
|
||||||
dup_err: t.CChar | t.CPtr = pool.alloc(128)
|
dup_err: str = pool.alloc(128)
|
||||||
if dup_err is not None:
|
if dup_err is not None:
|
||||||
viperlib.snprintf(dup_err, 128, "ERROR: duplicate definition '%s'", def_name)
|
viperlib.snprintf(dup_err, 128, "ERROR: duplicate definition '%s'", def_name)
|
||||||
_report_error(result, VERIFY_ERR_DUPLICATE_DEF, dup_err)
|
_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:
|
if undef > 0:
|
||||||
use_err: t.CChar | t.CPtr = pool.alloc(128)
|
use_err: str = pool.alloc(128)
|
||||||
if use_err is not None:
|
if use_err is not None:
|
||||||
viperlib.snprintf(use_err, 128, "ERROR: %d undefined use(s) in: %s", undef, text)
|
viperlib.snprintf(use_err, 128, "ERROR: %d undefined use(s) in: %s", undef, text)
|
||||||
_report_error(result, VERIFY_ERR_UNDEFINED_USE, use_err)
|
_report_error(result, VERIFY_ERR_UNDEFINED_USE, use_err)
|
||||||
@@ -404,13 +404,13 @@ def verify_function(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
return result.ErrorCount
|
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 正确性。
|
"""验证模块中所有函数的 SSA 正确性。
|
||||||
|
|
||||||
返回: 错误总数
|
返回: 错误总数
|
||||||
"""
|
"""
|
||||||
if mod is None or result is None: return 1
|
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:
|
while func is not None:
|
||||||
if func.IsDeclared == 0:
|
if func.IsDeclared == 0:
|
||||||
# 只验证有函数体的定义,跳过声明
|
# 只验证有函数体的定义,跳过声明
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ import stdlib
|
|||||||
MEMHUB_ALIGN: t.CDefine = 8
|
MEMHUB_ALIGN: t.CDefine = 8
|
||||||
|
|
||||||
# MemSlab bitmap constants
|
# MemSlab bitmap constants
|
||||||
MEMSLAB_MIN_BLOCK: t.CDefine = 16
|
MEMSLAB_MIN_BLOCK: t.CDefine = 16
|
||||||
MEMSLAB_BITMAP_BYTES: t.CDefine = 256
|
MEMSLAB_BITMAP_BYTES: t.CDefine = 256
|
||||||
|
|
||||||
# MemBuddy buddy constants
|
# MemBuddy buddy constants
|
||||||
MEMBUDDY_MIN_BLOCK: t.CDefine = 32
|
MEMBUDDY_MIN_BLOCK: t.CDefine = 32
|
||||||
MEMBUDDY_MAX_ORDERS: t.CDefine = 32
|
MEMBUDDY_MAX_ORDERS: t.CDefine = 32
|
||||||
MEMBUDDY_HEADER_SIZE: t.CDefine = 8
|
MEMBUDDY_HEADER_SIZE: t.CDefine = 8
|
||||||
# 块尾 canary:alloc 时在块尾(用户数据区之外)写 8 字节哨兵,
|
# 块尾 canary:alloc 时在块尾(用户数据区之外)写 8 字节哨兵,
|
||||||
# check_alive_blocks 校验——越界写穿数据区会破坏 canary,把
|
# check_alive_blocks 校验——越界写穿数据区会破坏 canary,把
|
||||||
@@ -34,7 +34,7 @@ MEMBUDDY_CANARY: t.CDefine = 8
|
|||||||
# alloc 时把用户数据区填充 0xCD 哨兵。若对象初始化(list.__init__ 等)
|
# alloc 时把用户数据区填充 0xCD 哨兵。若对象初始化(list.__init__ 等)
|
||||||
# 未执行,其字段保持 0xCDCD...,CTORDBG/VDBG 打印字段时一眼可辨
|
# 未执行,其字段保持 0xCDCD...,CTORDBG/VDBG 打印字段时一眼可辨
|
||||||
# "未初始化(0xCDCD)" 与 "被覆盖(其他值)"。0=关闭(性能),1=开启。
|
# "未初始化(0xCDCD)" 与 "被覆盖(其他值)"。0=关闭(性能),1=开启。
|
||||||
MEMBUDDY_FILL_GUARD: t.CDefine = 1
|
MEMBUDDY_FILL_GUARD: t.CDefine = 1
|
||||||
MEMBUDDY_FILL_PATTERN: t.CDefine = 0xCD
|
MEMBUDDY_FILL_PATTERN: t.CDefine = 0xCD
|
||||||
|
|
||||||
# [DET] 分配检测(alloc 前后 2 字节 0xCDCD 标记 + 记录表探测越界写):
|
# [DET] 分配检测(alloc 前后 2 字节 0xCDCD 标记 + 记录表探测越界写):
|
||||||
@@ -51,7 +51,15 @@ MEMBUDDY_DET_RECORD_SIZE: t.CDefine = 33554432
|
|||||||
# 记录追加本身 O(1) 不受影响;损坏是持久性的,不依赖即时扫描,采样
|
# 记录追加本身 O(1) 不受影响;损坏是持久性的,不依赖即时扫描,采样
|
||||||
# 不损失检测能力——2M 次 alloc 若每次全表 O(n) 扫描 = O(n²) 太慢
|
# 不损失检测能力——2M 次 alloc 若每次全表 O(n) 扫描 = O(n²) 太慢
|
||||||
# (用户反馈 detection 模式过慢),采样把扫描次数降为 1/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:
|
def _canary_pattern() -> t.CUInt64T:
|
||||||
@@ -88,30 +96,30 @@ def _block_size_at_order(order: t.CInt) -> t.CSizeT:
|
|||||||
@t.CVTable
|
@t.CVTable
|
||||||
class MemManager:
|
class MemManager:
|
||||||
__provides__: list[str] = ['__memmgr__']
|
__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
|
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.base = base
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
# === Virtual functions (overridden by subclasses) ===
|
# === 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
|
# Default: allocation not supported
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def free(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
|
def free(self, ptr: t.CPtr) -> int:
|
||||||
# Default: no operation
|
# Default: no operation
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def reset(self) -> t.CInt:
|
def reset(self) -> int:
|
||||||
# Default: no operation
|
# Default: no operation
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# === Concrete methods (invoke virtual functions for automatic polymorphic dispatch) ===
|
# === 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
|
total: t.CSizeT = count * size
|
||||||
ptr: t.CVoid | t.CPtr = self.alloc(total)
|
ptr: t.CVoid | t.CPtr = self.alloc(total)
|
||||||
if ptr is not None:
|
if ptr is not None:
|
||||||
@@ -418,16 +426,18 @@ class MemBuddy(MemManager):
|
|||||||
rem -= blk
|
rem -= blk
|
||||||
self.usable_size = used_area
|
self.usable_size = used_area
|
||||||
|
|
||||||
# [DET] 分配检测记录区:stdlib.malloc 独立分配(不占用 buddy 区,
|
# 分配记录区:stdlib.malloc 独立分配(不占用 buddy 区,
|
||||||
# 与 chk_stack 同策略)。容量 = detection_size // 16(每条 {ptr,size})。
|
# 与 chk_stack 同策略)。容量 = detection_size // 16(每条 {ptr,size})。
|
||||||
if detection != 0:
|
# 2026-09-04:记录+重叠检测从 detection 解耦——非 detection 也分配
|
||||||
det_arena: t.CVoid | t.CPtr = t.CVoid(
|
# 记录区并启用同地址重复分配检测(不做前后标记、不改 alloc 布局),
|
||||||
stdlib.malloc(self.detection_size), t.CPtr)
|
# 定位 free-list/重复分配类损坏(memhub 翻译早期容器 Count 槽被写坏)。
|
||||||
if det_arena is not None:
|
det_arena: t.CVoid | t.CPtr = t.CVoid(
|
||||||
self._det_arena = det_arena
|
stdlib.malloc(self.detection_size), t.CPtr)
|
||||||
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(det_arena, t.CPtr))
|
if det_arena is not None:
|
||||||
self._det_cap = self.detection_size // 16
|
self._det_arena = det_arena
|
||||||
self._det_count = 0
|
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 ===
|
# === Checkpoint support ===
|
||||||
|
|
||||||
@@ -487,7 +497,10 @@ class MemBuddy(MemManager):
|
|||||||
# free 只置标志不删),截断 chk_depth 必须同步截断 _det_count,
|
# free 只置标志不删),截断 chk_depth 必须同步截断 _det_count,
|
||||||
# 否则 reset 后旧记录仍标 active → 下一轮 alloc 复用同一块被
|
# 否则 reset 后旧记录仍标 active → 下一轮 alloc 复用同一块被
|
||||||
# 误报为"分配重叠/越界写"(SlotsBugTest 7B buf + 72B Token 误报根因)。
|
# 误报为"分配重叠/越界写"(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._det_count = mark
|
||||||
self._unlock()
|
self._unlock()
|
||||||
|
|
||||||
@@ -668,54 +681,80 @@ class MemBuddy(MemManager):
|
|||||||
if self.chk_depth < self.chk_cap:
|
if self.chk_depth < self.chk_cap:
|
||||||
self.chk_stack[self.chk_depth] = t.CUInt64T(block)
|
self.chk_stack[self.chk_depth] = t.CUInt64T(block)
|
||||||
self.chk_depth += 1
|
self.chk_depth += 1
|
||||||
if result is not None and self.detection != 0:
|
if result is not None and self._det_records is not None:
|
||||||
# [DET] 布局 [0xCDCD][请求大小内存][0xCDCD]:返回指针 = 用户区 + 2
|
|
||||||
# (前标记之后);记录 {返回 ptr, size} 到独立记录区;随后探测全部
|
|
||||||
# 存活块的后标记——被破坏 = 越界写,立即汇报并终止。
|
|
||||||
base_ret_d: t.CUInt64T = t.CUInt64T(result)
|
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))
|
# 返回指针(detection 布局下 = 用户区 + 2,前标记之后)
|
||||||
m_f_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
|
rec_ptr_d: t.CUInt64T = base_ret_d
|
||||||
tail_d: t.CUInt64T = base_ret_d + 2 + t.CUInt64T(size)
|
if self.detection != 0:
|
||||||
m_t_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(tail_d, t.CPtr))
|
# [DET] 布局 [0xCDCD][请求大小内存][0xCDCD]:返回指针 = 用户区 + 2
|
||||||
m_t_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
|
# (前标记之后);记录 {返回 ptr, size} 到独立记录区;随后探测全部
|
||||||
if self._det_records is not None:
|
# 存活块的后标记——被破坏 = 越界写,立即汇报并终止。
|
||||||
# 采样:每 MEMBUDDY_DET_PROBE_PERIOD 次 alloc 做一次全表扫描
|
m_f_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(base_ret_d, t.CPtr))
|
||||||
# (分配重叠 + 探测),其余只追加记录(O(1))。损坏是持久性的,
|
m_f_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
|
||||||
# 不依赖即时扫描——2M 次 alloc 若每次全表 O(n) = O(n²) 太慢
|
tail_d: t.CUInt64T = base_ret_d + 2 + t.CUInt64T(size)
|
||||||
# (用户反馈 detection 模式过慢),采样把扫描降为 O(n²/PERIOD)。
|
m_t_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(tail_d, t.CPtr))
|
||||||
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
|
m_t_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
|
||||||
# 分配重叠即时检测:新块地址是否已在 active 记录(同一块重复
|
rec_ptr_d = base_ret_d + 2
|
||||||
# 分配实锤——SlotsBugTest 7B buf 与 72B Token 同 ptr、cargs
|
# 采样:每 MEMBUDDY_DET_PROBE_PERIOD 次 alloc 做一次全表扫描
|
||||||
# 只写 0/40 根因)。重叠 = MemBuddy free list 损坏(active 块
|
# (分配重叠 + 探测),其余只追加记录(O(1))。损坏是持久性的,
|
||||||
# 混入 free list),在第一次重叠处拦截并打印两个 size。
|
# 不依赖即时扫描——2M 次 alloc 若每次全表 O(n) = O(n²) 太慢
|
||||||
ff_d: t.CUInt64T = t.CUInt64T(1) << 63
|
# (用户反馈 detection 模式过慢),采样把扫描降为 O(n²/PERIOD)。
|
||||||
dup_i: t.CSizeT = 0
|
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
|
||||||
while dup_i < self._det_count:
|
# 分配重叠即时检测:新块地址是否已在 active 记录(同一块重复
|
||||||
drp: t.CUInt64T = self._det_records[dup_i * 2]
|
# 分配实锤——SlotsBugTest 7B buf 与 72B Token 同 ptr、cargs
|
||||||
drs: t.CUInt64T = self._det_records[dup_i * 2 + 1]
|
# 只写 0/40 根因)。重叠 = MemBuddy free list 损坏(active 块
|
||||||
if drp == base_ret_d + 2 and (drs & ff_d) == 0:
|
# 混入 free list),在第一次重叠处拦截并打印两个 size。
|
||||||
stdio.printf("[DET] 分配重叠: 新alloc(size=%llu)与记录[%zu](sz=%llu)同地址 ptr=%llu(同一块重复分配,free list 损坏)\n",
|
ff_d: t.CUInt64T = t.CUInt64T(1) << 63
|
||||||
t.CUInt64T(size), dup_i, drs & (ff_d - 1), base_ret_d + 2)
|
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)
|
stdlib.exit(1)
|
||||||
dup_i += 1
|
dbg_n += 1
|
||||||
if self._det_count >= self._det_cap:
|
if dbg_n > self.usable_size / MEMBUDDY_MIN_BLOCK + 2:
|
||||||
# 记录表满:stdlib.realloc 翻倍扩容(防 is_alive/_det_probe
|
stdio.printf("[MEMDBG] alloc 扫描 free list order=%d 成环/超长(自检异常,终止)\n", dbg_order)
|
||||||
# 因容量耗尽漏检——SlotsBugTest 编译 includes 超 2M 次 alloc,
|
stdio.fflush(None)
|
||||||
# 满后新块无记录 → is_alive 误报"读取悬空")
|
stdlib.exit(1)
|
||||||
new_cap: t.CSizeT = self._det_cap * 2
|
dbg_cur = t.CVoid(c.Deref(t.CUInt64T(dbg_cur, t.CPtr)), t.CPtr)
|
||||||
new_rec: t.CVoid | t.CPtr = t.CVoid(
|
if self._det_count >= self._det_cap:
|
||||||
stdlib.realloc(self._det_arena, new_cap * 16), t.CPtr)
|
# 记录表满:stdlib.realloc 翻倍扩容(防 is_alive/_det_probe
|
||||||
if new_rec is not None:
|
# 因容量耗尽漏检——SlotsBugTest 编译 includes 超 2M 次 alloc,
|
||||||
self._det_arena = new_rec
|
# 满后新块无记录 → is_alive 误报"读取悬空")
|
||||||
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(new_rec, t.CPtr))
|
new_cap: t.CSizeT = self._det_cap * 2
|
||||||
self._det_cap = new_cap
|
new_rec: t.CVoid | t.CPtr = t.CVoid(
|
||||||
if self._det_count < self._det_cap:
|
stdlib.realloc(self._det_arena, new_cap * 16), t.CPtr)
|
||||||
self._det_records[self._det_count * 2] = base_ret_d + 2
|
if new_rec is not None:
|
||||||
self._det_records[self._det_count * 2 + 1] = t.CUInt64T(size)
|
self._det_arena = new_rec
|
||||||
self._det_count += 1
|
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(new_rec, t.CPtr))
|
||||||
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
|
self._det_cap = new_cap
|
||||||
self._det_probe()
|
if self._det_count < self._det_cap:
|
||||||
result = t.CVoid(base_ret_d + 2, t.CPtr)
|
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:
|
if result is None:
|
||||||
# 分配失败诊断(定位"异常 size/池耗尽导致 None → 调用方解引用段错误")
|
# 分配失败诊断(定位"异常 size/池耗尽导致 None → 调用方解引用段错误")
|
||||||
if size != 0 and self.usable is not None:
|
if size != 0 and self.usable is not None:
|
||||||
@@ -751,27 +790,60 @@ class MemBuddy(MemManager):
|
|||||||
if self.detection != 0:
|
if self.detection != 0:
|
||||||
# [DET] 返回指针比实际用户区靠后 2 字节,回收时向前偏移 2
|
# [DET] 返回指针比实际用户区靠后 2 字节,回收时向前偏移 2
|
||||||
p_eff = t.CVoid(t.CUInt64T(ptr) - 2, t.CPtr)
|
p_eff = t.CVoid(t.CUInt64T(ptr) - 2, t.CPtr)
|
||||||
# 从记录表取本条真实 size,free 后把用户区填 0xCD(UAF 写入
|
# 记录表置 free 标志(解耦于 detection,2026-09-04):非 detection
|
||||||
# 检测:free 后块被写穿 → 探测时 0xCD 被破坏 → 报警);记录
|
# 也需置位,否则 free 后同地址再 alloc(正常 reuse)被误报重叠。
|
||||||
# 保留并置 free 标志(探测时对仍 free 的块验证 0xCD 完整)。
|
if self._det_records is not None:
|
||||||
if self._det_records is not None:
|
# 从记录表取本条真实 size(detection 下 free 后填 0xCD,UAF
|
||||||
ri: t.CSizeT = 0
|
# 写入检测:free 后块被写穿 → 探测时 0xCD 被破坏 → 报警);
|
||||||
while ri < self._det_count:
|
# 记录保留并置 free 标志(探测时对仍 free 的块验证 0xCD 完整)。
|
||||||
rp: t.CUInt64T = self._det_records[ri * 2]
|
ri: t.CSizeT = 0
|
||||||
rs: t.CUInt64T = self._det_records[ri * 2 + 1]
|
while ri < self._det_count:
|
||||||
if rp == t.CUInt64T(ptr) and (rs & (t.CUInt64T(1) << 63)) == 0:
|
rp: t.CUInt64T = self._det_records[ri * 2]
|
||||||
if rs > 0:
|
rs: t.CUInt64T = self._det_records[ri * 2 + 1]
|
||||||
string.memset(ptr, MEMBUDDY_FILL_PATTERN, rs)
|
if rp == t.CUInt64T(ptr) and (rs & (t.CUInt64T(1) << 63)) == 0:
|
||||||
self._det_records[ri * 2 + 1] = rs | (t.CUInt64T(1) << 63)
|
if self.detection != 0 and rs > 0:
|
||||||
break
|
string.memset(ptr, MEMBUDDY_FILL_PATTERN, rs)
|
||||||
ri += 1
|
self._det_records[ri * 2 + 1] = rs | (t.CUInt64T(1) << 63)
|
||||||
|
break
|
||||||
|
ri += 1
|
||||||
if self._is_valid_ptr(p_eff) != 0:
|
if self._is_valid_ptr(p_eff) != 0:
|
||||||
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(p_eff) - MEMBUDDY_HEADER_SIZE, t.CPtr)
|
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: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
|
||||||
stored_val: t.CUInt64T = t.CUInt64T(stored)
|
stored_val: t.CUInt64T = t.CUInt64T(stored)
|
||||||
order: t.CInt = t.CInt(stored_val >> 1)
|
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))
|
c.DerefAs(block, t.CVoid(0, t.CPtr))
|
||||||
self._coalesce(block, order)
|
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()
|
self._unlock()
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
@@ -804,7 +876,8 @@ class MemBuddy(MemManager):
|
|||||||
self._rebuild_free_lists()
|
self._rebuild_free_lists()
|
||||||
# [DET] reset 重建全部 free list = 全部块释放:记录表同步清空,
|
# [DET] reset 重建全部 free list = 全部块释放:记录表同步清空,
|
||||||
# 防止后续 alloc 复用旧块被误报(与 reset_to 截断同因)。
|
# 防止后续 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
|
self._det_count = 0
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
@@ -898,6 +971,7 @@ class MemBuddy(MemManager):
|
|||||||
if mfv_a != t.CUInt16T(MEMBUDDY_DET_MARKER):
|
if mfv_a != t.CUInt16T(MEMBUDDY_DET_MARKER):
|
||||||
stdio.printf("[DET] 下溢写: ptr=%llu size=%llu 前标记=0x%04X(期望 0xCDCD)\n",
|
stdio.printf("[DET] 下溢写: ptr=%llu size=%llu 前标记=0x%04X(期望 0xCDCD)\n",
|
||||||
p, s, t.CUInt32T(mfv_a))
|
p, s, t.CUInt32T(mfv_a))
|
||||||
|
stdio.fflush(None)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
m16: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(p + s, t.CPtr))
|
m16: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(p + s, t.CPtr))
|
||||||
mv: t.CUInt16T = m16[0]
|
mv: t.CUInt16T = m16[0]
|
||||||
@@ -938,6 +1012,7 @@ class MemBuddy(MemManager):
|
|||||||
stdio.printf("[%zu]sz=%llu ", ci3, cs3 & (free_flag - 1))
|
stdio.printf("[%zu]sz=%llu ", ci3, cs3 & (free_flag - 1))
|
||||||
ci3 += 1
|
ci3 += 1
|
||||||
stdio.printf("\n")
|
stdio.printf("\n")
|
||||||
|
stdio.fflush(None)
|
||||||
stdlib.exit(1)
|
stdlib.exit(1)
|
||||||
i += 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_get_peer_certificate(s: SslPtr) -> X509Ptr
|
||||||
extern def SSL_get1_peer_certificate(s: SslPtr) -> X509Ptr
|
extern def SSL_get1_peer_certificate(s: SslPtr) -> X509Ptr
|
||||||
# 当前加密套件
|
# 当前加密套件
|
||||||
# const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) → 文本用下句
|
# SSL_get_cipher_name 在 ssl.h 是宏(SSL_CIPHER_get_name(SSL_get_current_cipher(s))),
|
||||||
# const char *SSL_get_cipher_name(const SSL *s) / int SSL_get_cipher_bits
|
# FFI 拆成两个真实导出函数调用:
|
||||||
extern def SSL_get_cipher_name(s: SslPtr) -> str
|
# 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)
|
# SNI: int SSL_set_tlsext_host_name(SSL *s, const char *name)(宏 → SSL_ctrl)
|
||||||
# const char *SSL_get_servername(const SSL *s, int type)
|
# const char *SSL_get_servername(const SSL *s, int type)
|
||||||
extern def SSL_get_servername(s: SslPtr, type: int) -> str
|
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
|
# openssl/types.vp — OpenSSL 3.x 不透明对象句柄 typedef
|
||||||
#
|
#
|
||||||
# 对接 libcrypto / libssl(OpenSSL 3.x 导出符号)。
|
# 对接 libcrypto / libssl(OpenSSL 3.x 导出符号)。
|
||||||
# 对象一律按不透明指针 (i8*) 处理,生命周期由 OpenSSL 库管理
|
# 对象一律按不透明指针 (void*) 处理,生命周期由 OpenSSL 库管理
|
||||||
# (X509_free/SSL_free/BIO_free/CRYPTO_free 等对应释放函数)。
|
# (X509_free/SSL_free/BIO_free/CRYPTO_free 等对应释放函数)。
|
||||||
# 链接目标:ViperOpenSSLProject 的 project.vpj 后续配置
|
# 链接目标:ViperOpenSSLProject 的 project.vpj 链接 openssl_358_C
|
||||||
# (msys2 mingw64 libcrypto/libssl 或 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*
|
OsslLibCtxPtr: t.CTypedef = t.CVoid | t.CPtr # OSSL_LIB_CTX*
|
||||||
EnginePtr: t.CTypedef = t.CPtr # ENGINE*
|
EnginePtr: t.CTypedef = t.CVoid | t.CPtr # ENGINE*
|
||||||
OpensslInitSettingsPtr: t.CTypedef = t.CPtr # OPENSSL_INIT_SETTINGS*
|
OpensslInitSettingsPtr: t.CTypedef = t.CVoid | t.CPtr # OPENSSL_INIT_SETTINGS*
|
||||||
|
|
||||||
# ---- BIO(内存/文件/Socket/Connect)----
|
# ---- BIO(内存/文件/Socket/Connect)----
|
||||||
BioPtr: t.CTypedef = t.CPtr # BIO*
|
BioPtr: t.CTypedef = t.CVoid | t.CPtr # BIO*
|
||||||
BioMethodPtr: t.CTypedef = t.CPtr # BIO_METHOD*
|
BioMethodPtr: t.CTypedef = t.CVoid | t.CPtr # BIO_METHOD*
|
||||||
BioAddrPtr: t.CTypedef = t.CPtr # BIO_ADDR*
|
BioAddrPtr: t.CTypedef = t.CVoid | t.CPtr # BIO_ADDR*
|
||||||
BioAddrInfoPtr: t.CTypedef = t.CPtr # BIO_ADDRINFO*
|
BioAddrInfoPtr: t.CTypedef = t.CVoid | t.CPtr # BIO_ADDRINFO*
|
||||||
|
|
||||||
# ---- EVP(摘要/对称/非对称)----
|
# ---- EVP(摘要/对称/非对称)----
|
||||||
EvpMdPtr: t.CTypedef = t.CPtr # EVP_MD*
|
EvpMdPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_MD*
|
||||||
EvpMdCtxPtr: t.CTypedef = t.CPtr # EVP_MD_CTX*
|
EvpMdCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_MD_CTX*
|
||||||
EvpCipherPtr: t.CTypedef = t.CPtr # EVP_CIPHER*
|
EvpCipherPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_CIPHER*
|
||||||
EvpCipherCtxPtr: t.CTypedef = t.CPtr # EVP_CIPHER_CTX*
|
EvpCipherCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_CIPHER_CTX*
|
||||||
EvpPkeyPtr: t.CTypedef = t.CPtr # EVP_PKEY*
|
EvpPkeyPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_PKEY*
|
||||||
EvpPkeyCtxPtr: t.CTypedef = t.CPtr # EVP_PKEY_CTX*
|
EvpPkeyCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_PKEY_CTX*
|
||||||
EvpEncodeCtxPtr: t.CTypedef = t.CPtr # EVP_ENCODE_CTX*
|
EvpEncodeCtxPtr: t.CTypedef = t.CVoid | t.CPtr # EVP_ENCODE_CTX*
|
||||||
HmacCtxPtr: t.CTypedef = t.CPtr # HMAC_CTX*
|
HmacCtxPtr: t.CTypedef = t.CVoid | t.CPtr # HMAC_CTX*
|
||||||
|
|
||||||
# ---- X509 / 证书 ----
|
# ---- X509 / 证书 ----
|
||||||
X509Ptr: t.CTypedef = t.CPtr # X509*
|
X509Ptr: t.CTypedef = t.CVoid | t.CPtr # X509*
|
||||||
X509NamePtr: t.CTypedef = t.CPtr # X509_NAME*
|
X509NamePtr: t.CTypedef = t.CVoid | t.CPtr # X509_NAME*
|
||||||
X509NameEntryPtr: t.CTypedef = t.CPtr # X509_NAME_ENTRY*
|
X509NameEntryPtr: t.CTypedef = t.CVoid | t.CPtr # X509_NAME_ENTRY*
|
||||||
X509CrlPtr: t.CTypedef = t.CPtr # X509_CRL*
|
X509CrlPtr: t.CTypedef = t.CVoid | t.CPtr # X509_CRL*
|
||||||
X509ReqPtr: t.CTypedef = t.CPtr # X509_REQ*
|
X509ReqPtr: t.CTypedef = t.CVoid | t.CPtr # X509_REQ*
|
||||||
X509ExtensionPtr: t.CTypedef = t.CPtr # X509_EXTENSION*
|
X509ExtensionPtr: t.CTypedef = t.CVoid | t.CPtr # X509_EXTENSION*
|
||||||
X509StorePtr: t.CTypedef = t.CPtr # X509_STORE*
|
X509StorePtr: t.CTypedef = t.CVoid | t.CPtr # X509_STORE*
|
||||||
X509StoreCtxPtr: t.CTypedef = t.CPtr # X509_STORE_CTX*
|
X509StoreCtxPtr: t.CTypedef = t.CVoid | t.CPtr # X509_STORE_CTX*
|
||||||
X509InfoPtr: t.CTypedef = t.CPtr # X509_INFO*
|
X509InfoPtr: t.CTypedef = t.CVoid | t.CPtr # X509_INFO*
|
||||||
X509VerifyParamPtr: t.CTypedef = t.CPtr # X509_VERIFY_PARAM*
|
X509VerifyParamPtr: t.CTypedef = t.CVoid | t.CPtr # X509_VERIFY_PARAM*
|
||||||
|
|
||||||
# ---- ASN.1 ----
|
# ---- ASN.1 ----
|
||||||
Asn1ObjectPtr: t.CTypedef = t.CPtr # ASN1_OBJECT*
|
Asn1ObjectPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_OBJECT*
|
||||||
Asn1StringPtr: t.CTypedef = t.CPtr # ASN1_STRING*
|
Asn1StringPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_STRING*
|
||||||
Asn1IntegerPtr: t.CTypedef = t.CPtr # ASN1_INTEGER*
|
Asn1IntegerPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_INTEGER*
|
||||||
Asn1TimePtr: t.CTypedef = t.CPtr # ASN1_TIME*
|
Asn1TimePtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_TIME*
|
||||||
Asn1OctetStringPtr: t.CTypedef = t.CPtr # ASN1_OCTET_STRING*
|
Asn1OctetStringPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_OCTET_STRING*
|
||||||
Asn1BitStringPtr: t.CTypedef = t.CPtr # ASN1_BIT_STRING*
|
Asn1BitStringPtr: t.CTypedef = t.CVoid | t.CPtr # ASN1_BIT_STRING*
|
||||||
GeneralNamesPtr: t.CTypedef = t.CPtr # GENERAL_NAMES*
|
GeneralNamesPtr: t.CTypedef = t.CVoid | t.CPtr # GENERAL_NAMES*
|
||||||
GeneralNamePtr: t.CTypedef = t.CPtr # GENERAL_NAME*
|
GeneralNamePtr: t.CTypedef = t.CVoid | t.CPtr # GENERAL_NAME*
|
||||||
|
|
||||||
# ---- SSL/TLS ----
|
# ---- SSL/TLS ----
|
||||||
SslPtr: t.CTypedef = t.CPtr # SSL*
|
SslPtr: t.CTypedef = t.CVoid | t.CPtr # SSL*
|
||||||
SslCtxPtr: t.CTypedef = t.CPtr # SSL_CTX*
|
SslCtxPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_CTX*
|
||||||
SslMethodPtr: t.CTypedef = t.CPtr # SSL_METHOD*
|
SslMethodPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_METHOD*
|
||||||
SslSessionPtr: t.CTypedef = t.CPtr # SSL_SESSION*
|
SslSessionPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_SESSION*
|
||||||
|
SslCipherPtr: t.CTypedef = t.CVoid | t.CPtr # SSL_CIPHER*
|
||||||
|
|
||||||
# ---- BIGNUM ----
|
# ---- BIGNUM ----
|
||||||
BnPtr: t.CTypedef = t.CPtr # BIGNUM*
|
BnPtr: t.CTypedef = t.CVoid | t.CPtr # BIGNUM*
|
||||||
BnCtxPtr: t.CTypedef = t.CPtr # BN_CTX*
|
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
|
out_pos: t.CSizeT = 0
|
||||||
i: t.CSizeT = 0
|
i: t.CSizeT = 0
|
||||||
s: str = sep()
|
s: t.CChar = sep()
|
||||||
|
|
||||||
# 处理绝对路径前缀
|
# 处理绝对路径前缀
|
||||||
is_absolute: bool = False
|
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
|
# st_mode type determination
|
||||||
|
|||||||
@@ -82,19 +82,18 @@ class timeval:
|
|||||||
# (Windows SOCKET=u64, POSIX fd=int → u64 Zero-Extension Compatible)
|
# (Windows SOCKET=u64, POSIX fd=int → u64 Zero-Extension Compatible)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def socket(family: INT, type: INT, protocol: INT) -> u64 | t.CExtern | t.CExport: pass
|
extern def socket(family: INT, type: INT, protocol: INT) -> u64
|
||||||
def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT | t.CExtern | t.CExport: pass
|
extern def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT
|
||||||
def send(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.CExtern | t.CExport: pass
|
extern def send(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT
|
||||||
def recv(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.CExtern | t.CExport: pass
|
extern def recv(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT
|
||||||
def bind(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT | t.CExtern | t.CExport: pass
|
extern def bind(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT
|
||||||
def listen(fd: u64, backlog: INT) -> INT | t.CExtern | t.CExport: pass
|
extern def listen(fd: u64, backlog: INT) -> INT
|
||||||
def accept(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64 | t.CExtern | t.CExport: pass
|
extern def accept(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64
|
||||||
def setsockopt(fd: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT | t.CExtern | t.CExport: pass
|
extern def setsockopt(fd: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT
|
||||||
def gethostbyname(name: t.CChar | t.CConst | t.CPtr) -> HostEnt | t.CPtr | t.CExtern | t.CExport: pass
|
extern def gethostbyname(name: t.CConst | str) -> HostEnt | t.CPtr
|
||||||
def ntohs(netshort: u16) -> u16 | t.CExtern | t.CExport: pass
|
extern def ntohs(netshort: u16) -> u16
|
||||||
def htons(hostshort: u16) -> u16 | t.CExtern | t.CExport: pass
|
extern def htons(hostshort: u16) -> u16
|
||||||
def close(fd: u64) -> INT | t.CExtern | t.CExport: pass
|
extern def close(fd: u64) -> INT
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Internal Auxiliary Functions
|
# Internal Auxiliary Functions
|
||||||
|
|||||||
@@ -66,20 +66,23 @@ def strncat(dest: str, src: str, n: t.CSizeT) -> str:
|
|||||||
|
|
||||||
|
|
||||||
# String length function
|
# String length function
|
||||||
def strlen(src: str) -> t.CSizeT | t.CExport:
|
export def strlen(src: str) -> t.CSizeT:
|
||||||
length: t.CSizeT = 0
|
length: t.CSizeT = 0
|
||||||
for _ in src:
|
for _ in src:
|
||||||
length += 1
|
length += 1
|
||||||
return length
|
return length
|
||||||
|
|
||||||
# String comparison function
|
# 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:
|
def strcmp(str1: str, str2: str) -> int:
|
||||||
while str1[0] != '\0' and str2[0] != '\0':
|
while str1[0] != '\0' and str2[0] != '\0':
|
||||||
if str1[0] != str2[0]:
|
if str1[0] != str2[0]:
|
||||||
return str1[0] - str2[0]
|
return int(str1[0]) - int(str2[0])
|
||||||
str1 += 1
|
str1 += 1
|
||||||
str2 += 1
|
str2 += 1
|
||||||
return str1[0] - str2[0]
|
return int(str1[0]) - int(str2[0])
|
||||||
|
|
||||||
def samestr(str1: str, str2: str) -> bool:
|
def samestr(str1: str, str2: str) -> bool:
|
||||||
return strcmp(str1, str2) == 0
|
return strcmp(str1, str2) == 0
|
||||||
@@ -90,12 +93,12 @@ def strncmp(str1: str, str2: str, n: t.CSizeT) -> int:
|
|||||||
i: t.CSizeT = 0
|
i: t.CSizeT = 0
|
||||||
while str1[0] != '\0' and str2[0] != '\0' and i < n:
|
while str1[0] != '\0' and str2[0] != '\0' and i < n:
|
||||||
if str1[0] != str2[0]:
|
if str1[0] != str2[0]:
|
||||||
return str1[0] - str2[0]
|
return int(str1[0]) - int(str2[0])
|
||||||
str1 += 1
|
str1 += 1
|
||||||
str2 += 1
|
str2 += 1
|
||||||
i += 1
|
i += 1
|
||||||
if i < n:
|
if i < n:
|
||||||
return str1[0] - str2[0]
|
return int(str1[0]) - int(str2[0])
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@@ -164,7 +167,7 @@ def strspn(s: str, skip: str = " ") -> int:
|
|||||||
return si
|
return si
|
||||||
|
|
||||||
# Memory set function
|
# 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:
|
# Original implementation:
|
||||||
# p: BYTEPTR = BYTEPTR(ptr)
|
# p: BYTEPTR = BYTEPTR(ptr)
|
||||||
# i: t.CSizeT
|
# 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
|
# 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:
|
# Original implementation:
|
||||||
# d: BYTEPTR = BYTEPTR(dest)
|
# d: BYTEPTR = BYTEPTR(dest)
|
||||||
# s: BYTEPTR = BYTEPTR(src)
|
# 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
|
num //= base
|
||||||
return count
|
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
|
if buf is None or rule is None: return
|
||||||
vsnprintf(buf, 0x7FFFFFFF, rule, args)
|
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
|
if buf is None or rule is None: return 0
|
||||||
return vsnprintf(buf, 0x7FFFFFFF, rule, args)
|
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 fmt is None: return 0
|
||||||
if buf is None or size == 0:
|
if buf is None or size == 0:
|
||||||
return vsnprintf(None, 0, fmt, args)
|
return vsnprintf(None, 0, fmt, args)
|
||||||
ret: t.CInt = vsnprintf(buf, size, fmt, args)
|
ret: int = vsnprintf(buf, size, fmt, args)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# Check floating-point special values (IEEE 754)
|
# Check floating-point special values (IEEE 754)
|
||||||
# Return: 0=normal, 1=+inf, 2=-inf, 3=nan
|
# 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
|
fbits: t.CUInt64T = 0
|
||||||
c.Load(c.Addr(fbits), c.Addr(fv))
|
c.Load(c.Addr(fbits), c.Addr(fv))
|
||||||
if ((fbits >> 52) & 0x7FF) != 0x7FF:
|
if ((fbits >> 52) & 0x7FF) != 0x7FF:
|
||||||
return 0
|
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 (fbits & 0x000FFFFFFFFFFFFF) == 0:
|
||||||
if is_neg:
|
if is_neg:
|
||||||
return 2
|
return 2
|
||||||
return 1
|
return 1
|
||||||
return 3
|
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
|
if fmt is None: return 0
|
||||||
# 长度探测模式:buf is None 时只计算格式化后长度,不实际写入
|
# 长度探测模式:buf is None 时只计算格式化后长度,不实际写入
|
||||||
# _step=0 使 ptr 不前进,反复写入同一个 dummy 字节(无害),write_count 正确累加
|
# _step=0 使 ptr 不前进,反复写入同一个 dummy 字节(无害),write_count 正确累加
|
||||||
count_mode: t.CInt = 0
|
count_mode: int = 0
|
||||||
_step: t.CInt = 1
|
_step: int = 1
|
||||||
_dummy: t.CChar = '\0'
|
_dummy: t.CChar = '\0'
|
||||||
if buf is None or size == 0:
|
if buf is None or size == 0:
|
||||||
count_mode = 1
|
count_mode = 1
|
||||||
|
|||||||
+202
-39
@@ -19,8 +19,13 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QStyleOptionButton>
|
#include <QStyleOptionButton>
|
||||||
|
#include <QStyleOptionViewItem>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QShowEvent>
|
#include <QShowEvent>
|
||||||
|
#include <QProxyStyle>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
@@ -853,6 +858,70 @@ extern "C" VQT6_API int vqt6_qplaintextedit_line_count(void* pte) {
|
|||||||
// QCheckBox / QRadioButton
|
// 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 绘制,勾选带过渡动画
|
// 自绘 QCheckBox:矢量框+对勾按 QPalette 绘制,勾选带过渡动画
|
||||||
class vqt6_CheckBox : public QCheckBox {
|
class vqt6_CheckBox : public QCheckBox {
|
||||||
public:
|
public:
|
||||||
@@ -875,41 +944,12 @@ protected:
|
|||||||
r = QRect(0, 0, 16, 16);
|
r = QRect(0, 0, 16, 16);
|
||||||
r.moveCenter(QPoint(rect().left() + 12, rect().center().y()));
|
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) {
|
vqt6_paint_check_indicator(&p, vqt6_indicator_box(r), pal, isEnabled(), m_progress, false);
|
||||||
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));
|
|
||||||
}
|
|
||||||
// 文本
|
// 文本
|
||||||
QRect lr = style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, this);
|
QRect lr = style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, this);
|
||||||
if (!lr.isEmpty() && !lr.isNull()) {
|
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());
|
p.drawText(lr, Qt::AlignLeft | Qt::AlignVCenter, text());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -949,13 +989,6 @@ private:
|
|||||||
m_progress = m_target;
|
m_progress = m_target;
|
||||||
m_timer.stop();
|
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) {
|
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;
|
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) {
|
extern "C" VQT6_API void* vqt6_qradiobutton_create(void) {
|
||||||
return new QRadioButton();
|
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 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 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_qapplication_set_theme_palette(void* app, int theme);
|
||||||
|
VQT6_API void vqt6_enable_custom_item_checks(void* app);
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// QWidget
|
// 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_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_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_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 self.closed: return FRESULT.ERR_CLOSED
|
||||||
if not self.can_write: return FRESULT.ERR_PERM
|
if not self.can_write: return FRESULT.ERR_PERM
|
||||||
bytes_written: ULONG = 0
|
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
|
if result == 0: return FRESULT.ERR_IO
|
||||||
return LONG(bytes_written)
|
return LONG(bytes_written)
|
||||||
|
|
||||||
|
|||||||
+86
-46
@@ -24,7 +24,9 @@ import t, c
|
|||||||
from stdint import *
|
from stdint import *
|
||||||
import stdlib
|
import stdlib
|
||||||
import string
|
import string
|
||||||
import w32.fileio as fio
|
import viperlib
|
||||||
|
import w32.win32base as wb
|
||||||
|
import w32.win32file as wf
|
||||||
import zlib.pyzlib as zpy
|
import zlib.pyzlib as zpy
|
||||||
|
|
||||||
|
|
||||||
@@ -71,6 +73,16 @@ def zipfile_set_error(code: t.CInt, msg: str):
|
|||||||
zipfile_error_msg[0] = '\0'
|
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:
|
def error_code() -> t.CInt:
|
||||||
return zipfile_error_code_val
|
return zipfile_error_code_val
|
||||||
|
|
||||||
@@ -124,31 +136,47 @@ def zf_w32le(h: BYTEPTR, v: t.CUInt32T):
|
|||||||
h[3] = (v >> 24) & 0xFF
|
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
|
done: t.CSizeT = 0
|
||||||
while done < n:
|
while done < n:
|
||||||
chunk: t.CSizeT = n - done
|
chunk: t.CSizeT = n - done
|
||||||
if chunk > 0xFFFFFF00:
|
if chunk > 0xFFFFFF00:
|
||||||
chunk = 0xFFFFFF00
|
chunk = 0xFFFFFF00
|
||||||
w: LONG = f.write(p + done, ULONG(chunk))
|
written: ULONG = 0
|
||||||
if w <= 0:
|
ok: BOOL = wf.WriteFile(h, p + done, ULONG(chunk), c.Addr(written), None)
|
||||||
zipfile_set_error(ZIP_ERR_IO, "write failed")
|
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
|
return ZIP_ERR_IO
|
||||||
done += t.CSizeT(w)
|
done += t.CSizeT(written)
|
||||||
return ZIP_ERR_OK
|
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
|
done: t.CSizeT = 0
|
||||||
while done < n:
|
while done < n:
|
||||||
chunk: t.CSizeT = n - done
|
chunk: t.CSizeT = n - done
|
||||||
if chunk > 0xFFFFFF00:
|
if chunk > 0xFFFFFF00:
|
||||||
chunk = 0xFFFFFF00
|
chunk = 0xFFFFFF00
|
||||||
rd: LONG = f.read(p + done, ULONG(chunk))
|
bytes_read: ULONG = 0
|
||||||
if rd <= 0:
|
ok: BOOL = wf.ReadFile(h, p + done, ULONG(chunk), c.Addr(bytes_read), None)
|
||||||
zipfile_set_error(ZIP_ERR_IO, "read failed")
|
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
|
return ZIP_ERR_IO
|
||||||
done += t.CSizeT(rd)
|
done += t.CSizeT(bytes_read)
|
||||||
return ZIP_ERR_OK
|
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:
|
if not out_len:
|
||||||
zipfile_set_error(ZIP_ERR_OPEN, "out_len is None")
|
zipfile_set_error(ZIP_ERR_OPEN, "out_len is None")
|
||||||
return None
|
return None
|
||||||
f: fio.File | t.CPtr = fio.File(path, fio.MODE.R)
|
h: wb.HANDLE = wf.CreateFileA(
|
||||||
if f.closed:
|
path, wf.GENERIC_READ, zf_share_flags(),
|
||||||
zipfile_set_error(ZIP_ERR_OPEN, "cannot open file for reading")
|
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
|
return None
|
||||||
sz64: LONGLONG = f.size()
|
li: wb.LARGE_INTEGER = wb.LARGE_INTEGER()
|
||||||
if sz64 < 0:
|
ok_size: BOOL = wf.GetFileSizeEx(h, t.CPtr(c.Addr(li)))
|
||||||
f.close()
|
if ok_size == 0:
|
||||||
|
wb.CloseHandle(h)
|
||||||
zipfile_set_error(ZIP_ERR_IO, "cannot get file size")
|
zipfile_set_error(ZIP_ERR_IO, "cannot get file size")
|
||||||
return None
|
return None
|
||||||
sz: t.CSizeT = t.CSizeT(sz64)
|
sz: t.CSizeT = t.CSizeT(li.QuadPart)
|
||||||
if sz == 0:
|
if sz == 0:
|
||||||
f.close()
|
wb.CloseHandle(h)
|
||||||
zipfile_set_error(ZIP_ERR_NOT_ZIP, "empty file is not a zip archive")
|
zipfile_set_error(ZIP_ERR_NOT_ZIP, "empty file is not a zip archive")
|
||||||
return None
|
return None
|
||||||
buf: BYTEPTR = BYTEPTR(stdlib.malloc(sz))
|
buf: BYTEPTR = BYTEPTR(stdlib.malloc(sz))
|
||||||
if not buf:
|
if not buf:
|
||||||
f.close()
|
wb.CloseHandle(h)
|
||||||
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
|
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
|
||||||
return None
|
return None
|
||||||
rc: t.CInt = zf_fread_all(f, buf, sz)
|
rc: t.CInt = zf_read_all(h, buf, sz)
|
||||||
f.close()
|
wb.CloseHandle(h)
|
||||||
if rc != ZIP_ERR_OK:
|
if rc != ZIP_ERR_OK:
|
||||||
stdlib.free(buf)
|
stdlib.free(buf)
|
||||||
return None
|
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:
|
class ZipInfo:
|
||||||
filename: bytes # 原始字节名(含 \0,zipfile 持有并负责释放)
|
filename: bytes # 原始字节名(含 \0,zipfile 持有并负责释放)
|
||||||
name_len: t.CSizeT
|
name_len: t.CSizeT
|
||||||
@@ -198,16 +232,6 @@ class ZipInfo:
|
|||||||
header_offset: t.CSizeT # 本地文件头偏移
|
header_offset: t.CSizeT # 本地文件头偏移
|
||||||
next: "ZipInfo" | t.CPtr # 链表(保持写入/目录顺序)
|
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
|
# ZipFile
|
||||||
@@ -217,7 +241,7 @@ class ZipFile:
|
|||||||
path: bytes
|
path: bytes
|
||||||
mode: t.CInt # 0 = 读,1 = 写
|
mode: t.CInt # 0 = 读,1 = 写
|
||||||
compression: t.CInt # write() 未显式指定时的压缩类型
|
compression: t.CInt # write() 未显式指定时的压缩类型
|
||||||
fh: fio.File | t.CPtr # 写模式句柄
|
fh: wb.HANDLE # 写模式句柄(裸 win32 CreateFileA)
|
||||||
data: BYTEPTR # 读模式:整个归档的内存副本
|
data: BYTEPTR # 读模式:整个归档的内存副本
|
||||||
data_len: t.CSizeT
|
data_len: t.CSizeT
|
||||||
info_head: ZipInfo | t.CPtr
|
info_head: ZipInfo | t.CPtr
|
||||||
@@ -240,9 +264,10 @@ class ZipFile:
|
|||||||
self.pos = 0
|
self.pos = 0
|
||||||
self.ok = 0
|
self.ok = 0
|
||||||
self.closed = 0
|
self.closed = 0
|
||||||
if mode == "r":
|
# 注意: 字符串必须用 strcmp 比较(== 只会比较指针)
|
||||||
|
if string.strcmp(mode, "r") == 0:
|
||||||
self.mode = 0
|
self.mode = 0
|
||||||
elif mode == "w":
|
elif string.strcmp(mode, "w") == 0:
|
||||||
self.mode = 1
|
self.mode = 1
|
||||||
else:
|
else:
|
||||||
zipfile_set_error(ZIP_ERR_OPEN, "mode must be 'r' or 'w'")
|
zipfile_set_error(ZIP_ERR_OPEN, "mode must be 'r' or 'w'")
|
||||||
@@ -261,9 +286,11 @@ class ZipFile:
|
|||||||
self.closed = 1
|
self.closed = 1
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.fh = fio.File(path, fio.MODE.W)
|
self.fh = wf.CreateFileA(
|
||||||
if self.fh.closed:
|
path, wf.GENERIC_WRITE, zf_share_flags(),
|
||||||
zipfile_set_error(ZIP_ERR_OPEN, "cannot create file for writing")
|
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.fh = None
|
||||||
self.closed = 1
|
self.closed = 1
|
||||||
return
|
return
|
||||||
@@ -278,13 +305,18 @@ class ZipFile:
|
|||||||
n.filename = None
|
n.filename = None
|
||||||
nxt: ZipInfo | t.CPtr = n.next
|
nxt: ZipInfo | t.CPtr = n.next
|
||||||
n.next = None
|
n.next = None
|
||||||
|
stdlib.free(n)
|
||||||
n = nxt
|
n = nxt
|
||||||
self.info_head = None
|
self.info_head = None
|
||||||
self.info_tail = None
|
self.info_tail = None
|
||||||
self.info_count = 0
|
self.info_count = 0
|
||||||
|
|
||||||
def _append_info(self) -> ZipInfo | t.CPtr:
|
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:
|
if self.info_tail is None:
|
||||||
self.info_head = node
|
self.info_head = node
|
||||||
else:
|
else:
|
||||||
@@ -354,6 +386,9 @@ class ZipFile:
|
|||||||
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
|
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
|
||||||
return ZIP_ERR_MEMORY
|
return ZIP_ERR_MEMORY
|
||||||
node: ZipInfo | t.CPtr = self._append_info()
|
node: ZipInfo | t.CPtr = self._append_info()
|
||||||
|
if node is None:
|
||||||
|
stdlib.free(dup)
|
||||||
|
return ZIP_ERR_MEMORY
|
||||||
node.filename = dup
|
node.filename = dup
|
||||||
node.name_len = t.CSizeT(nlen)
|
node.name_len = t.CSizeT(nlen)
|
||||||
node.compress_type = t.CInt(method)
|
node.compress_type = t.CInt(method)
|
||||||
@@ -514,12 +549,12 @@ class ZipFile:
|
|||||||
zf_w32le(hdr + 18, t.CUInt32T(plen))
|
zf_w32le(hdr + 18, t.CUInt32T(plen))
|
||||||
zf_w32le(hdr + 22, t.CUInt32T(data_len))
|
zf_w32le(hdr + 22, t.CUInt32T(data_len))
|
||||||
zf_w16le(hdr + 26, t.CUInt32T(name_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)
|
stdlib.free(hdr)
|
||||||
if rc == ZIP_ERR_OK:
|
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:
|
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:
|
if ctype == ZIP_DEFLATED:
|
||||||
stdlib.free(payload)
|
stdlib.free(payload)
|
||||||
if rc != ZIP_ERR_OK:
|
if rc != ZIP_ERR_OK:
|
||||||
@@ -531,6 +566,9 @@ class ZipFile:
|
|||||||
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
|
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
|
||||||
return ZIP_ERR_MEMORY
|
return ZIP_ERR_MEMORY
|
||||||
node: ZipInfo | t.CPtr = self._append_info()
|
node: ZipInfo | t.CPtr = self._append_info()
|
||||||
|
if node is None:
|
||||||
|
stdlib.free(dup)
|
||||||
|
return ZIP_ERR_MEMORY
|
||||||
node.filename = dup
|
node.filename = dup
|
||||||
node.name_len = name_len
|
node.name_len = name_len
|
||||||
node.compress_type = ctype
|
node.compress_type = ctype
|
||||||
@@ -565,9 +603,11 @@ class ZipFile:
|
|||||||
zf_w32le(hdr + 24, t.CUInt32T(n.file_size))
|
zf_w32le(hdr + 24, t.CUInt32T(n.file_size))
|
||||||
zf_w16le(hdr + 28, t.CUInt32T(n.name_len))
|
zf_w16le(hdr + 28, t.CUInt32T(n.name_len))
|
||||||
zf_w32le(hdr + 42, t.CUInt32T(n.header_offset))
|
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:
|
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
|
n = n.next
|
||||||
stdlib.free(hdr)
|
stdlib.free(hdr)
|
||||||
if rc != ZIP_ERR_OK:
|
if rc != ZIP_ERR_OK:
|
||||||
@@ -584,7 +624,7 @@ class ZipFile:
|
|||||||
zf_w16le(e + 10, t.CUInt32T(self.info_count))
|
zf_w16le(e + 10, t.CUInt32T(self.info_count))
|
||||||
zf_w32le(e + 12, t.CUInt32T(cd_size))
|
zf_w32le(e + 12, t.CUInt32T(cd_size))
|
||||||
zf_w32le(e + 16, t.CUInt32T(cd_start))
|
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)
|
stdlib.free(e)
|
||||||
if rc != ZIP_ERR_OK:
|
if rc != ZIP_ERR_OK:
|
||||||
zipfile_set_error(ZIP_ERR_IO, "write EOCD failed")
|
zipfile_set_error(ZIP_ERR_IO, "write EOCD failed")
|
||||||
@@ -596,7 +636,7 @@ class ZipFile:
|
|||||||
rc: t.CInt = ZIP_ERR_OK
|
rc: t.CInt = ZIP_ERR_OK
|
||||||
if self.mode == 1 and self.fh is not None:
|
if self.mode == 1 and self.fh is not None:
|
||||||
rc = self._finish_write()
|
rc = self._finish_write()
|
||||||
self.fh.close()
|
wb.CloseHandle(self.fh)
|
||||||
self.fh = None
|
self.fh = None
|
||||||
elif self.mode == 0:
|
elif self.mode == 0:
|
||||||
if self.data is not None:
|
if self.data is not None:
|
||||||
|
|||||||
+17
-10
@@ -52,8 +52,11 @@ class zdeflate_stream:
|
|||||||
attempts += 1
|
attempts += 1
|
||||||
return best_len if (best_len >= zdef.ZDEFLATE_MIN_MATCH) else 0
|
return best_len if (best_len >= zdef.ZDEFLATE_MIN_MATCH) else 0
|
||||||
|
|
||||||
def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT):
|
def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT, data_len: t.CSizeT):
|
||||||
if pos + 2 < pos: return
|
# 只在还能作为匹配起点的位置维护 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)
|
h: t.CUnsignedInt = zdeflate_hash(data + pos)
|
||||||
self.hash_prev[pos & zdef.ZDEFLATE_WINDOW_MASK] = self.hash_head[h]
|
self.hash_prev[pos & zdef.ZDEFLATE_WINDOW_MASK] = self.hash_head[h]
|
||||||
self.hash_head[h] = t.CInt(pos)
|
self.hash_head[h] = t.CInt(pos)
|
||||||
@@ -83,11 +86,11 @@ class zdeflate_stream:
|
|||||||
if extra > 0:
|
if extra > 0:
|
||||||
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
|
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
|
||||||
for i in range(match_len):
|
for i in range(match_len):
|
||||||
self.update_hash(data, pos + i)
|
self.update_hash(data, pos + i, length)
|
||||||
pos += match_len
|
pos += match_len
|
||||||
else:
|
else:
|
||||||
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
|
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
|
||||||
self.update_hash(data, pos)
|
self.update_hash(data, pos, length)
|
||||||
pos += 1
|
pos += 1
|
||||||
lit_tree.encode_symbol(256, c.Addr(self.writer))
|
lit_tree.encode_symbol(256, c.Addr(self.writer))
|
||||||
|
|
||||||
@@ -111,11 +114,11 @@ class zdeflate_stream:
|
|||||||
if extra > 0:
|
if extra > 0:
|
||||||
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
|
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
|
||||||
for j in range(match_len):
|
for j in range(match_len):
|
||||||
self.update_hash(data, pos + j)
|
self.update_hash(data, pos + j, length)
|
||||||
pos += match_len
|
pos += match_len
|
||||||
else:
|
else:
|
||||||
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
|
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
|
||||||
self.update_hash(data, pos)
|
self.update_hash(data, pos, length)
|
||||||
pos += 1
|
pos += 1
|
||||||
lit_tree.encode_symbol(256, c.Addr(self.writer))
|
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
|
lit_freqs[len_sym] += 1
|
||||||
dist_freqs[zdeflate_dist_to_symbol(best_dist)] += 1
|
dist_freqs[zdeflate_dist_to_symbol(best_dist)] += 1
|
||||||
for i in range(match_len):
|
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
|
pos += match_len
|
||||||
else:
|
else:
|
||||||
lit_freqs[data[pos]] += 1
|
lit_freqs[data[pos]] += 1
|
||||||
zdeflate_stream.update_hash(s, data, pos)
|
zdeflate_stream.update_hash(s, data, pos, length)
|
||||||
pos += 1
|
pos += 1
|
||||||
lit_freqs[256] = 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
|
if count > 6: count = 6
|
||||||
cl_freqs[16] += 1
|
cl_freqs[16] += 1
|
||||||
run -= count
|
run -= count
|
||||||
i += run
|
i += count
|
||||||
|
# 剩余的 1~2 个相同长度值不静默跳过,交由外层循环
|
||||||
|
# 按字面量(符号 val)逐个统计,保证总覆盖数恰为 total
|
||||||
|
|
||||||
def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt,
|
def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt,
|
||||||
w: zdef.zbit_writer | t.CPtr, cl_tree: zhuff.zhuff_tree | t.CPtr):
|
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)
|
cl_tree.encode_symbol(16, w)
|
||||||
w.write_bits(count - 3, 2)
|
w.write_bits(count - 3, 2)
|
||||||
run -= count
|
run -= count
|
||||||
i += run
|
i += count
|
||||||
|
# 剩余的 1~2 个相同长度值不静默跳过,交由外层循环
|
||||||
|
# 按字面量(符号 val)逐个编码,保证 RLE 覆盖总数恰为 total
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -70,7 +70,8 @@ class zinflate_stream:
|
|||||||
self.is_gzip = 1
|
self.is_gzip = 1
|
||||||
if self.input_pos + 10 > self.input_len: return -3
|
if self.input_pos + 10 > self.input_len: return -3
|
||||||
self.input_pos += 10
|
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 flg & 0x04:
|
||||||
if self.input_pos + 2 > self.input_len: return -3
|
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)
|
xlen: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8)
|
||||||
|
|||||||
Reference in new issue
Block a user