From c3a43dfe76ad5d7b3016863a269a6a25ca1a9b39 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 24 Aug 2026 23:31:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor(includes):=20=E6=A0=87=E5=87=86?= =?UTF-8?q?=E5=BA=93=20extern=20=E8=BD=AF=E5=85=B3=E9=94=AE=E5=AD=97?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E8=BF=81=E7=A7=BB=20+=20=5Fappend=5Fcstr=20O?= =?UTF-8?q?(1)=20=E8=BF=BD=E5=8A=A0=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - posix/stdio 等 19 文件: def ... -> T|t.State: pass 改写为 extern def ... -> T - llvmlite/__builder.vp: _append_cstr 加写入位置缓存(_g_last_dst/_g_last_pos,缓冲切换/重置自动回退 strlen,防 O(n^2)) --- includes/_variant.vp | 2 +- includes/ast/stmts.vp | 2 +- includes/hashlib/__md5.vp | 4 +-- includes/hashlib/__sha1.vp | 8 ++--- includes/hashlib/__sha256.vp | 2 +- includes/json/__init__.vp | 28 +++++++-------- includes/json/__parser.vp | 20 +++++------ includes/json/__writer.vp | 16 ++++----- includes/llvmlite/__builder.vp | 18 +++++++++- includes/llvmlite/__function.vp | 18 +++++++++- includes/llvmlite/__module.vp | 20 +++++++++-- includes/llvmlite/__values.vp | 2 +- includes/llvmlite/__verify.vp | 18 +++++++++- includes/posix.vp | 63 ++++++++++++++++----------------- includes/stdarg.vp | 8 ++--- includes/stdio.vp | 16 ++++----- includes/stdlib.vp | 12 +++---- includes/string.vp | 40 ++++++++++----------- includes/sys.vp | 8 ++--- 19 files changed, 183 insertions(+), 122 deletions(-) diff --git a/includes/_variant.vp b/includes/_variant.vp index 31273dc..4da7f37 100644 --- a/includes/_variant.vp +++ b/includes/_variant.vp @@ -2,7 +2,7 @@ import t, c from stdint import * # Variant type tags (fixed enumeration + custom pointer type) -VARIANT_NONE: t.CDefine = 0 # Untyped / null value +VARIANT_NONE: t.CDefine = 0 # Untyped / null value VARIANT_INT: t.CDefine = 1 # int (i64) VARIANT_FLOAT: t.CDefine = 2 # float (f32) VARIANT_DOUBLE: t.CDefine = 3 # double (f64) diff --git a/includes/ast/stmts.vp b/includes/ast/stmts.vp index 569646a..fccfab8 100644 --- a/includes/ast/stmts.vp +++ b/includes/ast/stmts.vp @@ -6,7 +6,7 @@ from .base import ( AST, Stmt, ASTKind, ASTCtx, OpKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list, - FLAG_IS_ASYNC, + FLAG_IS_ASYNC, _op_name ) diff --git a/includes/hashlib/__md5.vp b/includes/hashlib/__md5.vp index d98680f..4cf5332 100644 --- a/includes/hashlib/__md5.vp +++ b/includes/hashlib/__md5.vp @@ -14,7 +14,7 @@ def md5_G(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x def md5_H(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return x ^ y ^ z def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return y ^ (x | ~z) # Circular left shift -def md5_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: return (x << n) | (x >> (32 - n)) +def md5_rotl(x: t.CUInt32T, n: int) -> t.CUInt32T: return (x << n) | (x >> (32 - n)) # MD5 constant table md5_T: t.CArray[t.CUInt32T, 64] = [ @@ -28,7 +28,7 @@ md5_T: t.CArray[t.CUInt32T, 64] = [ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ] -md5_S: t.CArray[t.CInt, 64] = [ +md5_S: t.CArray[int, 64] = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, diff --git a/includes/hashlib/__sha1.vp b/includes/hashlib/__sha1.vp index fdd28ae..21ecab7 100644 --- a/includes/hashlib/__sha1.vp +++ b/includes/hashlib/__sha1.vp @@ -9,7 +9,7 @@ import t, c SHA1_BLOCK_LEN: t.CDefine = 64 SHA1_DIGEST_LEN: t.CDefine = 20 -def sha1_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: return (x << n) | (x >> (32 - n)) +def sha1_rotl(x: t.CUInt32T, n: int) -> t.CUInt32T: return (x << n) | (x >> (32 - n)) # 3-round logical functions def sha1_f1(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (~b & d) def sha1_f2(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return b ^ c ^ d @@ -22,7 +22,7 @@ class sha1: count: t.CUInt64T buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN] def __init__(self): - memset(self.buf, 0, SHA1_BLOCK_LEN) + string.memset(self.buf, 0, SHA1_BLOCK_LEN) self.state[0] = 0x67452301 self.state[1] = 0xefcdab89 self.state[2] = 0x98badcfe @@ -103,10 +103,10 @@ class sha1: self.buf[idx] = 0x80 idx += 1 if idx > SHA1_BLOCK_LEN - 8: - memset(self.buf + idx, 0, SHA1_BLOCK_LEN - idx) + string.memset(self.buf + idx, 0, SHA1_BLOCK_LEN - idx) self.transform(self.buf) idx = 0 - 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 # SHA1 big-endian write length for i in range(8): diff --git a/includes/hashlib/__sha256.vp b/includes/hashlib/__sha256.vp index 4330bd5..c04af58 100644 --- a/includes/hashlib/__sha256.vp +++ b/includes/hashlib/__sha256.vp @@ -1,5 +1,5 @@ -import t, c import string +import t, c # ============================================== diff --git a/includes/json/__init__.vp b/includes/json/__init__.vp index b937cea..49f6e23 100644 --- a/includes/json/__init__.vp +++ b/includes/json/__init__.vp @@ -21,13 +21,13 @@ JSON_OBJECT: t.CDefine = 6 # 使用 mpool 分配:JsonValue(pool) 从池中分配内存 # ============================================================ class JsonValue: - vtype: t.CInt - bool_val: t.CInt + vtype: int + bool_val: int int_val: t.CInt64T float_val: t.CDouble - str_val: t.CChar | t.CPtr + str_val: str next: 'JsonValue' | t.CPtr - key: t.CChar | t.CPtr + key: str child: 'JsonValue' | t.CPtr child_count: t.CSizeT @@ -38,7 +38,7 @@ class JsonValue: string.memset(ptr, 0, JsonValue.__sizeof__()) return ptr - def type(self) -> t.CInt: + def type(self) -> int: return self.vtype def is_null(self) -> bool: @@ -71,13 +71,13 @@ class JsonValue: def as_float(self) -> t.CDouble: return self.float_val - def as_string(self) -> t.CChar | t.CPtr: + def as_string(self) -> str: return self.str_val def __len__(self) -> t.CSizeT: return self.child_count - def __getitem__(self, key: t.CChar | t.CPtr) -> 'JsonValue' | t.CPtr: + def __getitem__(self, key: str) -> 'JsonValue' | t.CPtr: """Python风格取值:v["key"] 取对象字段""" if self.vtype != JSON_OBJECT: return None @@ -91,7 +91,7 @@ class JsonValue: cur = cur.next return None - def __setitem__(self, key: t.CChar | t.CPtr, val: 'JsonValue' | t.CPtr): + def __setitem__(self, key: str, val: 'JsonValue' | t.CPtr): """Python风格赋值:v["key"] = val""" if self.vtype != JSON_OBJECT or key == None or val == None: return @@ -110,7 +110,7 @@ class JsonValue: cur = cur.next # key 不存在,追加新子节点 klen: t.CSizeT = string.strlen(key) - kbuf: t.CChar | t.CPtr = self._pool_alloc(klen + 1) + kbuf: str = self._pool_alloc(klen + 1) if kbuf != None: string.memcpy(kbuf, key, klen + 1) val.key = kbuf @@ -129,7 +129,7 @@ class JsonValue: i += 1 return None - def _pool_alloc(self, size: t.CSizeT) -> t.CChar | t.CPtr: + def _pool_alloc(self, size: t.CSizeT) -> str: """内部方法:从当前对象的 mpool 分配内存(预留,暂返回 None)""" return None @@ -175,13 +175,13 @@ def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t v.float_val = val return v -def string_val(pool: memhub.MemManager | t.CPtr, val: t.CChar | t.CPtr) -> JsonValue | t.CPtr: +def string_val(pool: memhub.MemManager | t.CPtr, val: str) -> JsonValue | t.CPtr: v: JsonValue | t.CPtr = JsonValue(pool) if v == None: return None v.vtype = JSON_STRING if val != None: slen: t.CSizeT = string.strlen(val) - buf: t.CChar | t.CPtr = pool.alloc(slen + 1) + buf: str = pool.alloc(slen + 1) if buf != None: string.memcpy(buf, val, slen + 1) v.str_val = buf @@ -206,7 +206,7 @@ def array_append(pool: memhub.MemManager | t.CPtr, arr: JsonValue | t.CPtr, item arr._append_child(item) # 向对象设置键值对 -def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: t.CChar | t.CPtr, val: JsonValue | t.CPtr): +def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: str, val: JsonValue | t.CPtr): if obj == None or key == None or val == None: return if obj.vtype != JSON_OBJECT: return cur: JsonValue | t.CPtr = obj.child @@ -223,7 +223,7 @@ def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: t return cur = cur.next klen: t.CSizeT = string.strlen(key) - kbuf: t.CChar | t.CPtr = pool.alloc(klen + 1) + kbuf: str = pool.alloc(klen + 1) if kbuf != None: string.memcpy(kbuf, key, klen + 1) val.key = kbuf diff --git a/includes/json/__parser.vp b/includes/json/__parser.vp index 2c9a300..bc6ef1f 100644 --- a/includes/json/__parser.vp +++ b/includes/json/__parser.vp @@ -10,12 +10,12 @@ from . import ( class ParseState: - src: t.CChar | t.CPtr + src: str pos: t.CSizeT len: t.CSizeT pool: memhub.MemManager | t.CPtr - def __init__(self, src: t.CChar | t.CPtr, pool: memhub.MemManager | t.CPtr): + def __init__(self, src: str, pool: memhub.MemManager | t.CPtr): self.src = src self.pos = 0 self.len = string.strlen(src) if src != None else 0 @@ -52,7 +52,7 @@ def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool: return True -def _parse_string(s: ParseState | t.CPtr) -> t.CChar | t.CPtr: +def _parse_string(s: ParseState | t.CPtr) -> str: if _peek(s) != '"': return None _advance(s) @@ -69,7 +69,7 @@ def _parse_string(s: ParseState | t.CPtr) -> t.CChar | t.CPtr: slen += 1 s.pos += 1 - buf: t.CChar | t.CPtr = s.pool.alloc(slen + 1) + buf: str = s.pool.alloc(slen + 1) if buf == None: return None @@ -147,7 +147,7 @@ def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: break num_len: t.CSizeT = s.pos - start - buf: t.CChar | t.CPtr = s.pool.alloc(num_len + 1) + buf: str = s.pool.alloc(num_len + 1) if buf == None: return null(s.pool) @@ -173,7 +173,7 @@ def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: ch: t.CChar = _peek(s) if ch == '"': - sv: t.CChar | t.CPtr = _parse_string(s) + sv: str = _parse_string(s) return string_val(s.pool, sv) if ch == '{': @@ -249,12 +249,12 @@ def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: return obj _skip_whitespace(s) - key: t.CChar | t.CPtr = _parse_string(s) + key: str = _parse_string(s) _expect(s, ':') val: JsonValue | t.CPtr = _parse_value(s) if key != None and val != None: klen: t.CSizeT = string.strlen(key) - kbuf: t.CChar | t.CPtr = s.pool.alloc(klen + 1) + kbuf: str = s.pool.alloc(klen + 1) if kbuf != None: string.memcpy(kbuf, key, klen + 1) val.key = kbuf @@ -273,7 +273,7 @@ def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: val = _parse_value(s) if key != None and val != None: klen2: t.CSizeT = string.strlen(key) - kbuf2: t.CChar | t.CPtr = s.pool.alloc(klen2 + 1) + kbuf2: str = s.pool.alloc(klen2 + 1) if kbuf2 != None: string.memcpy(kbuf2, key, klen2 + 1) val.key = kbuf2 @@ -283,7 +283,7 @@ def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: return obj -def parse(pool: memhub.MemManager | t.CPtr, src: t.CChar | t.CPtr) -> JsonValue | t.CPtr: +def parse(pool: memhub.MemManager | t.CPtr, src: str) -> JsonValue | t.CPtr: """解析 JSON 字符串,返回 JsonValue 树""" if src == None: return null(pool) diff --git a/includes/json/__writer.vp b/includes/json/__writer.vp index 4b6435b..8a493a0 100644 --- a/includes/json/__writer.vp +++ b/includes/json/__writer.vp @@ -9,17 +9,17 @@ from . import ( ) -def _write_char(buf: t.CChar | t.CPtr, pos: t.CSizeT, ch: t.CChar) -> t.CSizeT: +def _write_char(buf: str, pos: t.CSizeT, ch: t.CChar) -> t.CSizeT: buf[pos] = ch return pos + 1 -def _write_str(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT: +def _write_str(buf: str, pos: t.CSizeT, s: str) -> t.CSizeT: if s == None: return pos slen: t.CSizeT = string.strlen(s) string.memcpy(t.CChar(t.CUInt64T(buf) + pos, t.CPtr), s, slen) return pos + slen -def _write_string_escaped(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT: +def _write_string_escaped(buf: str, pos: t.CSizeT, s: str) -> t.CSizeT: if s == None: pos = _write_str(buf, pos, "null") return pos @@ -45,7 +45,7 @@ def _write_string_escaped(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.C return pos -def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CSizeT: +def _write_value(buf: str, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CSizeT: if val == None: pos = _write_str(buf, pos, "null") return pos @@ -60,13 +60,13 @@ def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, pos = _write_str(buf, pos, "false") elif val.vtype == JSON_INT: - tmp: t.CChar | t.CPtr = pool.alloc(32) + tmp: str = pool.alloc(32) if tmp != None: snprintf(tmp, 32, "%lld", val.int_val) pos = _write_str(buf, pos, tmp) elif val.vtype == JSON_FLOAT: - tmp2: t.CChar | t.CPtr = pool.alloc(32) + tmp2: str = pool.alloc(32) if tmp2 != None: snprintf(tmp2, 32, "%.6g", val.float_val) pos = _write_str(buf, pos, tmp2) @@ -109,9 +109,9 @@ def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, return pos -def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> t.CChar | t.CPtr: +def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> str: """将 JsonValue 序列化为 JSON 字符串""" - buf: t.CChar | t.CPtr = pool.alloc(4096) + buf: str = pool.alloc(4096) if buf == None: return None end_pos: t.CSizeT = _write_value(buf, 0, val, pool) diff --git a/includes/llvmlite/__builder.vp b/includes/llvmlite/__builder.vp index 0de1afc..da9cfc5 100644 --- a/includes/llvmlite/__builder.vp +++ b/includes/llvmlite/__builder.vp @@ -1822,10 +1822,25 @@ def build_inline_asm(builder: IRBuilder | t.CPtr, ret_ty: LLVMType | t.CPtr, # ============================================================ # 内部辅助 # ============================================================ +# _append_cstr 写入位置缓存(性能优化:同一缓冲连续追加时 O(1) 定位, +# 避免每次 strlen(dst) 从头扫描导致的 O(n²) —— IR 序列化热点)。 +# 缓冲切换(dst 不同)或缓冲被重置(dst[0]=0 且 pos>0)时自动回退 strlen。 +_g_last_dst: t.CUInt64T = 0 +_g_last_pos: t.CSizeT = 0 + def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): """将 C 字符串 src 追加到 dst 末尾""" + global _g_last_dst, _g_last_pos if dst is None or src is None: return - dlen: t.CSizeT = string.strlen(dst) + dlen: t.CSizeT = 0 + if _g_last_dst == t.CUInt64T(dst): + dlen = _g_last_pos + # 缓冲被重置(调用方 buf[0]=0 后复用同一地址)→ 回到头部 + if dlen > 0 and dst[0] == '\0': + dlen = 0 + else: + dlen = string.strlen(dst) + _g_last_dst = t.CUInt64T(dst) # 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回, # 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到缓冲外 if dlen >= dst_size: @@ -1838,3 +1853,4 @@ def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPt dst[dlen + i] = src[i] i += 1 dst[dlen + i] = '\0' + _g_last_pos = dlen + i diff --git a/includes/llvmlite/__function.vp b/includes/llvmlite/__function.vp index 18a963b..0d52e92 100644 --- a/includes/llvmlite/__function.vp +++ b/includes/llvmlite/__function.vp @@ -785,10 +785,25 @@ def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT, # ============================================================ # 内部辅助 # ============================================================ +# _append_cstr 写入位置缓存(性能优化:同一缓冲连续追加时 O(1) 定位, +# 避免每次 strlen(dst) 从头扫描导致的 O(n²) —— IR 序列化热点)。 +# 缓冲切换(dst 不同)或缓冲被重置(dst[0]=0 且 pos>0)时自动回退 strlen。 +_g_last_dst: t.CUInt64T = 0 +_g_last_pos: t.CSizeT = 0 + def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): """将 C 字符串 src 追加到 dst 末尾""" + global _g_last_dst, _g_last_pos if dst is None or src is None: return - dlen: t.CSizeT = string.strlen(dst) + dlen: t.CSizeT = 0 + if _g_last_dst == t.CUInt64T(dst): + dlen = _g_last_pos + # 缓冲被重置(调用方 buf[0]=0 后复用同一地址)→ 回到头部 + if dlen > 0 and dst[0] == '\0': + dlen = 0 + else: + dlen = string.strlen(dst) + _g_last_dst = t.CUInt64T(dst) # 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回, # 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到缓冲外 if dlen >= dst_size: @@ -801,6 +816,7 @@ def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPt dst[dlen + i] = src[i] i += 1 dst[dlen + i] = '\0' + _g_last_pos = dlen + i # ============================================================ diff --git a/includes/llvmlite/__module.vp b/includes/llvmlite/__module.vp index 3d657fc..1681709 100644 --- a/includes/llvmlite/__module.vp +++ b/includes/llvmlite/__module.vp @@ -691,10 +691,25 @@ def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT, # ============================================================ # 内部辅助 # ============================================================ +# _append_cstr 写入位置缓存(性能优化:同一缓冲连续追加时 O(1) 定位, +# 避免每次 strlen(dst) 从头扫描导致的 O(n²) —— IR 序列化热点)。 +# 缓冲切换(dst 不同)或缓冲被重置(dst[0]=0 且 pos>0)时自动回退 strlen。 +_g_last_dst: t.CUInt64T = 0 +_g_last_pos: t.CSizeT = 0 + def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): """将 C 字符串 src 追加到 dst 末尾""" + global _g_last_dst, _g_last_pos if dst is None or src is None: return - dlen: t.CSizeT = string.strlen(dst) + dlen: t.CSizeT = 0 + if _g_last_dst == t.CUInt64T(dst): + dlen = _g_last_pos + # 缓冲被重置(调用方 buf[0]=0 后复用同一地址)→ 回到头部 + if dlen > 0 and dst[0] == '\0': + dlen = 0 + else: + dlen = string.strlen(dst) + _g_last_dst = t.CUInt64T(dst) # 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回, # 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到缓冲外 if dlen >= dst_size: @@ -706,4 +721,5 @@ def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPt while i < slen and i + 1 < remain: dst[dlen + i] = src[i] i += 1 - dst[dlen + i] = '\0' \ No newline at end of file + dst[dlen + i] = '\0' + _g_last_pos = dlen + i \ No newline at end of file diff --git a/includes/llvmlite/__values.vp b/includes/llvmlite/__values.vp index af44781..f488587 100644 --- a/includes/llvmlite/__values.vp +++ b/includes/llvmlite/__values.vp @@ -104,7 +104,7 @@ def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr, # 用 CRT stdio.snprintf: viperlib 自实现 %g 有小数位反转 bug。 f_bits: t.CInt = 64 match ty: - case llvmlite.LLVMType.Float(ftb): + case LLVMType.Float(ftb): f_bits = ftb fv_bits: t.CUInt64T = 0 c.Load(c.Addr(fv_bits), c.Addr(val)) diff --git a/includes/llvmlite/__verify.vp b/includes/llvmlite/__verify.vp index 1c21e86..04f7733 100644 --- a/includes/llvmlite/__verify.vp +++ b/includes/llvmlite/__verify.vp @@ -78,10 +78,25 @@ def _report_error(result: VerifyResult | t.CPtr, code: t.CInt, msg: t.CChar | t. _append_cstr(result.ErrorBuf, result.ErrorBufSize, "\n") +# _append_cstr 写入位置缓存(性能优化:同一缓冲连续追加时 O(1) 定位, +# 避免每次 strlen(dst) 从头扫描导致的 O(n²) —— IR 序列化热点)。 +# 缓冲切换(dst 不同)或缓冲被重置(dst[0]=0 且 pos>0)时自动回退 strlen。 +_g_last_dst: t.CUInt64T = 0 +_g_last_pos: t.CSizeT = 0 + def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): """将 src 追加到 dst 末尾""" + global _g_last_dst, _g_last_pos if dst is None or src is None: return - dlen: t.CSizeT = string.strlen(dst) + dlen: t.CSizeT = 0 + if _g_last_dst == t.CUInt64T(dst): + dlen = _g_last_pos + # 缓冲被重置(调用方 buf[0]=0 后复用同一地址)→ 回到头部 + if dlen > 0 and dst[0] == '\0': + dlen = 0 + else: + dlen = string.strlen(dst) + _g_last_dst = t.CUInt64T(dst) # 无符号下溢防护:dlen 超过缓冲大小时(缓冲已被破坏/悬空)直接返回, # 否则 remain = dst_size - dlen 下溢成巨值会把 dst[dlen+i] 写穿到缓冲外 if dlen >= dst_size: @@ -94,6 +109,7 @@ def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPt dst[dlen + i] = src[i] i += 1 dst[dlen + i] = '\0' + _g_last_pos = dlen + i # ============================================================ diff --git a/includes/posix.vp b/includes/posix.vp index d98e7ac..3a0d7b5 100644 --- a/includes/posix.vp +++ b/includes/posix.vp @@ -162,57 +162,56 @@ class Dirent(): # ============================================================================= # File operations (10) # ============================================================================= -def open(path: t.CConst | str, oflag: INT, *args) -> INT | t.State: pass -def close(fd: INT) -> INT | t.State: pass -def read(fd: INT, buf: bytes, count: t.CSizeT) -> ssize_t | t.State: pass -def write(fd: INT, buf: t.CConst | bytes, count: t.CSizeT) -> ssize_t | t.State: pass -def lseek(fd: INT, offset: off_t, whence: INT) -> off_t | t.State: pass -def unlink(path: t.CConst | str) -> INT | t.State: pass -def access(path: t.CConst | str, amode: INT) -> INT | t.State: pass -def realpath(path: t.CConst | str, resolved: CHARPTR) -> CHARPTR | t.State: pass -def rename(oldpath: t.CConst | str, newpath: t.CConst | str) -> INT | t.State: pass -def chmod(path: t.CConst | str, mode: mode_t) -> INT | t.State: pass - +extern def open(path: t.CConst | str, oflag: INT, *args) -> INT +extern def close(fd: INT) -> INT +extern def read(fd: INT, buf: bytes, count: t.CSizeT) -> ssize_t +extern def write(fd: INT, buf: t.CConst | bytes, count: t.CSizeT) -> ssize_t +extern def lseek(fd: INT, offset: off_t, whence: INT) -> off_t +extern def unlink(path: t.CConst | str) -> INT +extern def access(path: t.CConst | str, amode: INT) -> INT +extern def realpath(path: t.CConst | str, resolved: CHARPTR) -> CHARPTR +extern def rename(oldpath: t.CConst | str, newpath: t.CConst | str) -> INT +extern def chmod(path: t.CConst | str, mode: mode_t) -> INT # ============================================================================= # stat series (2) # ============================================================================= -def stat(path: t.CConst | str, buf: Stat | t.CPtr) -> INT | t.State: pass -def fstat(fd: INT, buf: Stat | t.CPtr) -> INT | t.State: pass +extern def stat(path: t.CConst | str, buf: Stat | t.CPtr) -> INT +extern def fstat(fd: INT, buf: Stat | t.CPtr) -> INT # ============================================================================= # Directory operations (6) # ============================================================================= -def opendir(name: t.CConst | str) -> DIR | t.CPtr | t.State: pass -def readdir(dirp: DIR | t.CPtr) -> Dirent | t.CPtr | t.State: pass -def closedir(dirp: DIR | t.CPtr) -> INT | t.State: pass -def mkdir(path: t.CConst | str, mode: mode_t) -> INT | t.State: pass -def rmdir(path: t.CConst | str) -> INT | t.State: pass -def getcwd(buf: CHARPTR, size: t.CSizeT) -> CHARPTR | t.State: pass -def chdir(path: t.CConst | str) -> INT | t.State: pass +extern def opendir(name: t.CConst | str) -> DIR | t.CPtr +extern def readdir(dirp: DIR | t.CPtr) -> Dirent | t.CPtr +extern def closedir(dirp: DIR | t.CPtr) -> INT +extern def mkdir(path: t.CConst | str, mode: mode_t) -> INT +extern def rmdir(path: t.CConst | str) -> INT +extern def getcwd(buf: CHARPTR, size: t.CSizeT) -> CHARPTR +extern def chdir(path: t.CConst | str) -> INT # ============================================================================= # Process operations (8) # ============================================================================= -def fork() -> pid_t | t.State: pass -def execvp(file: t.CConst | str, argv: CHARPTR | t.CPtr) -> INT | t.State: pass -def execv(path: t.CConst | str, argv: CHARPTR | t.CPtr) -> INT | t.State: pass -def waitpid(pid: pid_t, status: INT | t.CPtr, options: INT) -> pid_t | t.State: pass -def pipe(fds: INT | t.CPtr) -> INT | t.State: pass -def dup2(oldfd: INT, newfd: INT) -> INT | t.State: pass -def _exit(status: INT) -> t.CVoid | t.State: pass -def getpid() -> pid_t | t.State: pass +extern def fork() -> pid_t +extern def execvp(file: t.CConst | str, argv: CHARPTR | t.CPtr) -> INT +extern def execv(path: t.CConst | str, argv: CHARPTR | t.CPtr) -> INT +extern def waitpid(pid: pid_t, status: INT | t.CPtr, options: INT) -> pid_t +extern def pipe(fds: INT | t.CPtr) -> INT +extern def dup2(oldfd: INT, newfd: INT) -> INT +extern def _exit(status: INT) -> t.CVoid +extern def getpid() -> pid_t # ============================================================================= # Environment operations (4) # ============================================================================= -def getenv(name: t.CConst | str) -> CHARPTR | t.State: pass -def setenv(name: t.CConst | str, value: t.CConst | str, overwrite: INT) -> INT | t.State: pass -def sysconf(name: INT) -> LONG | t.State: pass -def isatty(fd: INT) -> INT | t.State: pass +extern def getenv(name: t.CConst | str) -> CHARPTR +extern def setenv(name: t.CConst | str, value: t.CConst | str, overwrite: INT) -> INT +extern def sysconf(name: INT) -> LONG +extern def isatty(fd: INT) -> INT # ============================================================================= diff --git a/includes/stdarg.vp b/includes/stdarg.vp index 1d0192f..68586b3 100644 --- a/includes/stdarg.vp +++ b/includes/stdarg.vp @@ -1,9 +1,9 @@ import t -def va_start(args: t.CPtr, last_arg: t.CPtr) -> t.State: pass -def va_arg(args: t.CPtr, type: t.CPtr) -> t.CPtr | t.State: pass -def va_end(args: t.CPtr) -> t.State | t.State: pass +extern def va_start(args: t.CPtr, last_arg: t.CPtr) +extern def va_arg(args: t.CPtr, type: t.CPtr) -> t.CPtr +extern def va_end(args: t.CPtr) va_list: t.CTypedef = t.CUnsignedChar | t.CPtr -def arg(type: t.CType) -> t.State: pass \ No newline at end of file +extern def arg(type: t.CType) diff --git a/includes/stdio.vp b/includes/stdio.vp index 5dd3213..a74d249 100644 --- a/includes/stdio.vp +++ b/includes/stdio.vp @@ -1,11 +1,11 @@ import t, c -def printf(fmt: t.CConst | str, *args) -> int | t.State: pass -def fprintf(stream: bytes, fmt: t.CConst | str, *args) -> int | t.State: pass -def sprintf(buf: bytes, fmt: t.CConst | str, *args) -> int | t.State: pass -def snprintf(buf: bytes, size: t.CSizeT, fmt: t.CConst | str, *args) -> int | t.State: pass -def puts(s: t.CConst | str) -> int | t.State: pass -def fputs(s: t.CConst | str, stream: bytes) -> int | t.State: pass -def fgets(buf: bytes, size: int, stream: bytes) -> bytes | t.State: pass -def fflush(stream: bytes) -> int | t.State: pass +extern def printf(fmt: t.CConst | str, *args) -> int +extern def fprintf(stream: bytes, fmt: t.CConst | str, *args) -> int +extern def sprintf(buf: bytes, fmt: t.CConst | str, *args) -> int +extern def snprintf(buf: bytes, size: t.CSizeT, fmt: t.CConst | str, *args) -> int +extern def puts(s: t.CConst | str) -> int +extern def fputs(s: t.CConst | str, stream: bytes) -> int +extern def fgets(buf: bytes, size: int, stream: bytes) -> bytes +extern def fflush(stream: bytes) -> int diff --git a/includes/stdlib.vp b/includes/stdlib.vp index a580043..104b73d 100644 --- a/includes/stdlib.vp +++ b/includes/stdlib.vp @@ -2,9 +2,9 @@ from stdint import * import t -def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass -def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass -def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass -def free(p: t.CVoid | t.CPtr) -> t.State: pass -def system(cmd: t.CConst | t.CChar | t.CPtr) -> INT | t.State: pass -def exit(status: int) -> t.State: pass \ No newline at end of file +extern def malloc(size: t.CSizeT) -> t.CPtr +extern def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CPtr +extern def realloc(p: t.CPtr, size: t.CSizeT) -> t.CPtr +extern def free(p: t.CPtr) +extern def system(cmd: t.CConst | str) -> int +extern def exit(status: int) diff --git a/includes/string.vp b/includes/string.vp index 89981f1..fdaa966 100644 --- a/includes/string.vp +++ b/includes/string.vp @@ -73,7 +73,7 @@ def strlen(src: str) -> t.CSizeT | t.CExport: return length # String comparison function -def strcmp(str1: str, str2: str) -> t.CInt: +def strcmp(str1: str, str2: str) -> int: while str1[0] != '\0' and str2[0] != '\0': if str1[0] != str2[0]: return str1[0] - str2[0] @@ -86,7 +86,7 @@ def samestr(str1: str, str2: str) -> bool: # String compare function with limited length -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: +def strncmp(str1: str, str2: str, n: t.CSizeT) -> int: i: t.CSizeT = 0 while str1[0] != '\0' and str2[0] != '\0' and i < n: if str1[0] != str2[0]: @@ -100,19 +100,19 @@ def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: # Memory compare function -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> int: p1: BYTEPTR = BYTEPTR(ptr1) p2: BYTEPTR = BYTEPTR(ptr2) i: t.CSizeT = 0 while i < n: if p1[i] != p2[i]: - return t.CInt(p1[i]) - t.CInt(p2[i]) + return int(p1[i]) - int(p2[i]) i += 1 return 0 # String find function -def strchr(s: str, cr: t.CInt) -> str: +def strchr(s: str, cr: int) -> str: while s[0] != '\0': if s[0] == t.CChar(cr): return str(s) @@ -122,7 +122,7 @@ def strchr(s: str, cr: t.CInt) -> str: return None # String reverse find function (find last occurrence of character) -def strrchr(s: str, cr: t.CInt) -> str: +def strrchr(s: str, cr: int) -> str: last: str = None while s[0] != '\0': if s[0] == t.CChar(cr): @@ -164,7 +164,7 @@ def strspn(s: str, skip: str = " ") -> int: return si # Memory set function -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: +def memset(ptr: t.CVoid | t.CPtr, value: int, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: # Original implementation: # p: BYTEPTR = BYTEPTR(ptr) # i: t.CSizeT @@ -248,9 +248,9 @@ def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.C return dest -def atoi(src: str) -> t.CInt: - num: t.CInt = 0 - sign: t.CInt = 1 +def atoi(src: str) -> int: + num: int = 0 + sign: int = 1 s: str = src if s == None: return 0 # 跳过空白 @@ -264,7 +264,7 @@ def atoi(src: str) -> t.CInt: s += 1 for ch in s: if ch < '0' or ch > '9': break - digit: t.CInt = ch - '0' + digit: int = ch - '0' num = num * 10 + digit return num * sign @@ -282,13 +282,13 @@ def atoll(src: str) -> t.CInt64T: elif s[0] == '+': s += 1 # 十六进制前缀 0x / 0X - is_hex: t.CInt = 0 + is_hex: int = 0 if s[0] == '0' and (s[1] == 'x' or s[1] == 'X'): is_hex = 1 s += 2 if is_hex: for ch in s: - d: t.CInt = 0 + d: int = 0 if ch >= '0' and ch <= '9': d = ch - '0' elif ch >= 'a' and ch <= 'f': @@ -302,7 +302,7 @@ def atoll(src: str) -> t.CInt64T: else: for ch in s: if ch < '0' or ch > '9': break - d: t.CInt = ch - '0' + d: int = ch - '0' digit: t.CInt64T = t.CInt64T(d) num = num * 10 + digit return num * sign @@ -325,7 +325,7 @@ def atof(src: str) -> t.CDouble: int_part: t.CDouble = 0.0 for ch in s: if ch < '0' or ch > '9': break - d1: t.CInt = ch - '0' + d1: int = ch - '0' int_part = int_part * 10.0 + t.CDouble(d1) s += 1 # 小数部分 @@ -335,13 +335,13 @@ def atof(src: str) -> t.CDouble: s += 1 for ch in s: if ch < '0' or ch > '9': break - d2: t.CInt = ch - '0' + d2: int = ch - '0' frac_div = frac_div * 10.0 frac_part = frac_part * 10.0 + t.CDouble(d2) s += 1 # 指数部分 - exp: t.CInt = 0 - exp_sign: t.CInt = 1 + exp: int = 0 + exp_sign: int = 1 if s[0] == 'e' or s[0] == 'E': s += 1 if s[0] == '-': @@ -351,7 +351,7 @@ def atof(src: str) -> t.CDouble: s += 1 for ch in s: if ch < '0' or ch > '9': break - d3: t.CInt = ch - '0' + d3: int = ch - '0' exp = exp * 10 + d3 s += 1 exp = exp * exp_sign @@ -368,7 +368,7 @@ def atof(src: str) -> t.CDouble: return result -def atof_out(src: str, out: t.CDouble | t.CPtr) -> t.CInt: +def atof_out(src: str, out: t.CDouble | t.CPtr) -> int: """atof 结果写入 out[0](输出参数方式,避免跨模块 double 返回值传递 bug) 返回值仅表示成功与否(1=成功,0=失败),结果值通过 out 指针传递, diff --git a/includes/sys.vp b/includes/sys.vp index 251a776..8f29169 100644 --- a/includes/sys.vp +++ b/includes/sys.vp @@ -20,12 +20,10 @@ _mbuddy: memhub.MemBuddy | t.CPtr # C Standard Library IO Declarations # ============================================================================= -def fgets(buf: bytes, size: int, stream: t.CVoid | t.CPtr) -> str | t.State: pass - -def fflush(stream: t.CVoid | t.CPtr) -> int | t.State: pass - +extern def fgets(buf: bytes, size: int, stream: t.CVoid | t.CPtr) -> str +extern def fflush(stream: t.CVoid | t.CPtr) -> int # C standard library exit (terminates the process after flushing the buffer, cross-platform) -def exit(status: int) -> t.State: pass +extern def exit(status: int) # =============================================================================