refactor(gen): R12/R13 同步——下标 while 循环改 for range、去 c.Set

与 includes 同步执行两批源改写:R12 把「i: int = 0 与 while i < N: … i += 1」形式的计数循环改写为「for i in range(N):」;R13 把 c.Set(*p, v) 迁移为 *p = v、c.Set(a, b) 迁移为 a = b(c.Set 是正在退化的路径)。

验证:bootstrap 三重重编 SUCCESS(无 vast_c 解析回退);全量 77/77 顺序回归通过(WebTest 首轮网络超时,单独重跑通过)。
This commit is contained in:
TermiNexus committed 2026-10-05 15:33:58 +08:00
1 parent a7b8118ce8
commit fb53f88893
25 files changed
+133 -345

No files matched your search

+12 -36
View File
@@ -940,12 +940,10 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, linker_cmd: str, link
dt2len: sizet = dj - ds2
if dt2len == dtlen:
deq: int = 1
dk: sizet = 0
while dk < dtlen:
for dk in range(dtlen):
if dedup[ds2 + dk] != obj_paths[dstart + dk]:
deq = 0
break
dk += 1
if deq != 0:
ddup = 1
break
@@ -1304,18 +1302,14 @@ def _tb_quoted_after(mb: memhub.MemBuddy*, s: str, key: str) -> str:
def _tb_dir_lookup(dirs: bytes, count: int, idx: int) -> str:
i: int = 0
while i < count:
for i in range(count):
if int(_tb_rd_u32(dirs, sizet(i) * TB_DIR_SIZE)) == idx: return rawptr(_tb_rd_u64(dirs, sizet(i) * TB_DIR_SIZE + 8))
i += 1
return None
def _tb_file_rec(files: bytes, count: int, idx: int) -> int:
i: int = 0
while i < count:
for i in range(count):
if int(_tb_rd_u32(files, sizet(i) * TB_FILE_SIZE)) == idx: return i
i += 1
return -1
@@ -1407,11 +1401,9 @@ def _tb_func_name_for(fbuf: bytes, fcount: int, rva: uint64) -> str:
def _tb_intern(p: TbPool*, s: str) -> uint64:
"""Intern s into the pool (linear scan; keeps offset 0 as the empty sentinel)."""
if p is None or s is None: return 0
k: int = 0
while k < p.OffCount:
for k in range(p.OffCount):
o: uint64 = _tb_rd_u64(p.Offs, sizet(k) * 8)
if string.strcmp(p.Pool + sizet(o), s) == 0: return o
k += 1
off: uint64 = uint64(p.PoolLen)
n: sizet = string.strlen(s)
string.memcpy(p.Pool + sizet(off), s, n)
@@ -1456,8 +1448,7 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*:
min_rva: uint64 = 0xFFFFFFFF
found_text: int = 0
have_sec: int = 0
si: uint64 = 0
while si < nsec:
for si in range(nsec):
base: sizet = sec_off + sizet(si) * 40
if uint64(base) + 40 > uint64(got): break
va: uint64 = uint64(_tb_rd_u32(head, base + 12))
@@ -1466,7 +1457,6 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*:
if _tb_cc(head, base) == 46 and _tb_cc(head, base + 1) == 116 and _tb_cc(head, base + 2) == 101 and _tb_cc(head, base + 3) == 120 and _tb_cc(head, base + 4) == 116:
text_rva = va
found_text = 1
si += 1
if found_text == 0 and have_sec != 0 and min_rva != 0xFFFFFFFF: text_rva = min_rva
lay.ImageBase = img_base
lay.SizeOfImage = size_img
@@ -1752,8 +1742,7 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int)
if grp is None or cap <= 0 or caller is None or callee is None: return -1
mask: uint64 = uint64(cap - 1)
hv: uint64 = (_tb_strhash(caller) * 0x100000001B3 + _tb_strhash(callee)) & mask
i: int = 0
while i < cap:
for i in range(cap):
slot: int = int((hv + uint64(i)) & mask)
off: sizet = sizet(slot) * TB_GRP_SIZE
if uint64(_tb_rd_u32(grp, off + TB_GRP_OFF_USED)) == 0:
@@ -1768,7 +1757,6 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int)
sc: str = rawptr(_tb_rd_u64(grp, off + TB_GRP_OFF_CALLER))
sk: str = rawptr(_tb_rd_u64(grp, off + TB_GRP_OFF_CALLEE))
if sc is not None and sk is not None and string.strcmp(sc, caller) == 0 and string.strcmp(sk, callee) == 0: return slot
i += 1
return -1
@@ -1910,13 +1898,11 @@ def _tb_parse_vpcall_file(mb: memhub.MemBuddy*, path: str, cp: TbCallParse*) ->
def _tb_load_vpcalls(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int:
if _tb_vpcall_buf is None or _tb_vpcall_n <= 0: return 0
k: int = 0
while k < _tb_vpcall_n:
for k in range(_tb_vpcall_n):
slot: str* = (str*)(uint64(_tb_vpcall_buf) + sizet(k) * 8)
path: str = slot[0]
if path is not None:
if _tb_parse_vpcall_file(mb, path, cp) != 0: return 1
k += 1
return 0
@@ -1929,8 +1915,7 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int:
VLogger.error("--traceback: 调用点分组表分配失败,终止编译", "TRACEBACK")
return 1
string.memset(cp.Grp, 0, sizet(cp.GrpCap) * TB_GRP_SIZE)
i: int = 0
while i < cp.CrN:
for i in range(cp.CrN):
off: sizet = sizet(i) * TB_CR_SIZE
caller: str = rawptr(_tb_rd_u64(cp.Cr, off + TB_CR_OFF_CALLER))
callee: str = rawptr(_tb_rd_u64(cp.Cr, off + TB_CR_OFF_CALLEE))
@@ -1948,7 +1933,6 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int:
_tb_wr_u32(cp.Cr, toff + TB_CR_OFF_NEXT, uint64(i))
_tb_wr_u32(cp.Cr, off + TB_CR_OFF_NEXT, uint64(TB_IDX_NONE))
_tb_wr_u32(cp.Grp, goff + TB_GRP_OFF_TAIL, uint64(i))
i += 1
return 0
@@ -1972,15 +1956,13 @@ def _tb_emit_call_row(mb: memhub.MemBuddy*, d: TbDump*, cp: TbCallParse*, img_lo
def _tb_emit_entry_row(mb: memhub.MemBuddy*, d: TbDump*, cp: TbCallParse*, img_lo: uint64, addr: uint64, sym: str) -> int:
"""Emit a fallback function-entry row for an objdump label sym (file/line from the F record)."""
if sym is None or cp.Fr is None or cp.FrN <= 0 or addr < img_lo: return 0
i: int = 0
while i < cp.FrN:
for i in range(cp.FrN):
off: sizet = sizet(i) * TB_FR_SIZE
s: str = rawptr(_tb_rd_u64(cp.Fr, off + TB_FR_OFF_SYM))
if s is not None and string.strcmp(s, sym) == 0:
file: str = rawptr(_tb_rd_u64(cp.Fr, off + TB_FR_OFF_FILE))
dl: int = int(_tb_rd_u32(cp.Fr, off + TB_FR_OFF_DEFLINE))
return _tb_emit_row(mb, d, addr, file, dl, sym)
i += 1
return 0
@@ -2298,8 +2280,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
if ro is None:
VLogger.error("--traceback: 记录偏移缓冲分配失败,终止编译", "TRACEBACK")
return 1
i = 0
while i < uniq:
for i in range(uniq):
pth2: str = rawptr(_tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FILE))
foff: uint64 = _tb_intern(p, pth2)
noff: uint64 = 0
@@ -2311,7 +2292,6 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
if nm2 is not None: noff = _tb_intern(p, nm2)
_tb_wr_u32(ro, sizet(i) * 8, foff)
_tb_wr_u32(ro, sizet(i) * 8 + 4, noff)
i += 1
# ---- 5) self-checks (mirror the runtime LoadMapFile validation) ----
prev_rva: uint64 = 0
@@ -2335,13 +2315,11 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
return 1
# file_off must be >= 1: offset 0 is the empty-string sentinel and the runtime
# rejects a whole map whose record file_off is 0.
ci = 0
while ci < uniq:
for ci in range(uniq):
fo: uint64 = uint64(_tb_rd_u32(ro, sizet(ci) * 8))
if fo == 0:
VLogger.error("--traceback 自检失败:存在 file_off==0 的记录(空路径,运行期会拒绝该旁文件),终止编译", "TRACEBACK")
return 1
ci += 1
# ---- 6) serialise and write <exe>.stackmap ----
total: sizet = 20 + sizet(uniq) * 20 + sizet(p.PoolLen)
@@ -2357,8 +2335,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
_tb_wr_u32(out, 8, uint64(uniq))
_tb_wr_u32(out, 12, uint64(p.OffCount))
_tb_wr_u32(out, 16, uint64(p.PoolLen))
ri2: int = 0
while ri2 < uniq:
for ri2 in range(uniq):
roff2: sizet = 20 + sizet(ri2) * 20
rv3: uint64 = _tb_rd_u64(d.RowBuf, sizet(ri2) * TB_ROW_SIZE)
ln3: uint64 = uint64(_tb_rd_u32(d.RowBuf, sizet(ri2) * TB_ROW_SIZE + TB_ROW_OFF_LINE))
@@ -2366,7 +2343,6 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
_tb_wr_u32(out, roff2 + 8, uint64(_tb_rd_u32(ro, sizet(ri2) * 8)))
_tb_wr_u32(out, roff2 + 12, ln3)
_tb_wr_u32(out, roff2 + 16, uint64(_tb_rd_u32(ro, sizet(ri2) * 8 + 4)))
ri2 += 1
string.memcpy(out + 20 + sizet(uniq) * 20, p.Pool, sizet(p.PoolLen))
map_len: sizet = string.strlen(exe_path) + 16
+2 -6
View File
@@ -267,8 +267,7 @@ def _normalize_path(path: str) -> str:
seg_start: sizet = 0
out_len: sizet = 0
has_seg: int = 0
i: sizet = 0
while i <= plen:
for i in range(plen + 1):
ch: char = '\0'
if i < plen: ch = path[i]
if ch == '/' or ch == '\\' or ch == '\0':
@@ -313,7 +312,6 @@ def _normalize_path(path: str) -> str:
jj += 1
has_seg = 1
seg_start = i + 1
i += 1
if has_seg == 0:
# All segments consumed (e.g. ./..): return current dir
return "./"
@@ -577,8 +575,7 @@ def slice_subdir(sha1: str, level: int) -> str:
buf: str = _mbuddy.alloc(buf_len)
if buf is None: return None
pos: int = 0
i: int = 0
while i < level:
for i in range(level):
if i > 0:
buf[pos] = '/'
pos += 1
@@ -586,6 +583,5 @@ def slice_subdir(sha1: str, level: int) -> str:
buf[pos] = sha1[idx]
buf[pos + 1] = sha1[idx + 1]
pos += 2
i += 1
buf[pos] = '\0'
return buf
+14 -38
View File
@@ -98,7 +98,7 @@ def _lookup_cdefine_for_pyi(name: str) -> int64:
global _g_pyi_cdefine_found
# Look up this file's CDefine cache first (globals are empty during vpi gen)
if _g_pyi_cdef_names is not None and _g_pyi_cdef_vals is not None:
# Bound loop by _g_pyi_cdef_count; never len()/.get on i8** (len falls back
# Bound loop by _g_pyi_cdef_count; never len()/.get on i8** (len falls back
# to strlen, .get misdispatches to HashTable.get) -- index via t.CPtr(base + i*8).
pn: sizet = sizet(_g_pyi_cdef_count)
for pi in range(pn):
@@ -160,10 +160,8 @@ def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet, text: str) -> sizet:
# _PyiIndent - append level*4 spaces to buf at pos
def _PyiIndent(buf: bytes, buf_size: sizet, pos: sizet, level: int) -> sizet:
"""Append level*4 spaces to buf at pos and return the new pos"""
i: int = 0
while i < level:
for i in range(level):
pos = _PyiEmit(buf, buf_size, pos, " ")
i += 1
return pos
@@ -249,8 +247,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
cmps_ct: list[ast.AST*]* = cmp_t.comparators
if ops_ct is not None:
on_ct: sizet = len(ops_ct)
oi_ct: sizet = 0
while oi_ct < on_ct:
for oi_ct in range(on_ct):
oid_ct: int = ops_ct.get(oi_ct)
if oid_ct == ast.OpKind.Eq: pos = _PyiEmit(buf, buf_size, pos, " == ")
elif oid_ct == ast.OpKind.Ne: pos = _PyiEmit(buf, buf_size, pos, " != ")
@@ -262,7 +259,6 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
# TPC indexes comparators[i] by ops; guard the length here so a
# malformed AST (unequal ops/comparators) cannot overrun.
if cmps_ct is not None and oi_ct < len(cmps_ct): pos = _PyiTypeStr(buf, buf_size, pos, cmps_ct.get(oi_ct), depth + 1)
oi_ct += 1
return pos
# BoolOp: boolean ops (ENABLED and MAX_SIZE > 0 / A or B).
@@ -272,13 +268,11 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
vals_bt: list[ast.AST*]* = bool_t.values
if vals_bt is not None:
vn_bt: sizet = len(vals_bt)
vi_bt: sizet = 0
while vi_bt < vn_bt:
for vi_bt in range(vn_bt):
if vi_bt > 0:
if bool_t.op == ast.OpKind.Or: pos = _PyiEmit(buf, buf_size, pos, " or ")
else: pos = _PyiEmit(buf, buf_size, pos, " and ")
pos = _PyiTypeStr(buf, buf_size, pos, vals_bt.get(vi_bt), depth + 1)
vi_bt += 1
return pos
# Constant: string forward refs (e.g. 'MyClass'), None or numeric constants
@@ -309,12 +303,10 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
if lst.elts is not None:
lst_elts: list[ast.AST*]* = lst.elts
ln: sizet = len(lst_elts)
li: sizet = 0
while li < ln:
for li in range(ln):
if li > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
le: ast.AST* = lst_elts.get(li)
pos = _PyiTypeStr(buf, buf_size, pos, le, depth + 1)
li += 1
pos = _PyiEmit(buf, buf_size, pos, "]")
return pos
@@ -324,12 +316,10 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
if tup.elts is not None:
tup_elts: list[ast.AST*]* = tup.elts
tn: sizet = len(tup_elts)
ti: sizet = 0
while ti < tn:
for ti in range(tn):
if ti > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
el: ast.AST* = tup_elts.get(ti)
pos = _PyiTypeStr(buf, buf_size, pos, el, depth + 1)
ti += 1
return pos
# Call: call expression (used by decorators such as @t.NoVTable())
@@ -340,12 +330,10 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
if cl.args is not None:
cl_args: list[ast.AST*]* = cl.args
can: sizet = len(cl_args)
cai: sizet = 0
while cai < can:
for cai in range(can):
if cai > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
ca: ast.AST* = cl_args.get(cai)
pos = _PyiTypeStr(buf, buf_size, pos, ca, depth + 1)
cai += 1
pos = _PyiEmit(buf, buf_size, pos, ")")
return pos
@@ -437,15 +425,13 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet, fn: ast.FunctionDef*,
if fn.decorator_list is not None:
fn_decorator_list: list[ast.AST*]* = fn.decorator_list
dn: sizet = len(fn_decorator_list)
di: sizet = 0
while di < dn:
for di in range(dn):
dec: ast.AST* = fn_decorator_list.get(di)
if dec is not None:
pos = _PyiIndent(buf, buf_size, pos, indent_level)
pos = _PyiEmit(buf, buf_size, pos, "@")
pos = _PyiTypeStr(buf, buf_size, pos, dec)
pos = _PyiEmit(buf, buf_size, pos, "\n")
di += 1
pos = _PyiIndent(buf, buf_size, pos, indent_level)
pos = _PyiEmit(buf, buf_size, pos, "def ")
@@ -521,15 +507,13 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, cls: ast.ClassDef*, inden
if cls.decorator_list is not None:
cls_decorator_list: list[ast.AST*]* = cls.decorator_list
dcn: sizet = len(cls_decorator_list)
dci: sizet = 0
while dci < dcn:
for dci in range(dcn):
ddec: ast.AST* = cls_decorator_list.get(dci)
if ddec is not None:
pos = _PyiIndent(buf, buf_size, pos, indent_level)
pos = _PyiEmit(buf, buf_size, pos, "@")
pos = _PyiTypeStr(buf, buf_size, pos, ddec)
pos = _PyiEmit(buf, buf_size, pos, "\n")
dci += 1
pos = _PyiIndent(buf, buf_size, pos, indent_level)
pos = _PyiEmit(buf, buf_size, pos, "class ")
@@ -543,12 +527,10 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, cls: ast.ClassDef*, inden
tpn: sizet = len(cls_type_params)
if tpn > 0:
pos = _PyiEmit(buf, buf_size, pos, "[")
tpi: sizet = 0
while tpi < tpn:
for tpi in range(tpn):
if tpi > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
tpname: str = cls_type_params.get(tpi)
if tpname is not None: pos = _PyiEmit(buf, buf_size, pos, tpname)
tpi += 1
pos = _PyiEmit(buf, buf_size, pos, "]")
# Base classes
@@ -557,12 +539,10 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, cls: ast.ClassDef*, inden
bn: sizet = len(cls_bases)
if bn > 0:
pos = _PyiEmit(buf, buf_size, pos, "(")
bi: sizet = 0
while bi < bn:
for bi in range(bn):
if bi > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
base: ast.AST* = cls_bases.get(bi)
pos = _PyiTypeStr(buf, buf_size, pos, base)
bi += 1
pos = _PyiEmit(buf, buf_size, pos, ")")
pos = _PyiEmit(buf, buf_size, pos, ":\n")
@@ -736,8 +716,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
if imp2.names is not None:
imp2_names: list[ast.AST*]* = imp2.names
an2: sizet = len(imp2_names)
ai2: sizet = 0
while ai2 < an2:
for ai2 in range(an2):
if ai2 > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
al2: ast.Alias* = ast.Alias*(imp2_names.get(ai2))
# fail-fast: never silently write "import , ". Import names are the
@@ -750,7 +729,6 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
if al2.asname is not None and string.strlen(al2.asname) > 0:
pos = _PyiEmit(buf, buf_size, pos, " as ")
pos = _PyiEmit(buf, buf_size, pos, al2.asname)
ai2 += 1
pos = _PyiEmit(buf, buf_size, pos, "\n")
# ImportFrom statement
@@ -770,8 +748,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
if ifr.names is not None:
ifr_names: list[ast.AST*]* = ifr.names
an3: sizet = len(ifr_names)
ai3: sizet = 0
while ai3 < an3:
for ai3 in range(an3):
if ai3 > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
al3: ast.Alias* = ast.Alias*(ifr_names.get(ai3))
# fail-fast: same as Import (report the two causes separately).
@@ -783,7 +760,6 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
if al3.asname is not None and string.strlen(al3.asname) > 0:
pos = _PyiEmit(buf, buf_size, pos, " as ")
pos = _PyiEmit(buf, buf_size, pos, al3.asname)
ai3 += 1
pos = _PyiEmit(buf, buf_size, pos, "\n")
# Function definition (_PyiFunction already ends with a newline)
@@ -827,7 +803,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
viperlib.snprintf(num_buf, 32, " = %lld", cv.int_val)
pos = _PyiEmit(buf, buf_size, pos, num_buf)
elif cv.const_kind == ast.CONST_FLOAT:
# Float CDefines (e.g. numpy pi/e) must emit a value or read-back
# Float CDefines (e.g. numpy pi/e) must emit a value or read-back
# degrades to a global pointer; %.17g round-trips double exactly.
fbuf_c: bytes = mb.alloc(64)
if fbuf_c is not None:
+5 -15
View File
@@ -148,8 +148,7 @@ def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes, cap: int, key:
h: uint64 = _vpi_idx_hash(key)
mask: sizet = sizet(cap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < cap:
for i in range(cap):
slot: sizet* = _vpi_idx_slot(idx_base, si)
sv: sizet = slot[0]
if sv == 0: return -1
@@ -157,7 +156,6 @@ def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes, cap: int, key:
ek: bytes = keys + se * key_stride
if string.strcmp(ek, key) == 0: return se
si = (si + 1) & mask
i += 1
return -1
@@ -167,14 +165,12 @@ def _vpi_idx_insert(idx_base: bytes, cap: int, slot_index: int, key: bytes) -> i
h: uint64 = _vpi_idx_hash(key)
mask: sizet = sizet(cap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < cap:
for i in range(cap):
slot: sizet* = _vpi_idx_slot(idx_base, si)
if slot[0] == 0:
slot[0] = sizet(slot_index + 1)
return 0
si = (si + 1) & mask
i += 1
return 1
@@ -839,13 +835,11 @@ def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str, seg_
prm: str = _lookup_vpi_param_annots(src_sha1, cls_name, method_name)
if prm is None or prm[0] == '\0': return 0
cur: sizet = 0
seg: int = 0
# locate segment start: skip seg_idx '@'-separated segments
while seg < seg_idx:
for seg in range(seg_idx):
while prm[cur] != '\0' and prm[cur] != '@': cur += 1
if prm[cur] == '\0': return 0
cur += 1
seg += 1
slen: sizet = 0
while prm[cur + slen] != '\0' and prm[cur + slen] != '@': slen += 1
wlen: sizet = string.strlen(want)
@@ -1053,10 +1047,8 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, seg: str) -> mlirlite.L
star_off_ps: sizet = string.strlen(star_buf_ps)
string.strncpy(star_buf_ps + star_off_ps, seg, star_base_end_ps)
star_buf_ps[star_off_ps + star_base_end_ps] = '\0'
star_k_ps = 0
while star_k_ps < star_cnt_ps:
for star_k_ps in range(star_cnt_ps):
string.strcat(star_buf_ps, "]")
star_k_ps += 1
star_ty_ps: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, star_buf_ps)
stdlib.free(star_buf_ps)
return star_ty_ps
@@ -1307,10 +1299,8 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: m
if cptr_sub_lvl > 0:
if first_ty is None: return cptr_sub_ty
res_ty_cs: mlirlite.LLVMType* = first_ty
wrap_i_cs: int = 0
while wrap_i_cs < cptr_sub_lvl:
for wrap_i_cs in range(cptr_sub_lvl):
res_ty_cs = mlirlite.Ptr(pool, res_ty_cs)
wrap_i_cs += 1
return res_ty_cs
if has_cvoid != 0:
# t.CVoid | t.State: State is a decorator marker (ignored), t.CVoid -> void.
+2 -6
View File
@@ -416,12 +416,10 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str:
if colon < total_len and from_imports[colon] == ':' and local_len == alias_len:
# compare local_name == alias
Matched: int = 1
li: sizet = 0
while li < alias_len:
for li in range(alias_len):
if from_imports[ci + li] != alias[li]:
Matched = 0
break
li += 1
if Matched == 1:
# extract module (from colon+1 to next ':' or space)
m_start: sizet = colon + 1
@@ -459,12 +457,10 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str:
if colon < total_len and from_imports[colon] == ':' and local_len == alias_len:
# compare local_name == alias
Matched: int = 1
li: sizet = 0
while li < alias_len:
for li in range(alias_len):
if from_imports[ci + li] != alias[li]:
Matched = 0
break
li += 1
if Matched == 1:
# extract module (from colon+1 to next ':' or space)
m_start: sizet = colon + 1
+1 -3
View File
@@ -721,15 +721,13 @@ novirtual class AssignGenMixin:
n_s: sizet = string.strlen(sv_s)
if sizet(arr_count) < n_s:
self.Gen.TypeGenErr.fatal_error(list_node, f"字符串字面量长度 {n_s} 超过字符数组声明长度 {arr_count},不允许越界写入", "OverflowError")
bi_s: sizet = 0
while bi_s < n_s:
for bi_s in range(n_s):
bidx_s: mlirlite.Value* = mlirlite.const_int32(pool, bi_s)
bp_s: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, array_alloca, bidx_s)
if bp_s is None: break
bvv: mlirlite.Value* = mlirlite.const_int32(pool, sv_s[bi_s])
bsv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, bvv, elem_ty, e0_s)
mlirlite.build_store(builder, bsv, bp_s)
bi_s += 1
return 0
# Element count exceeds declared length: fail fast (avoid out-of-range GEP writes)
+3 -7
View File
@@ -182,12 +182,10 @@ novirtual class CallGenBase:
fl2_od: sizet = fend_od - fstart_od
if fl2_od == name_len:
fd_eq_od: int = 1
fdi_od: sizet = 0
while fdi_od < fl2_od:
for fdi_od in range(fl2_od):
if buf[fstart_od + fdi_od] != func_name[fdi_od]:
fd_eq_od = 0
break
fdi_od += 1
if fd_eq_od != 0: has_own_def = 1
continue
# line must start with "from "
@@ -455,7 +453,7 @@ novirtual class CallGenBase:
while cur is not None:
cur_name: str = mlirlite.function_get_name(cur)
if cur_name is not None:
# fast path: skip strcmp when first chars differ (mangled names start
# fast path: skip strcmp when first chars differ (mangled names start
# with sha1 hex, bare names with letters/underscore)
if cur_name[0] == name[0] and string.strcmp(cur_name, name) == 0: return cur
# use Function.NameLen (computed once) instead of per-node strlen
@@ -760,10 +758,8 @@ novirtual class CallGenBase:
stdlib.free(nm_buf)
if nm_ty is not None:
nm_wrap: mlirlite.LLVMType* = nm_ty
nm_i: int = 0
while nm_i < nm_star:
for nm_i in range(nm_star):
nm_wrap = mlirlite.Ptr(pool, nm_wrap)
nm_i += 1
return nm_wrap
# contains "*" -> generic i8* (i8*, i32*, { i32, i8 }*, unregistered %name*)
+5 -11
View File
@@ -744,7 +744,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
if base_pfx_g != 0: base_clean_g = base_buf_g + sizet(base_pfx_g)
spec_name_g: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_clean_g, ta_list_g)
if spec_name_g is not None:
# Re-lookup the specialized function after specialization;
# Re-lookup the specialized function after specialization;
# find_func_in_module matches both bare and tpl-prefixed names.
spec_lk_g: str = pool.alloc(string.strlen(class_name) + string.strlen(method_name) + 2)
if spec_lk_g is not None:
@@ -871,7 +871,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
kwc: sizet = 0
if kw_calls is not None: kwc = len(kw_calls)
# Multi-inheritance this-adjust (byte-offset): delta = field offset in the
# Multi-inheritance this-adjust (byte-offset): delta = field offset in the
# subclass minus in the parent layout; delta>0 GEPs and bitcasts to the parent.
self_arg: mlirlite.Value* = obj_ptr
if mc_anc is not None and string.strcmp(mc_anc, class_name) != 0:
@@ -887,15 +887,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
# fields, so this needs no byte adjust; pass it through unchanged.
if anc_entry_th is not None and anc_entry_th.FieldCount > 0:
anc_first_name_th: str = None
afi_th: int = 0
while afi_th < anc_entry_th.FieldCount:
for afi_th in range(anc_entry_th.FieldCount):
afe_th: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(anc_entry_th, afi_th)
if afe_th is not None:
afn_th: str = self.Gen.StructGen.get_field_name_ptr(afe_th)
if afn_th is not None and string.strcmp(afn_th, "__vtable__") != 0:
anc_first_name_th = afn_th
break
afi_th += 1
if anc_first_name_th is not None:
sub_entry_th: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(class_name)
if sub_entry_th is not None:
@@ -1442,15 +1440,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
anc_entry_sp: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(anc)
if anc_entry_sp is not None and anc_entry_sp.FieldCount > 0:
first_name_sp: str = None
afi_sp: int = 0
while afi_sp < anc_entry_sp.FieldCount:
for afi_sp in range(anc_entry_sp.FieldCount):
afe_sp: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(anc_entry_sp, afi_sp)
if afe_sp is not None:
afn_sp: str = self.Gen.StructGen.get_field_name_ptr(afe_sp)
if afn_sp is not None and string.strcmp(afn_sp, "__vtable__") != 0:
first_name_sp = afn_sp
break
afi_sp += 1
if first_name_sp is not None:
sub_entry_sp: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(cur_class)
if sub_entry_sp is not None:
@@ -1563,12 +1559,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
e: GenTypes.StructEntry* = self.Gen.StructGen._get_struct_entry(j)
if e is not None and e.Name is not None:
pc: int = self.Gen.StructGen.get_parent_count(e.Name)
pj: int = 0
while pj < pc:
for pj in range(pc):
pn: str = self.Gen.StructGen.get_parent_name_at(e.Name, pj)
if pn is not None:
if string.strcmp(pn, class_name) == 0: return 1
pj += 1
j += 1
return 0
+5 -7
View File
@@ -170,7 +170,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
# in translate_constant, else coercing an inttoptr char value as a pointer crashes).
fe: GenTypes.FieldEntry* = None
if ctor_entry is not None:
# Field 0 is __vtable__ (vtable pointer placeholder): ctor args must skip it,
# Field 0 is __vtable__ (vtable pointer placeholder): ctor args must skip it,
# else an arg overwrites the vtable slot and isinstance/dispatch break.
target_idx: int = 0
for fi in range(ctor_entry.FieldCount):
@@ -494,7 +494,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if val_bits == 1:
# i1 is a boolean (from icmp/fcmp) with unsigned semantics; must zext
return mlirlite.build_zext(builder, val, target_ty)
# Unify the widening direction (same source as coerce_to_type's _zext_or_sext_val):
# Unify the widening direction (same source as coerce_to_type's _zext_or_sext_val):
# i1/i8 -> zext; unsigned source -> zext; else sext (keeps the source's signedness).
if self.Gen.ExprGenBase._zext_or_sext_val(pool, val, src_node, trans) != 0: return mlirlite.build_zext(builder, val, target_ty)
return mlirlite.build_sext(builder, val, target_ty)
@@ -558,7 +558,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
tn = self.Gen.TypeGenResolve._norm_type_arg_name(pool, tn_raw, from_imports)
if tn is not None: result.append(tn)
return result
# Generic-class ctor helper list[str](pool, 8): reuse translate_list_literal's flow (alloca,
# Generic-class ctor helper list[str](pool, 8): reuse translate_list_literal's flow (alloca,
# arg array, __new__ -> __before_init__ -> __init__). Must not go through the normal call path.
# _ptr_layer_type_arg - add the pointer layer (`*`) to inferred type args so the ctor side
@@ -784,7 +784,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty)
if tmp is None: return None
# Translate args into a pointer array (extra_args[slot]): positional args -> slots
# Translate args into a pointer array (extra_args[slot]): positional args -> slots
# 0..can-1; keywords -> slot by __init__ param name. Positional wins; order must not be assumed.
cargs: list[ast.AST*]* = cl.args
can: sizet = 0
@@ -840,12 +840,10 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
if slot_kw > arg_max_filled: arg_max_filled = slot_kw
# Slots must be contiguous (0..arg_max_filled all filled): a hole means a param
# got neither positional nor keyword arg. Never pass the hole as 0; fail-fast.
ci_hole: int = 0
while ci_hole <= arg_max_filled:
for ci_hole in range(arg_max_filled + 1):
if arg_filled[sizet(ci_hole)] == 0:
self.Gen.TypeGenErr.fatal_error(cl, f"泛型类 '{tmpl_name}' 的关键字构造缺少前置形参(第 {ci_hole + 1} 个实参位置既无位置实参也无关键字实参)", "TypeError")
break
ci_hole += 1
arg_count: int = 0
if arg_max_filled >= 0: arg_count = arg_max_filled + 1
+1 -3
View File
@@ -171,8 +171,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
head: mlirlite.Value* = None
tail: mlirlite.Value* = None
fp: mlirlite.Param* = mlirlite.function_get_param_head(func)
ai: sizet = 0
while ai < can:
for ai in range(can):
arg: ast.AST* = cargs.get(ai)
fpty: mlirlite.LLVMType* = None
if fp is not None: fpty = mlirlite.param_get_ty(fp)
@@ -185,7 +184,6 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
else: tail.Next = av
tail = av
if fp is not None: fp = mlirlite.param_get_next(fp)
ai += 1
# build_call's second arg is the callee name string (not Function*); passing a Function*
# reads its first field as a string and emits illegal IR. Use the looked-up symbol name.
return mlirlite.build_call(builder, spec_name, head, int(can), ret_ty, 0)
+3 -7
View File
@@ -65,8 +65,7 @@ def _gfn_idx_find(funcs: GenTypes.FuncEntry*, idx_base: sizet*, cap: int, name:
mask: sizet = sizet(cap - 1)
si: sizet = sizet(h) & mask
entry_size: sizet = GenTypes.FuncEntry.__sizeof__()
i: int = 0
while i < cap:
for i in range(cap):
slot: sizet* = _gfn_idx_slot(idx_base, si)
sv: sizet = slot[0]
if sv == 0: return -1
@@ -76,7 +75,6 @@ def _gfn_idx_find(funcs: GenTypes.FuncEntry*, idx_base: sizet*, cap: int, name:
if entry is not None and entry.Name is not None:
if string.strcmp(entry.Name, name) == 0: return se
si = (si + 1) & mask
i += 1
return -1
@@ -86,14 +84,12 @@ def _gfn_idx_insert(idx_base: sizet*, cap: int, slot_index: int, name: str) -> i
h: uint64 = _gfn_hash(name)
mask: sizet = sizet(cap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < cap:
for i in range(cap):
slot: sizet* = _gfn_idx_slot(idx_base, si)
if slot[0] == 0:
slot[0] = sizet(slot_index + 1)
return 0
si = (si + 1) & mask
i += 1
return 1
@@ -936,7 +932,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
return 0
# _build_func_spec: build the full-signature TypeSpec (Kind=TS_FUNC) from a function after all
# _build_func_spec: build the full-signature TypeSpec (Kind=TS_FUNC) from a function after all
# params are added; unlike SpecFromLLVMType's Func branch it carries func.IsVarArg.
def _build_func_spec(self, func: mlirlite.Function*) -> TSpec.TypeSpec*:
"""Build the full-signature TypeSpec from a function; returns None on failure"""
+3 -5
View File
@@ -116,13 +116,11 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
n_av: sizet = string.strlen(annot_val)
last_dot_av: sizet = n_av
depth_av: int = 0
ai_av: sizet = 0
while ai_av < n_av:
for ai_av in range(n_av):
ch_av: int = annot_val[ai_av]
if ch_av == '[': depth_av += 1
elif ch_av == ']': depth_av -= 1
elif ch_av == '.' and depth_av == 0: last_dot_av = ai_av
ai_av += 1
if last_dot_av < n_av: return annot_val + last_dot_av + 1
return annot_val
return None
@@ -263,7 +261,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
pfx: int = GenApi.sha1_prefix_len(name)
return name + pfx if pfx != 0 else name
# _resolve_generic_receiver_name - resolve the receiver's actual generic specialization name (IR truth).
# _resolve_generic_receiver_name - resolve the receiver's actual generic specialization name (IR truth).
# Strip the sha1 prefix, take the base before '['; bare generic base => fail-fast (D25), else None.
def _resolve_generic_receiver_name(self, pool: memhub.MemBuddy*, struct_ty: mlirlite.LLVMType*, method_name: str, cl: ast.Call*) -> str:
"""Return the actual generic specialization name (sha1 stripped) or None; a bare generic base fails fast"""
@@ -287,7 +285,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase):
self.Gen.TypeGenErr.fatal_error(cl, f"方法 '{method_name}' 的接收者实际结构体类型是裸泛型基类 " f"'{short_nm}*'(丢失类型实参),元素类型未知;" f"禁止静默按默认元素类型处理(元素按 i32 处理会截断指针)," f"请让该变量的注解/类型带上实参(如 list[ast.AST*])", "TypeError")
return None
# _is_list_builtin_receiver - test list builtin methods from the receiver's actual type.
# _is_list_builtin_receiver - test list builtin methods from the receiver's actual type.
# Prefer the actual LLVM struct name (sha1 stripped); fall back to the annotation/registered name.
def _is_list_builtin_receiver(self, pool: memhub.MemBuddy*, recv_val: mlirlite.Value*, fallback_name: str, method_name: str, cl: ast.Call*) -> int:
"""Test list builtin methods from the receiver's actual type (fall back to the annotation name if unavailable)"""
+3 -5
View File
@@ -198,7 +198,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
# these objects are referenced at runtime, so emit a linkonce_odr definition with null init.
is_t_type_obj: int = 0
if string.strcmp(mod_path_w, "t") == 0: is_t_type_obj = self._is_t_type_object_name(at.attr)
# a class name is not a module-level global: registered classes/structs/REnums are always
# a class name is not a module-level global: registered classes/structs/REnums are always
# handled by the class/REnum paths, never manufactured into an external global here.
if is_t_type_obj == 0 and self.Gen.StructGen.find_struct(at.attr) is not None: return None
# fallback declaration name: t type objects (t.py uncompiled, no sha1) keep the bare
@@ -600,7 +600,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if alias_fe is not None and alias_fe.Ty is not None:
alias_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, alias_fe.Ty, obj_ptr, alias_idx)
if alias_ptr is not None:
# REnum variant field read by its declared type (matching match binding): the slot is i32/i64,
# REnum variant field read by its declared type (matching match binding): the slot is i32/i64,
# so bitcast the slot address then load the declared type (no info loss) to avoid an int→ptr error.
decl_ty_rn: mlirlite.LLVMType* = self.Gen.ClassGenEnum._lookup_renum_field_alias_ty(renum_se.Name, at.attr)
if decl_ty_rn is not None:
@@ -878,11 +878,9 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
if bare is None: return None
st: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(bare)
if st is None: return None
fi: int = 0
while fi < st.FieldCount:
for fi in range(st.FieldCount):
fe_u: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(st, fi)
if fe_u is not None and fe_u.Name is not None and string.strcmp(fe_u.Name, at.attr) == 0: return fe_u
fi += 1
return None
def attr_field_pointee_is_volatile(self, pool: memhub.MemBuddy*, trans: HT.Translator*, attr_node: ast.AST*) -> int:
+6 -14
View File
@@ -22,7 +22,7 @@ import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
"""Cross-module CDefine lookup"""
# _build_source_path_from_sha1: build a source .vp/.py path from SHA1 via the StubMerger
# _build_source_path_from_sha1: build a source .vp/.py path from SHA1 via the StubMerger
# global store (.vpi missing -> source .py); "lib/..." -> SourceDir, else IncludesDir.
def _build_source_path_from_sha1(self, sha1: str) -> str:
"""Build a source .py path from a SHA1 via the global store"""
@@ -49,7 +49,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
ridx: sizet = sizet(idx_s) * MAX_RPL
rel_path: str = rel_arr_ptr + ridx
if rel_path[0] == '\0': return None
# choose base dir: 1) stored includes root IncDir (absolute, supports multiple dirs);
# choose base dir: 1) stored includes root IncDir (absolute, supports multiple dirs);
# 2) prefix heuristic: "lib/" -> SourceDir, "includes/" -> IncludesDir, else SourceDir then IncludesDir.
base_dir: str = None
rel_used: str = rel_path
@@ -175,19 +175,15 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
if im_nlen > 0 and im_nlen < 256:
im_buf: str = pool.alloc(im_nlen + 1)
if im_buf is not None:
mk: sizet = 0
while mk < im_nlen:
for mk in range(im_nlen):
im_buf[mk] = imported_modules[im_start + mk]
mk += 1
im_buf[im_nlen] = '\0'
sub_fi: str = pool.alloc(im_nlen + 3)
if sub_fi is not None:
sub_fi[0] = '*'
sub_fi[1] = ':'
mk2: sizet = 0
while mk2 < im_nlen:
for mk2 in range(im_nlen):
sub_fi[2 + mk2] = im_buf[mk2]
mk2 += 1
sub_fi[2 + im_nlen] = '\0'
sub_val: int64 = self._lookup_cross_module_cdefine(pool, name, sub_fi, None, depth + 1, node)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0: return sub_val
@@ -752,19 +748,15 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
if im2_nlen > 0 and im2_nlen < 256:
im2_buf: str = pool.alloc(im2_nlen + 1)
if im2_buf is not None:
mk3: sizet = 0
while mk3 < im2_nlen:
for mk3 in range(im2_nlen):
im2_buf[mk3] = imported_modules[im2_start + mk3]
mk3 += 1
im2_buf[im2_nlen] = '\0'
sub_fi2: str = pool.alloc(im2_nlen + 3)
if sub_fi2 is not None:
sub_fi2[0] = '*'
sub_fi2[1] = ':'
mk4: sizet = 0
while mk4 < im2_nlen:
for mk4 in range(im2_nlen):
sub_fi2[2 + mk4] = im2_buf[mk4]
mk4 += 1
sub_fi2[2 + im2_nlen] = '\0'
sub_val2: int64 = self._lookup_cross_module_cdefine(pool, name, sub_fi2, None, depth + 1, node)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
+1 -3
View File
@@ -219,8 +219,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
if bare_u is not None:
st_u: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(bare_u)
if st_u is not None:
fi_u: int = 0
while fi_u < st_u.FieldCount:
for fi_u in range(st_u.FieldCount):
fe_u: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(st_u, fi_u)
if fe_u is not None and fe_u.Name is not None and string.strcmp(fe_u.Name, at_u.attr) == 0:
# [S4 read] An explicit unsigned field Spec wins
@@ -229,7 +228,6 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
if fcn_u is not None:
if self._annot_str_unsigned(fcn_u) != 0: return 1
break
fi_u += 1
return 0
return 0
def _node_type_signed(self, pool: memhub.MemBuddy*, node: ast.AST*, trans: HT.Translator* = None) -> int:
+6 -18
View File
@@ -179,8 +179,7 @@ novirtual class ImportsGenMixin:
if name is None: return 0
if StubMergerStore.LookupSha1ByModName(name) is None: return 0
nl: sizet = string.strlen(name)
dot_pos: sizet = 0
while dot_pos < nl:
for dot_pos in range(nl):
if name[dot_pos] == '.':
pfx: str = stdlib.malloc(dot_pos + 1)
if pfx is not None:
@@ -189,7 +188,6 @@ novirtual class ImportsGenMixin:
hit: int = self.is_module_imported(imported_modules, pfx)
stdlib.free(pfx)
if hit != 0: return 1
dot_pos += 1
return 0
# Add a from-import name mapping
@@ -240,12 +238,10 @@ novirtual class ImportsGenMixin:
# Compare the name
if entry_name_len == name_len:
Matched: int = 1
ei: sizet = 0
while ei < name_len:
for ei in range(name_len):
if cur[ci + ei] != local_name[ei]:
Matched = 0
break
ei += 1
if Matched == 1:
# Match found; check for a third field (the original name)
pos: sizet = colon1 + 1
@@ -309,12 +305,10 @@ novirtual class ImportsGenMixin:
# Compare the name
elif entry_name_len == name_len:
Matched: int = 1
ei: sizet = 0
while ei < name_len:
for ei in range(name_len):
if cur[ci + ei] != name[ei]:
Matched = 0
break
ei += 1
if Matched == 1:
mod_start2: sizet = colon_pos + 1
mod_end2: sizet = mod_start2
@@ -395,12 +389,10 @@ novirtual class ImportsGenMixin:
pkg_len: sizet = string.strlen(pkg)
last_dot: sizet = 0
found: int = 0
i: sizet = 0
while i < pkg_len:
for i in range(pkg_len):
if pkg[i] == '.':
last_dot = i
found = 1
i += 1
if found == 0:
# No more parents (the relative level exceeds the package depth): fall back to
# the original module; a later import SHA1 check reports "module not found".
@@ -443,13 +435,11 @@ novirtual class ImportsGenMixin:
# Find the last / or \
last_sep: sizet = 0
found: int = 0
i: sizet = 0
while i < rlen:
for i in range(rlen):
ch: char = rel_path[i]
if ch == '/' or ch == '\\':
last_sep = i
found = 1
i += 1
if found == 0:
# No directory separator -> top-level file, no package
return None
@@ -457,12 +447,10 @@ novirtual class ImportsGenMixin:
dir_len: sizet = last_sep
buf: str = pool.alloc(dir_len + 1)
if buf is None: return None
j: sizet = 0
while j < dir_len:
for j in range(dir_len):
ch2: char = rel_path[j]
if ch2 == '/' or ch2 == '\\': buf[j] = '.'
else: buf[j] = ch2
j += 1
buf[dir_len] = '\0'
return buf
+3 -9
View File
@@ -55,12 +55,10 @@ def _struct_ty_hash(tyval: uint64) -> uint64:
"""Hash a Ty pointer value with 32-bit FNV-1a over its 8 bytes."""
h: uint64 = uint64(FNV32_OFFSET)
v: uint64 = tyval
j: int = 0
while j < 8:
for j in range(8):
h = (h ^ (v & uint64(255))) * uint64(FNV32_PRIME)
h = h & uint64(FNV32_MASK)
v = v >> 8
j += 1
return h
@@ -331,14 +329,12 @@ novirtual class StructGenMixin:
h: uint64 = _struct_name_hash(name)
mask: sizet = sizet(self.StructIdxCap - 1)
idx: sizet = sizet(h) & mask
i: int = 0
while i < self.StructIdxCap:
for i in range(self.StructIdxCap):
slot: sizet* = (sizet*)(uint64(base) + uint64(idx * 8))
if slot[0] == 0:
slot[0] = sizet(ei + 1)
return 0
idx = (idx + 1) & mask
i += 1
return 1
def _struct_type_idx_insert(self, ei: int, tyval: uint64) -> int:
@@ -348,14 +344,12 @@ novirtual class StructGenMixin:
h: uint64 = _struct_ty_hash(tyval)
mask: sizet = sizet(self.StructIdxCap - 1)
idx: sizet = sizet(h) & mask
i: int = 0
while i < self.StructIdxCap:
for i in range(self.StructIdxCap):
slot: sizet* = (sizet*)(uint64(base) + uint64(idx * 8))
if slot[0] == 0:
slot[0] = sizet(ei + 1)
return 0
idx = (idx + 1) & mask
i += 1
return 1
def _struct_idx_add(self, ei: int, entry: GenTypes.StructEntry*) -> None:
+4 -12
View File
@@ -529,11 +529,9 @@ novirtual class Translator:
"""Return 1 if name is a registered Project macro variable."""
if name is None or proj_vars is None: return 0
n: sizet = len(proj_vars)
i: sizet = 0
while i < n:
for i in range(n):
s: str = proj_vars.get(i)
if s is not None and string.strcmp(s, name) == 0: return 1
i += 1
return 0
def _vb_is_project_ctor(self, value: ast.AST*, alias: str, ctor: str) -> int:
@@ -631,26 +629,22 @@ novirtual class Translator:
if kd == ast.ASTKind.Import:
names: list[ast.AST*]* = ast.Import*(child).names
if names is not None:
ni: sizet = 0
while ni < len(names):
for ni in range(len(names)):
al: ast.Alias* = ast.Alias*(names.get(ni))
if al is not None and al.name is not None:
if string.strcmp(al.name, "viperbuild") == 0:
if al.asname is not None: alias = al.asname
else: alias = "viperbuild"
ni += 1
elif kd == ast.ASTKind.ImportFrom:
ifr: ast.ImportFrom* = ast.ImportFrom*(child)
if ifr is not None and ifr.level == 0 and ifr.names is not None:
if ifr.module is not None and string.strcmp(ifr.module, "viperbuild") == 0:
ni: sizet = 0
while ni < len(ifr.names):
for ni in range(len(ifr.names)):
al: ast.Alias* = ast.Alias*(ifr.names.get(ni))
if al is not None and al.name is not None:
if string.strcmp(al.name, "Project") == 0:
if al.asname is not None: ctor = al.asname
else: ctor = "Project"
ni += 1
ci += 1
if alias is None and ctor is None: return 0
# (2) Filter: register Project macro variables, then drop the related statements
@@ -658,13 +652,11 @@ novirtual class Translator:
kept: list[ast.AST*]* = list[ast.AST*](pool, 8)
if proj_vars is None or kept is None: return 0
erased: int = 0
ci = 0
while ci < cn:
for ci in range(cn):
child = ch.get(ci)
if child is not None:
if self._vb_is_macro_stmt(child, alias, ctor, proj_vars) != 0: erased = 1
else: kept.append(child)
ci += 1
if erased != 0: tree.children = kept
return erased
+3 -9
View File
@@ -185,8 +185,7 @@ novirtual class TranslatorGenMixin:
elem_ty_str_n: str = pool.alloc(512)
if elem_ty_str_n is None: return None
mlirlite.TypePrint(elem_ty_str_n, 512, elem_ty, pool)
i_n: sizet = 0
while i_n < cnt_total_n:
for i_n in range(cnt_total_n):
sub_n: str = None
if i_n < elts_count:
en_n: ast.AST* = elts.get(i_n)
@@ -206,7 +205,6 @@ novirtual class TranslatorGenMixin:
pos_n += sizet(written_n)
written_n = viperlib.snprintf(buf_n + pos_n, buf_size_n - pos_n, "%s%s", elem_ty_str_n, sub_n)
pos_n += sizet(written_n)
i_n += 1
viperlib.snprintf(buf_n + pos_n, buf_size_n - pos_n, "]")
return buf_n
for zi in range(elts_count):
@@ -238,8 +236,7 @@ novirtual class TranslatorGenMixin:
# Write elements up to the declared length arr_count, zero-padding short lists so the
# initializer element count always matches the type llc expects.
i: sizet = 0
while i < cnt_total:
for i in range(cnt_total):
elem_val: int64 = 0
if i < elts_count:
elem_node: ast.AST* = elts.get(i)
@@ -263,7 +260,6 @@ novirtual class TranslatorGenMixin:
pos += sizet(written)
written = viperlib.snprintf(buf + pos, buf_size - pos, "%s %lld", elem_ir_ty, elem_val)
pos += sizet(written)
i += 1
# Write the closing "]" suffix
viperlib.snprintf(buf + pos, buf_size - pos, "]")
@@ -286,8 +282,7 @@ novirtual class TranslatorGenMixin:
if buf is None: return None
written: int = viperlib.snprintf(buf, buf_size, "[")
pos: sizet = sizet(written)
i: sizet = 0
while i < sizet(arr_count):
for i in range(sizet(arr_count)):
if i > 0:
written = viperlib.snprintf(buf + pos, buf_size - pos, ", ")
pos += sizet(written)
@@ -295,7 +290,6 @@ novirtual class TranslatorGenMixin:
if i < slen: bv = int64(str_val[i])
written = viperlib.snprintf(buf + pos, buf_size - pos, "i8 %lld", bv)
pos += sizet(written)
i += 1
viperlib.snprintf(buf + pos, buf_size - pos, "]")
return buf
+2 -6
View File
@@ -64,8 +64,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
h: uint64 = self._cdef_idx_hash(name)
mask: sizet = sizet(self.CDefineNameIdxCap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < self.CDefineNameIdxCap:
for i in range(self.CDefineNameIdxCap):
slot: sizet* = self._cdef_idx_slot(si)
sv: sizet = slot[0]
if sv == 0: return -1
@@ -73,7 +72,6 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
nm: str = self.CDefineNames.get(sizet(se))
if nm is not None and string.strcmp(nm, name) == 0: return se
si = (si + 1) & mask
i += 1
return -1
def _cdef_idx_insert(self, slot_index: int, name: str) -> int:
@@ -82,14 +80,12 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase):
h: uint64 = self._cdef_idx_hash(name)
mask: sizet = sizet(self.CDefineNameIdxCap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < self.CDefineNameIdxCap:
for i in range(self.CDefineNameIdxCap):
slot: sizet* = self._cdef_idx_slot(si)
if slot[0] == 0:
slot[0] = sizet(slot_index + 1)
return 0
si = (si + 1) & mask
i += 1
return 1
def _cdef_idx_sync_append(self, name: str) -> None:
+3 -9
View File
@@ -71,8 +71,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
h: uint64 = _ctypedef_idx_hash(name)
mask: sizet = sizet(self.CTypedefNameIdxCap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < self.CTypedefNameIdxCap:
for i in range(self.CTypedefNameIdxCap):
slot: sizet* = self._ctypedef_idx_slot(si)
sv: sizet = slot[0]
if sv == 0: return -1
@@ -80,7 +79,6 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
nm: str = self.CTypedefNames.get(sizet(se))
if nm is not None and string.strcmp(nm, name) == 0: return se
si = (si + 1) & mask
i += 1
return -1
def _ctypedef_idx_insert(self, slot_index: int, name: str) -> int:
@@ -89,14 +87,12 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
h: uint64 = _ctypedef_idx_hash(name)
mask: sizet = sizet(self.CTypedefNameIdxCap - 1)
si: sizet = sizet(h) & mask
i: int = 0
while i < self.CTypedefNameIdxCap:
for i in range(self.CTypedefNameIdxCap):
slot: sizet* = self._ctypedef_idx_slot(si)
if slot[0] == 0:
slot[0] = sizet(slot_index + 1)
return 0
si = (si + 1) & mask
i += 1
return 1
def _ctypedef_idx_sync_append(self, name: str) -> None:
@@ -216,12 +212,10 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
# rules out a match without strlen.
if nm[0] != text[start] or string.strlen(nm) != want: continue
hit: int = 1
k: sizet = 0
while k < want:
for k in range(want):
if nm[k] != text[start + k]:
hit = 0
break
k += 1
if hit != 0:
ts: str = self.CTypedefTypeStrs.get(i)
self.CTypedefFound = 1
+18 -32
View File
@@ -331,15 +331,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if seg_len == 0: return type_name
pipe_idx: sizet = seg_len
p_depth: int = 0
pi: sizet = 0
while pi < seg_len:
for pi in range(seg_len):
ch_p: int = type_name[pi]
if ch_p == '[': p_depth += 1
elif ch_p == ']': p_depth -= 1
elif ch_p == '|' and p_depth == 0:
pipe_idx = pi
break
pi += 1
if pipe_idx < seg_len:
left_buf: str = pool.alloc(pipe_idx + 1)
if left_buf is None: return type_name
@@ -376,15 +374,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# normalize each; t.CArray / list keep their count arg verbatim.
lb_idx: sizet = seg_len
ld: int = 0
li2: sizet = 0
while li2 < seg_len:
for li2 in range(seg_len):
if type_name[li2] == '[':
if ld == 0:
lb_idx = li2
break
ld += 1
elif type_name[li2] == ']': ld -= 1
li2 += 1
if lb_idx < seg_len and type_name[seg_len - 1] == ']':
container_g: str = pool.alloc(lb_idx + 1)
if container_g is not None:
@@ -675,12 +671,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# Check for '|' (BinOp): search only within the valid range [0, seg_len)
pipe_idx: sizet = seg_len
pi: sizet = 0
while pi < seg_len:
for pi in range(seg_len):
if type_str[pi] == '|':
pipe_idx = pi
break
pi += 1
if pipe_idx < seg_len:
# Copy the left segment into its own buffer (trim trailing spaces), preserving the original
left_len: sizet = pipe_idx
@@ -699,12 +693,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# Check for '[' (Subscript) like t.Callable[[int], int]; must precede the '.'
# check since it is a Subscript. Parse fully via ast.parse_expression.
bracket_idx: sizet = seg_len
bi: sizet = 0
while bi < seg_len:
for bi in range(seg_len):
if type_str[bi] == '[':
bracket_idx = bi
break
bi += 1
if bracket_idx < seg_len:
# If the inner part starts with a digit (a "{16hex}.Class" name), the lexer
# mis-scans it as a number; split base+slice manually for a single non-nested arg.
@@ -759,12 +751,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# Whether the text contains '.' (Attribute): search only within [0, seg_len).
dot_idx: sizet = seg_len
di: sizet = 0
while di < seg_len:
for di in range(seg_len):
if type_str[di] == '.':
dot_idx = di
break
di += 1
if dot_idx < seg_len:
# Trim trailing spaces of the module-name segment
mod_len: sizet = dot_idx
@@ -840,17 +830,17 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
lib_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, lib_node, imported_modules, from_imports, trans, 1)
self.Gen.TypeGenCType.CTypedefResolveDepth -= 1
if lib_ty is not None: return lib_ty
# Bare Python/C builtin aliases: map_t_type only knows the t.CXxx spelling, so
# resolve them here to match resolve_annotation_type's bare-name branch. Without
# this the two-arg form int(x, t.CPtr) misses _tc_h4 and fails fast as "int".
if string.strcmp(name, "str") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(name, "bytes") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(name, "int") == 0: return mlirlite.Int32(pool)
if string.strcmp(name, "char") == 0: return mlirlite.Int8(pool)
if string.strcmp(name, "bool") == 0: return mlirlite.Int1(pool)
if string.strcmp(name, "float") == 0: return mlirlite.Float(pool)
if string.strcmp(name, "double") == 0: return mlirlite.Double(pool)
if string.strcmp(name, "void") == 0: return mlirlite.Void(pool)
# Bare Python/C builtin aliases: map_t_type only knows the t.CXxx spelling, so
# resolve them here to match resolve_annotation_type's bare-name branch. Without
# this the two-arg form int(x, t.CPtr) misses _tc_h4 and fails fast as "int".
if string.strcmp(name, "str") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(name, "bytes") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool))
if string.strcmp(name, "int") == 0: return mlirlite.Int32(pool)
if string.strcmp(name, "char") == 0: return mlirlite.Int8(pool)
if string.strcmp(name, "bool") == 0: return mlirlite.Int1(pool)
if string.strcmp(name, "float") == 0: return mlirlite.Float(pool)
if string.strcmp(name, "double") == 0: return mlirlite.Double(pool)
if string.strcmp(name, "void") == 0: return mlirlite.Void(pool)
return self.map_t_type(pool, name)
def get_type_size_bytes(self, pool: memhub.MemBuddy*, name: str, imported_modules: str, from_imports: str) -> int:
"""Return the type size in bytes via resolve_typedef_or_map, or 0 on failure."""
@@ -990,10 +980,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
out_buf[ci] = buf[line_start + name_s + ci]
ci += 1
out_buf[name_l] = '\0'
ci = 0
while ci < vlen:
for ci in range(vlen):
out_buf[name_l + 1 + ci] = buf[line_start + vs + ci]
ci += 1
out_buf[name_l + 1 + vlen] = '\0'
return 1
def _lookup_builtins_typedef(self, pool: memhub.MemBuddy*, name: str) -> str:
@@ -2384,10 +2372,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
cur_lvl = nxt_lvl
# Result = wrap the other side's type in N layers of Ptr
res_ty: mlirlite.LLVMType* = cptr_other_ty
li2: int = 0
while li2 < cptr_level:
for li2 in range(cptr_level):
res_ty = mlirlite.Ptr(pool, res_ty)
li2 += 1
return res_ty
# No CPtr marker: return the first non-attribute-marker side. Attribute markers
+6 -18
View File
@@ -185,8 +185,7 @@ def _spec_index_find(arena: TypeSpecArena*, key: str, h: uint64) -> int:
if arena.Index is None or arena.IndexCap <= 0: return -1
mask: sizet = sizet(arena.IndexCap - 1)
idx: sizet = sizet(h) & mask
i: int = 0
while i < arena.IndexCap:
for i in range(arena.IndexCap):
slot: sizet* = (sizet*)(uint64(arena.Index) + uint64(idx * 8))
sv: sizet = slot[0]
if sv == 0: return -1
@@ -194,7 +193,6 @@ def _spec_index_find(arena: TypeSpecArena*, key: str, h: uint64) -> int:
ek: str = _spec_key_at(arena.Keys, ei)
if ek is not None and string.strcmp(ek, key) == 0: return ei
idx = (idx + 1) & mask
i += 1
return -1
@@ -205,14 +203,12 @@ def _spec_index_insert(arena: TypeSpecArena*, key: str, h: uint64, ei: int) -> i
if arena.Index is None or arena.IndexCap <= 0: return 1
mask: sizet = sizet(arena.IndexCap - 1)
idx: sizet = sizet(h) & mask
i: int = 0
while i < arena.IndexCap:
for i in range(arena.IndexCap):
slot: sizet* = (sizet*)(uint64(arena.Index) + uint64(idx * 8))
if slot[0] == 0:
slot[0] = sizet(ei + 1)
return 0
idx = (idx + 1) & mask
i += 1
return 1
@@ -426,8 +422,7 @@ def _spec_to_text(sp: TypeSpec*, buf: str, buf_size: sizet, depth: int) -> int:
pos: sizet = 0
pos = _spec_text_append(buf, buf_size, pos, "fn(")
if pos >= buf_size: return 1
i: int = 0
while i < sp.ParamCount:
for i in range(sp.ParamCount):
if i > 0:
pos = _spec_text_append(buf, buf_size, pos, ",")
if pos >= buf_size: return 1
@@ -438,7 +433,6 @@ def _spec_to_text(sp: TypeSpec*, buf: str, buf_size: sizet, depth: int) -> int:
if _spec_to_text(param, param_buf, SPEC_TEXT_MAX, depth + 1) != 0: return 1
pos = _spec_text_append(buf, buf_size, pos, param_buf)
if pos >= buf_size: return 1
i += 1
if sp.IsVarArg == 1:
if sp.ParamCount > 0: pos = _spec_text_append(buf, buf_size, pos, ",...")
else: pos = _spec_text_append(buf, buf_size, pos, "...")
@@ -461,14 +455,12 @@ def _spec_text_append(buf: str, buf_size: sizet, pos: sizet, text: str) -> sizet
"""Append text at pos in buf; buf_size sentinel when full, else the new position"""
if buf is None or text is None: return buf_size
tlen: sizet = string.strlen(text)
i: sizet = 0
while i < tlen:
for i in range(tlen):
if pos + 1 >= buf_size:
buf[pos] = '\0'
return buf_size
buf[pos] = text[i]
pos += 1
i += 1
buf[pos] = '\0'
return pos
@@ -626,14 +618,12 @@ def InternSpec(arena: TypeSpecArena*, sp: TypeSpec*) -> TypeSpec*:
return (TypeSpec*)(uint64(slot_e[0]))
if arena.Index is None:
# index unavailable: fall back to the linear scan
i: int = 0
while i < arena.Count:
for i in range(arena.Count):
exist_key: str = _spec_key_at(arena.Keys, i)
if exist_key is not None and string.strcmp(exist_key, key_buf) == 0:
slot_e2: sizet* = (sizet*)(uint64(arena.Specs) + uint64(i * 8))
if slot_e2 is None: return None
return (TypeSpec*)(uint64(slot_e2[0]))
i += 1
# Miss: append. Table full = fail-fast (never return None, which would silently
# lose type info up the call chain and corrupt signedness -> zext/sext direction).
if arena.Count >= arena.Cap:
@@ -881,14 +871,12 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet, depth: int) -> int
if sp.Kind == TS_FUNC:
if _spec_llvm_text(sp.Ret, buf, buf_size, depth + 1) != 0: return 1
if _spec_llvm_append(buf, buf_size, " (") != 0: return 1
i: int = 0
while i < sp.ParamCount:
for i in range(sp.ParamCount):
if i > 0:
if _spec_llvm_append(buf, buf_size, ", ") != 0: return 1
ps: TypeSpec* = _spec_param_at(sp, i)
if ps is None: return 1
if _spec_llvm_text(ps, buf, buf_size, depth + 1) != 0: return 1
i += 1
# vararg suffix (unique to this Spec convention, see above)
if sp.IsVarArg == 1:
if sp.ParamCount > 0:
+3 -9
View File
@@ -1377,11 +1377,9 @@ def _repl_sig_to_text(tag: int, bits: int, pc: int) -> str:
"""Render ReplSigResult + ReplSigTags/Bits as "(P1, P2) -> R" (PermPool buffer)."""
if ReplSigText is None: return "(?)"
pos: int = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, 0, "(")
i: int = 0
while i < pc:
for i in range(pc):
if i > 0: pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, ", ")
pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(int(ReplSigTags[i]), int(ReplSigBits[i])))
i += 1
pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, ") -> ")
pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(tag, bits))
if pos < 0: return "(?)"
@@ -1428,12 +1426,10 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int:
sig_same: int = 1
if old.RetTag != ReplSigResult.RetTag or old.RetBits != ReplSigResult.RetBits or old.ParamCount != ReplSigResult.ParamCount: sig_same = 0
if sig_same != 0:
pi: int = 0
while pi < old.ParamCount:
for pi in range(old.ParamCount):
if int(old.ParamTags[pi]) != int(ReplSigTags[pi]) or int(old.ParamBits[pi]) != int(ReplSigBits[pi]):
sig_same = 0
break
pi += 1
if sig_same == 0:
stdio.printf("M3: 会话函数 '%s' 重定义签名不一致(旧 %s,新 %s)\n" " M3 允许同签名覆盖(只换地址);换签名会让先前片段里已编好的" "调用点按旧 ABI 调新代码 —— 该片段整体不执行,请换名字\n", nm, _repl_entry_sig_text(old), _repl_sig_to_text(ReplSigResult.RetTag, ReplSigResult.RetBits, ReplSigResult.ParamCount))
return 1
@@ -1447,11 +1443,9 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int:
def _repl_entry_sig_text(e: rawptr[GenTypes.ReplFuncEntry]) -> str:
if e is None or ReplSigText2 is None: return "(?)"
pos: int = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, 0, "(")
i: int = 0
while i < e.ParamCount:
for i in range(e.ParamCount):
if i > 0: pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, ", ")
pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(int(e.ParamTags[i]), int(e.ParamBits[i])))
i += 1
pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, ") -> ")
pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(e.RetTag, e.RetBits))
if pos < 0: return "(?)"
+19 -57
View File
@@ -131,11 +131,9 @@ def _BaseNameOf(path: str) -> str:
if path is None: return None
n: sizet = string.strlen(path)
start: sizet = 0
i: sizet = 0
while i < n:
for i in range(n):
ch: char = path[i]
if ch == '/' or ch == '\\': start = i + 1
i += 1
return _DupStd(path + start)
@@ -168,12 +166,10 @@ def _FindInList(names: list[str]*, name: str) -> int:
"""Linear-search names for name; return its index, or -1 if not found."""
if names is None or name is None: return -1
n: sizet = names.__len__()
i: sizet = 0
while i < n:
for i in range(n):
s: str = names.get(i)
if s is not None:
if string.strcmp(s, name) == 0: return int(i)
i += 1
return -1
@@ -203,8 +199,7 @@ def _SplitInto(out: list[str]*, joined: str) -> int:
n: sizet = string.strlen(joined)
if n == 0: return 1
start: sizet = 0
i: sizet = 0
while i <= n:
for i in range(n + 1):
if i == n or joined[i] == char(VB_SEP_CODE):
seg: str = stdlib.malloc(i - start + 1)
if seg is None: return 0
@@ -213,7 +208,6 @@ def _SplitInto(out: list[str]*, joined: str) -> int:
out.append(_DupScratch(seg))
stdlib.free(seg)
start = i + 1
i += 1
return 1
@@ -233,8 +227,7 @@ def _JoinSep(lst: list[str]*) -> str:
buf: str = _scratch.alloc(total + 1)
if buf is None: return None
pos: sizet = 0
i = 0
while i < n:
for i in range(n):
s = lst.get(i)
if s is not None:
sl: sizet = string.strlen(s)
@@ -243,7 +236,6 @@ def _JoinSep(lst: list[str]*) -> str:
pos += 1
string.strcpy(buf + pos, s)
pos += sl
i += 1
buf[pos] = '\0'
return buf
@@ -263,8 +255,7 @@ def _JoinSpace(lst: list[str]*) -> str:
buf: str = stdlib.malloc(total + 1)
if buf is None: return None
pos: sizet = 0
i = 0
while i < n:
for i in range(n):
s = lst.get(i)
if s is not None:
sl: sizet = string.strlen(s)
@@ -273,7 +264,6 @@ def _JoinSpace(lst: list[str]*) -> str:
pos += 1
string.strcpy(buf + pos, s)
pos += sl
i += 1
buf[pos] = '\0'
return buf
@@ -284,12 +274,10 @@ def _FirstSpaceTok(joined: str) -> str:
n: sizet = string.strlen(joined)
if n == 0: return None
sp: sizet = n
i: sizet = 0
while i < n:
for i in range(n):
if joined[i] == ' ':
sp = i
break
i += 1
seg: str = stdlib.malloc(sp + 1)
if seg is None: return None
string.strncpy(seg, joined, sp)
@@ -349,8 +337,7 @@ def _EvalList(node: ast.AST*, out: list[str]*) -> int:
lst: ast.List* = ast.List*(node)
if lst is None or lst.elts is None: return 0
n: sizet = lst.elts.__len__()
i: sizet = 0
while i < n:
for i in range(n):
e: ast.AST* = lst.elts.get(i)
if e is None: return 0
if e.kind() == ast.ASTKind.Starred:
@@ -360,7 +347,6 @@ def _EvalList(node: ast.AST*, out: list[str]*) -> int:
else:
if _EvalStr(e) == 0: return 0
out.append(_DupScratch(_g_out_str))
i += 1
return 1
if k == ast.ASTKind.BinOp:
bop: ast.BinOp* = ast.BinOp*(node)
@@ -423,8 +409,7 @@ def _HandleImport(stmt: ast.Import*) -> int:
global _alias, _saw_viperbuild
if stmt is None or stmt.names is None: return 0
n: sizet = stmt.names.__len__()
i: sizet = 0
while i < n:
for i in range(n):
al: ast.Alias* = ast.Alias*(stmt.names.get(i))
if al is not None and al.name is not None:
if string.strcmp(al.name, "viperbuild") == 0:
@@ -432,7 +417,6 @@ def _HandleImport(stmt: ast.Import*) -> int:
if al.asname is not None: _alias = _DupScratch(al.asname)
else: _alias = _DupScratch("viperbuild")
else: _AddPending(al.name)
i += 1
return 0
@@ -450,14 +434,12 @@ def _HandleImportFrom(stmt: ast.ImportFrom*) -> int:
_saw_viperbuild = 1
if stmt.names is None: return 0
n: sizet = stmt.names.__len__()
i: sizet = 0
while i < n:
for i in range(n):
al: ast.Alias* = ast.Alias*(stmt.names.get(i))
if al is not None and al.name is not None:
if string.strcmp(al.name, "Project") == 0:
if al.asname is not None: _ctor_name = _DupScratch(al.asname)
else: _ctor_name = _DupScratch("Project")
i += 1
return 0
@@ -505,8 +487,7 @@ def _ApplyCtorArgs(cl: ast.Call*) -> int:
_c_version = _DupStd(_g_out_str)
if cl.keywords is None: return 0
n: sizet = cl.keywords.__len__()
i: sizet = 0
while i < n:
for i in range(n):
kw: ast.Keyword* = ast.Keyword*(cl.keywords.get(i))
if kw is not None and kw.arg is not None and kw.value is not None:
if string.strcmp(kw.arg, "name") == 0:
@@ -522,7 +503,6 @@ def _ApplyCtorArgs(cl: ast.Call*) -> int:
else:
VLogger.error(f"viperbuild: Project(...) 不支持的关键字 {kw.arg}", "viperbuild")
return 1
i += 1
return 0
@@ -660,12 +640,10 @@ def _HandleConfigCall(cl: ast.Call*) -> int:
"""Handle a proj.config(kw=...) call."""
if cl is None or cl.keywords is None: return 0
n: sizet = cl.keywords.__len__()
i: sizet = 0
while i < n:
for i in range(n):
kw: ast.Keyword* = ast.Keyword*(cl.keywords.get(i))
if kw is not None and kw.arg is not None and kw.value is not None:
if _SetField(kw.arg, kw.value) != 0: return 1
i += 1
return 0
@@ -679,8 +657,7 @@ def _HandleBuildCall(cl: ast.Call*) -> int:
_c_has_build = 1
if cl.keywords is None: return 0
n: sizet = cl.keywords.__len__()
i: sizet = 0
while i < n:
for i in range(n):
kw: ast.Keyword* = ast.Keyword*(cl.keywords.get(i))
if kw is not None and kw.arg is not None and kw.value is not None:
if string.strcmp(kw.arg, "triple") == 0:
@@ -702,7 +679,6 @@ def _HandleBuildCall(cl: ast.Call*) -> int:
else:
VLogger.error(f"viperbuild: build(...) 不支持的关键字 {kw.arg}", "viperbuild")
return 1
i += 1
return 0
@@ -711,18 +687,14 @@ def _CallArgsHaveProjRef(cl: ast.Call*) -> int:
if cl is None: return 0
if cl.args is not None:
n: sizet = cl.args.__len__()
i: sizet = 0
while i < n:
for i in range(n):
if _IsProjRef(cl.args.get(i)) != 0: return 1
i += 1
if cl.keywords is not None:
n = cl.keywords.__len__()
i = 0
while i < n:
for i in range(n):
kw: ast.Keyword* = ast.Keyword*(cl.keywords.get(i))
if kw is not None and kw.value is not None:
if _IsProjRef(kw.value) != 0: return 1
i += 1
return 0
@@ -803,8 +775,7 @@ def _ScanFile(pool: memhub.MemBuddy*, path: str) -> int:
rc: int = 0
if body is not None:
cn: sizet = len(body)
ci: sizet = 0
while ci < cn:
for ci in range(cn):
child: ast.AST* = body.get(ci)
if child is not None:
kd: int = child.kind()
@@ -814,7 +785,6 @@ def _ScanFile(pool: memhub.MemBuddy*, path: str) -> int:
elif kd == ast.ASTKind.AnnAssign: rc = _HandleAnnAssign(ast.AnnAssign*(child))
elif kd == ast.ASTKind.Expr: rc = _HandleExprStmt(ast.Expr*(child))
if rc != 0: break
ci += 1
pool.reset_to(mark)
stdlib.free(src_buf)
@@ -883,13 +853,11 @@ def _RunBfs(pool: memhub.MemBuddy*, entry_path: str) -> int:
if rc == 1: return 1
# Resolve module names collected from this file
pn: sizet = _pending.__len__()
pi: sizet = 0
while pi < pn:
for pi in range(pn):
mod: str = _pending.get(pi)
if mod is not None:
dep: str = _ResolveModuleToFile(mod)
if dep is not None: _Enqueue(dep)
pi += 1
return 0
@@ -939,10 +907,8 @@ def _ProbeIncludes() -> str:
k: int = 0
while k <= 3:
base: str = _DupStd(exe_dir)
j: int = 0
while j < k:
for j in range(k):
base = _Join2(base, "..")
j += 1
cand: str = _Join2(base, "includes")
if _IsDir(cand) != 0: return cand
k += 1
@@ -955,12 +921,10 @@ def _DeriveOutputFromEntry(entry_path: str) -> str:
if base is None: return "app.exe"
n: sizet = string.strlen(base)
cut: sizet = n
i: sizet = 0
while i < n:
for i in range(n):
if base[i] == '.':
cut = i
break
i += 1
head: str = stdlib.malloc(cut + 5)
if head is None: return "app.exe"
string.strncpy(head, base, cut)
@@ -1047,12 +1011,10 @@ def _SplitToolCmd(joined: str, which: int) -> None:
if joined is None: return
n: sizet = string.strlen(joined)
sp: sizet = n
i: sizet = 0
while i < n:
for i in range(n):
if joined[i] == ' ':
sp = i
break
i += 1
cmd: str = stdlib.malloc(sp + 1)
if cmd is not None:
string.strncpy(cmd, joined, sp)