支持 tls 关键字,全面准备清退 t, c
This commit is contained in:
1 parent
6e17716a69
commit
3242560d02
74 files changed
+328
-380
No files matched your search
+138
-70
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import string
|
||||
@@ -262,8 +261,8 @@ class BuildResult:
|
||||
OutputPath: str
|
||||
ErrorMsg: str
|
||||
|
||||
def __new__(self) -> t.CPtr:
|
||||
return t.CPtr(_mbuddy.alloc(BuildResult.__sizeof__()))
|
||||
def __new__(self) -> rawptr:
|
||||
return rawptr(_mbuddy.alloc(BuildResult.__sizeof__()))
|
||||
|
||||
def __init__(self):
|
||||
self.Success = 0
|
||||
@@ -576,12 +575,12 @@ def _run_cmd_wait(cmd: str) -> int:
|
||||
string.memset(&sa, 0, win32.win32base.SECURITY_ATTRIBUTES.__sizeof__())
|
||||
string.memset(&pi, 0, win32process.PROCESS_INFORMATION.__sizeof__())
|
||||
sa.nLength = win32.win32base.SECURITY_ATTRIBUTES.__sizeof__()
|
||||
sa.lpSecurityDescriptor = t.CPtr(0)
|
||||
sa.lpSecurityDescriptor = None
|
||||
sa.bInheritHandle = 1
|
||||
si.cb = win32process.STARTUPINFOA.__sizeof__()
|
||||
# create_flags=0: the child inherits the parent console (output shown, like system);
|
||||
# si.dwFlags stays 0 after memset (no STARTF_USESTDHANDLES, no std handles).
|
||||
ok: int = win32process.CreateProcessA(t.CPtr(0), cmd_line, t.CPtr(0), t.CPtr(0), 1, 0, t.CPtr(0), t.CPtr(0), &si, &pi)
|
||||
ok: int = win32process.CreateProcessA(None, cmd_line, None, None, 1, 0, None, None, &si, &pi)
|
||||
# CreateProcessA failure diagnostics: read GetLastError immediately (later calls overwrite
|
||||
# it). Use warning, not error (error would sys.exit in a worker thread).
|
||||
if ok == 0:
|
||||
@@ -597,10 +596,10 @@ def _run_cmd_wait(cmd: str) -> int:
|
||||
return int(exit_code)
|
||||
|
||||
|
||||
def _llc_task_worker(arg: t.CPtr) -> t.CPtr:
|
||||
def _llc_task_worker(arg: rawptr) -> rawptr:
|
||||
"""llc thread entry: only calls _run_cmd_wait, no pool allocation (thread-safe)."""
|
||||
task: LlcTask* = (LlcTask*)(arg)
|
||||
if task is None: return t.CPtr(0)
|
||||
if task is None: return None
|
||||
# MLIR backend: validate (mlir-opt) -> lower (mlir-translate), then ASan opt -> llc
|
||||
if task.MlirOptCmd is not None:
|
||||
mo_rc: int = _run_cmd_wait(task.MlirOptCmd)
|
||||
@@ -608,21 +607,21 @@ def _llc_task_worker(arg: t.CPtr) -> t.CPtr:
|
||||
task.ExitCode = mo_rc
|
||||
task.FailStage = LLC_STAGE_MLIR_OPT
|
||||
task.Result = 1
|
||||
return t.CPtr(0)
|
||||
return None
|
||||
if task.MlirTranslateCmd is not None:
|
||||
mt_rc: int = _run_cmd_wait(task.MlirTranslateCmd)
|
||||
if mt_rc != 0:
|
||||
task.ExitCode = mt_rc
|
||||
task.FailStage = LLC_STAGE_MLIR_TRANSLATE
|
||||
task.Result = 1
|
||||
return t.CPtr(0)
|
||||
return None
|
||||
if task.OptCmd is not None:
|
||||
opt_rc: int = _run_cmd_wait(task.OptCmd)
|
||||
if opt_rc != 0:
|
||||
task.ExitCode = opt_rc
|
||||
task.FailStage = LLC_STAGE_ASAN_OPT
|
||||
task.Result = 1
|
||||
return t.CPtr(0)
|
||||
return None
|
||||
llc_rc: int = _run_cmd_wait(task.LlcCmd)
|
||||
task.ExitCode = llc_rc
|
||||
if llc_rc != 0:
|
||||
@@ -631,7 +630,7 @@ def _llc_task_worker(arg: t.CPtr) -> t.CPtr:
|
||||
else:
|
||||
task.FailStage = LLC_STAGE_NONE
|
||||
task.Result = 0
|
||||
return t.CPtr(0)
|
||||
return None
|
||||
|
||||
|
||||
def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
|
||||
@@ -650,7 +649,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
|
||||
return 0
|
||||
if max_threads <= 0: max_threads = 1
|
||||
# Thread-handle array: list[str] (str=bytes=i8*, explicit elem_size=8) stores handles;
|
||||
# list[t.CPtr] append crashes reading page zero. Grab the handle right after start().
|
||||
# list[rawptr] append crashes reading page zero. Grab the handle right after start().
|
||||
handles: list[str]* = list[str](_mbuddy, 8)
|
||||
if handles is None:
|
||||
VLogger.error("run_llc_parallel: failed to allocate thread handle array", "PhaseB")
|
||||
@@ -664,13 +663,13 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
|
||||
# spawn this batch
|
||||
for j in range(int(batch_n)):
|
||||
tsk: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size)
|
||||
th: vthreading.Thread* = vthreading.Thread(_llc_task_worker, t.CPtr(tsk))
|
||||
th: vthreading.Thread* = vthreading.Thread(_llc_task_worker, rawptr(tsk))
|
||||
th.start()
|
||||
# Read the handle right after start() (the Thread object's stack slot may be
|
||||
# reused; reading self.handle at join could see a cleared/overwritten value).
|
||||
handles.append(t.CPtr(th.handle))
|
||||
handles.append(rawptr(th.handle))
|
||||
for j in range(int(batch_n)):
|
||||
h_j: t.CPtr = t.CPtr(handles.get(batch_start + j))
|
||||
h_j: rawptr = rawptr(handles.get(batch_start + j))
|
||||
wr: uint32 = win32sync.WaitForSingleObject(h_j, 600000)
|
||||
if wr != 0: VLogger.error("llc thread join timeout/failure (not finished within 600 seconds)", "PhaseB")
|
||||
win32.win32base.CloseHandle(h_j)
|
||||
@@ -1052,8 +1051,8 @@ class TbPeLayout:
|
||||
SizeOfImage: uint64
|
||||
TextRva: uint64
|
||||
|
||||
def __new__(self) -> t.CPtr:
|
||||
return t.CPtr(_mbuddy.alloc(TbPeLayout.__sizeof__()))
|
||||
def __new__(self) -> rawptr:
|
||||
return rawptr(_mbuddy.alloc(TbPeLayout.__sizeof__()))
|
||||
|
||||
def __init__(self):
|
||||
self.Ok = 0
|
||||
@@ -1071,8 +1070,8 @@ class TbDump:
|
||||
FuncCap: int
|
||||
FuncCount: int
|
||||
|
||||
def __new__(self) -> t.CPtr:
|
||||
return t.CPtr(_mbuddy.alloc(TbDump.__sizeof__()))
|
||||
def __new__(self) -> rawptr:
|
||||
return rawptr(_mbuddy.alloc(TbDump.__sizeof__()))
|
||||
|
||||
def __init__(self):
|
||||
self.RowBuf = None
|
||||
@@ -1090,8 +1089,8 @@ class TbPool:
|
||||
Offs: bytes
|
||||
OffCount: int
|
||||
|
||||
def __new__(self) -> t.CPtr:
|
||||
return t.CPtr(_mbuddy.alloc(TbPool.__sizeof__()))
|
||||
def __new__(self) -> rawptr:
|
||||
return rawptr(_mbuddy.alloc(TbPool.__sizeof__()))
|
||||
|
||||
def __init__(self):
|
||||
self.Pool = None
|
||||
@@ -1118,9 +1117,12 @@ def _tb_rd_u32(buf: bytes, off: sizet) -> uint32:
|
||||
|
||||
|
||||
def _tb_rd_u64(buf: bytes, off: sizet) -> uint64:
|
||||
lo: uint64 = uint64(_tb_rd_u32(buf, off))
|
||||
hi: uint64 = uint64(_tb_rd_u32(buf, off + 4))
|
||||
return lo | (hi << 32)
|
||||
# Assemble via memcpy instead of u32 widening + shifts: the manual form left 0xFFFFFFFF in
|
||||
# the high half (a stale register/slot), which then looked like a wild pointer in the
|
||||
# stackmap tables. memcpy is exact and little-endian on x86-64.
|
||||
v: uint64 = 0
|
||||
string.memcpy(&v, buf + off, 8)
|
||||
return v
|
||||
|
||||
|
||||
def _tb_wr_u32(buf: bytes, off: sizet, v: uint64):
|
||||
@@ -1131,8 +1133,18 @@ def _tb_wr_u32(buf: bytes, off: sizet, v: uint64):
|
||||
|
||||
|
||||
def _tb_wr_u64(buf: bytes, off: sizet, v: uint64):
|
||||
_tb_wr_u32(buf, off, v & 0xFFFFFFFF)
|
||||
_tb_wr_u32(buf, off + 4, (v >> 32) & 0xFFFFFFFF)
|
||||
string.memcpy(buf + off, &v, 8)
|
||||
|
||||
|
||||
def _tb_wr_ptr(buf: bytes, off: sizet, p: str):
|
||||
"""Store a string pointer into a byte table without a ptr->int cast.
|
||||
|
||||
Do NOT write `memcpy(buf + off, &p, 8)`: passing `&p` (i8**) to a `rawptr` parameter is
|
||||
currently compiled as a dereference (it copies the string's first 8 bytes instead of the
|
||||
pointer value), so go through a typed slot instead.
|
||||
"""
|
||||
slot: str* = str*(buf + off)
|
||||
slot[0] = p
|
||||
|
||||
|
||||
# ---- tiny string helpers (no re module) ----
|
||||
@@ -1142,6 +1154,18 @@ def _tb_cc(s: str, i: sizet) -> int:
|
||||
return int(s[i]) & 0xFF
|
||||
|
||||
|
||||
def _tb_str_ok(s: str) -> int:
|
||||
"""Return 1 when s is a plausible user-space string pointer (not 0, -1 or garbage).
|
||||
|
||||
DWARF/objdump text is parsed into pointer-bearing tables; a single bad slot would later be
|
||||
dereferenced by _tb_cc/strlen and crash the compiler with ASan "unknown address 0xffff...".
|
||||
Callers use this to reject such a slot at the boundary instead of storing it.
|
||||
"""
|
||||
if s is None: return 0
|
||||
v: uint64 = uint64(s)
|
||||
return 1 if v >= 65536 and v <= 0x7FFFFFFFFFFF else 0
|
||||
|
||||
|
||||
def _tb_contains(s: str, sub: str) -> int:
|
||||
if s is None or sub is None: return 0
|
||||
return 1 if string.strstr(s, sub) is not None else 0
|
||||
@@ -1331,7 +1355,13 @@ def _tb_quoted_after(mb: memhub.MemBuddy*, s: str, key: str) -> str:
|
||||
|
||||
def _tb_dir_lookup(dirs: bytes, count: int, idx: int) -> str:
|
||||
for i in range(int(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))
|
||||
if int(_tb_rd_u32(dirs, sizet(i) * TB_DIR_SIZE)) == idx:
|
||||
p: uint64 = _tb_rd_u64(dirs, sizet(i) * TB_DIR_SIZE + 8)
|
||||
# fail-fast: a wild name pointer would crash inside _tb_is_abs_path/strlen later.
|
||||
if p < 65536 or p > 0x7FFFFFFFFFFF:
|
||||
VLogger.error(f"--traceback: internal error: DWARF directory record {i} has an invalid name pointer ({p})", "TRACEBACK")
|
||||
return None
|
||||
return rawptr(p)
|
||||
return None
|
||||
|
||||
|
||||
@@ -1345,8 +1375,20 @@ def _tb_resolve_file(mb: memhub.MemBuddy*, files: bytes, fcount: int, dirs: byte
|
||||
"""Resolve a file-table entry to a path (absolute name wins, else dir join)."""
|
||||
roff: sizet = sizet(frec) * TB_FILE_SIZE
|
||||
cached: uint64 = _tb_rd_u64(files, roff + 24)
|
||||
if cached != 0: return rawptr(cached)
|
||||
name: str = rawptr(_tb_rd_u64(files, roff + 8))
|
||||
if cached != 0:
|
||||
# fail-fast: a wild cached path would crash inside strlen/is_abs_path below; report the
|
||||
# record that carries it together with the table state instead.
|
||||
if cached < 65536 or cached > 0x7FFFFFFFFFFF:
|
||||
VLogger.error(f"--traceback: internal error: DWARF file record {frec} has an invalid cached path pointer ({cached})", "TRACEBACK")
|
||||
return None
|
||||
return rawptr(cached)
|
||||
nptr: uint64 = _tb_rd_u64(files, roff + 8)
|
||||
if nptr < 65536 or nptr > 0x7FFFFFFFFFFF:
|
||||
ridx: uint64 = uint64(_tb_rd_u32(files, roff))
|
||||
rdir: uint64 = uint64(_tb_rd_u32(files, roff + 4))
|
||||
VLogger.error(f"--traceback: internal error: DWARF file record {frec} has an invalid name pointer ({nptr}); record idx={ridx} dir_index={rdir}, records in table={fcount}", "TRACEBACK")
|
||||
return None
|
||||
name: str = rawptr(nptr)
|
||||
path: str = name
|
||||
if name is not None and _tb_is_abs_path(name) == 0:
|
||||
didx: int = int(_tb_rd_u32(files, roff + 4))
|
||||
@@ -1357,7 +1399,7 @@ def _tb_resolve_file(mb: memhub.MemBuddy*, files: bytes, fcount: int, dirs: byte
|
||||
if root is not None and _tb_is_abs_path(root) != 0: base = _tb_join(mb, root, base)
|
||||
path = _tb_join(mb, base, name)
|
||||
if path is None or string.strlen(path) == 0: path = "??"
|
||||
_tb_wr_u64(files, roff + 24, uint64(path))
|
||||
_tb_wr_ptr(files, roff + 24, path)
|
||||
return path
|
||||
|
||||
|
||||
@@ -1371,6 +1413,10 @@ def _tb_grow_rec(mb: memhub.MemBuddy*, buf: bytes, old_cap: int, rec_size: int,
|
||||
|
||||
def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump*, addr: uint64, path: str, line: int, fname: str = None) -> int:
|
||||
if d is None: return 1
|
||||
# Every row must carry a file path. A caller that could not resolve one passes None (or a
|
||||
# wild sentinel); storing that as-is makes the later strlen() sizing pass fault. Normalise to
|
||||
# the stackmap's existing "??" convention (the DWARF path already does the same).
|
||||
if _tb_str_ok(path) == 0: path = "??"
|
||||
if d.RowCount >= d.RowCap:
|
||||
ncap: int = d.RowCap * 2
|
||||
nb: bytes = _tb_grow_rec(mb, d.RowBuf, d.RowCap, TB_ROW_SIZE, ncap)
|
||||
@@ -1381,11 +1427,10 @@ def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump*, addr: uint64, path: str, line
|
||||
d.RowCap = ncap
|
||||
off: sizet = sizet(d.RowCount) * TB_ROW_SIZE
|
||||
_tb_wr_u64(d.RowBuf, off, addr)
|
||||
_tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FILE, uint64(path))
|
||||
_tb_wr_ptr(d.RowBuf, off + TB_ROW_OFF_FILE, path)
|
||||
_tb_wr_u32(d.RowBuf, off + TB_ROW_OFF_LINE, uint64(line))
|
||||
fv: uint64 = 0
|
||||
if fname is not None: fv = uint64(fname)
|
||||
_tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FUNC, fv)
|
||||
if _tb_str_ok(fname) != 0: _tb_wr_ptr(d.RowBuf, off + TB_ROW_OFF_FUNC, fname)
|
||||
else: _tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FUNC, 0)
|
||||
d.RowCount = d.RowCount + 1
|
||||
d.RawRowCount = d.RawRowCount + 1
|
||||
return 0
|
||||
@@ -1404,7 +1449,7 @@ def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump*, low: uint64, high: uint64, n
|
||||
off: sizet = sizet(d.FuncCount) * TB_FUNC_SIZE
|
||||
_tb_wr_u64(d.FuncBuf, off, low)
|
||||
_tb_wr_u64(d.FuncBuf, off + 8, high)
|
||||
_tb_wr_u64(d.FuncBuf, off + 16, uint64(name))
|
||||
_tb_wr_ptr(d.FuncBuf, off + 16, name)
|
||||
d.FuncCount = d.FuncCount + 1
|
||||
return 0
|
||||
|
||||
@@ -1549,10 +1594,10 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
if in_line != 0:
|
||||
if _tb_startswith(st, "debug_line[") != 0:
|
||||
# new CU: commit pending file, reset both tables
|
||||
if pkind == 1 and pname is not None and file_count < TB_FILE_CAP:
|
||||
if pkind == 1 and _tb_str_ok(pname) != 0 and file_count < TB_FILE_CAP:
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx))
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir))
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname))
|
||||
_tb_wr_ptr(files, sizet(file_count) * TB_FILE_SIZE + 8, pname)
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0))
|
||||
file_count += 1
|
||||
pkind = 0
|
||||
@@ -1562,10 +1607,10 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
file_count = 0
|
||||
continue
|
||||
if _tb_startswith(st, "file_names[") != 0:
|
||||
if pkind == 1 and pname is not None and file_count < TB_FILE_CAP:
|
||||
if pkind == 1 and _tb_str_ok(pname) != 0 and file_count < TB_FILE_CAP:
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx))
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir))
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname))
|
||||
_tb_wr_ptr(files, sizet(file_count) * TB_FILE_SIZE + 8, pname)
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0))
|
||||
file_count += 1
|
||||
pname = None
|
||||
@@ -1574,10 +1619,10 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
pidx = _tb_bracket_idx(st)
|
||||
continue
|
||||
if _tb_startswith(st, "directory_names[") != 0 or _tb_startswith(st, "include_directories[") != 0:
|
||||
if pkind == 1 and pname is not None and file_count < TB_FILE_CAP:
|
||||
if pkind == 1 and _tb_str_ok(pname) != 0 and file_count < TB_FILE_CAP:
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx))
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir))
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname))
|
||||
_tb_wr_ptr(files, sizet(file_count) * TB_FILE_SIZE + 8, pname)
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0))
|
||||
file_count += 1
|
||||
pname = None
|
||||
@@ -1586,9 +1631,13 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
val: str = _tb_value_after_sep(_tb_after_bracket(st))
|
||||
if val is not None and _tb_len_trimmed(val) > 0:
|
||||
if dir_count < TB_DIR_CAP:
|
||||
_tb_wr_u32(dirs, sizet(dir_count) * TB_DIR_SIZE, uint64(pidx))
|
||||
_tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, uint64(_tb_unquote(mb, val)))
|
||||
dir_count += 1
|
||||
dname: str = _tb_unquote(mb, val)
|
||||
if _tb_str_ok(dname) != 0:
|
||||
_tb_wr_u32(dirs, sizet(dir_count) * TB_DIR_SIZE, uint64(pidx))
|
||||
_tb_wr_ptr(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, dname)
|
||||
dir_count += 1
|
||||
else:
|
||||
VLogger.warning("--traceback: ignoring a DWARF directory entry whose name could not be copied", "TRACEBACK")
|
||||
pkind = 0
|
||||
else: pkind = 2
|
||||
continue
|
||||
@@ -1596,9 +1645,9 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
val2: str = _tb_unquote(mb, _tb_ltrim(st + 5))
|
||||
if pkind == 1: pname = val2
|
||||
else:
|
||||
if dir_count < TB_DIR_CAP and val2 is not None:
|
||||
if dir_count < TB_DIR_CAP and _tb_str_ok(val2) != 0:
|
||||
_tb_wr_u32(dirs, sizet(dir_count) * TB_DIR_SIZE, uint64(pidx))
|
||||
_tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, uint64(val2))
|
||||
_tb_wr_ptr(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, val2)
|
||||
dir_count += 1
|
||||
pkind = 0
|
||||
continue
|
||||
@@ -1608,10 +1657,10 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
pdir = _tb_parse_dec(_tb_ltrim(st + 10))
|
||||
continue
|
||||
if _tb_startswith(st, "Address") != 0 and _tb_contains(st, "Column") != 0:
|
||||
if pkind == 1 and pname is not None and file_count < TB_FILE_CAP:
|
||||
if pkind == 1 and _tb_str_ok(pname) != 0 and file_count < TB_FILE_CAP:
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx))
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir))
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname))
|
||||
_tb_wr_ptr(files, sizet(file_count) * TB_FILE_SIZE + 8, pname)
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0))
|
||||
file_count += 1
|
||||
pkind = 0
|
||||
@@ -1619,10 +1668,10 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
pdir = 0
|
||||
continue
|
||||
if _tb_cc(linebuf, 0) == 48 and _tb_cc(linebuf, 1) == 120:
|
||||
if pkind == 1 and pname is not None and file_count < TB_FILE_CAP:
|
||||
if pkind == 1 and _tb_str_ok(pname) != 0 and file_count < TB_FILE_CAP:
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx))
|
||||
_tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir))
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname))
|
||||
_tb_wr_ptr(files, sizet(file_count) * TB_FILE_SIZE + 8, pname)
|
||||
_tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0))
|
||||
file_count += 1
|
||||
pkind = 0
|
||||
@@ -1657,7 +1706,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*:
|
||||
|
||||
# ---- DWARF debug_info subprogram parsing ----
|
||||
if _tb_contains(linebuf, "DW_TAG_") != 0:
|
||||
if in_prog != 0 and cur_has_low != 0 and cname is not None and string.strlen(cname) > 0:
|
||||
if in_prog != 0 and cur_has_low != 0 and _tb_str_ok(cname) != 0 and string.strlen(cname) > 0:
|
||||
hi: uint64 = cur_low + 1
|
||||
if cur_has_high != 0:
|
||||
hi = cur_high
|
||||
@@ -1734,8 +1783,8 @@ class TbCallParse:
|
||||
Grp: bytes # array of TB_GRP_SIZE slots
|
||||
GrpCap: int
|
||||
|
||||
def __new__(self) -> t.CPtr:
|
||||
return t.CPtr(_mbuddy.alloc(TbCallParse.__sizeof__()))
|
||||
def __new__(self) -> rawptr:
|
||||
return rawptr(_mbuddy.alloc(TbCallParse.__sizeof__()))
|
||||
|
||||
def __init__(self):
|
||||
self.Cr = None
|
||||
@@ -1776,8 +1825,8 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int)
|
||||
if uint64(_tb_rd_u32(grp, off + TB_GRP_OFF_USED)) == 0:
|
||||
if do_insert == 0: return -1
|
||||
_tb_wr_u32(grp, off + TB_GRP_OFF_USED, uint64(1))
|
||||
_tb_wr_u64(grp, off + TB_GRP_OFF_CALLER, uint64(caller))
|
||||
_tb_wr_u64(grp, off + TB_GRP_OFF_CALLEE, uint64(callee))
|
||||
_tb_wr_ptr(grp, off + TB_GRP_OFF_CALLER, caller)
|
||||
_tb_wr_ptr(grp, off + TB_GRP_OFF_CALLEE, callee)
|
||||
_tb_wr_u32(grp, off + TB_GRP_OFF_HEAD, uint64(TB_IDX_NONE))
|
||||
_tb_wr_u32(grp, off + TB_GRP_OFF_TAIL, uint64(TB_IDX_NONE))
|
||||
_tb_wr_u32(grp, off + TB_GRP_OFF_CURSOR, uint64(TB_IDX_NONE))
|
||||
@@ -1811,9 +1860,9 @@ def _tb_cp_add_cr(mb: memhub.MemBuddy*, cp: TbCallParse*, caller: str, callee: s
|
||||
cp.Cr = nb
|
||||
cp.CrCap = ncap
|
||||
off: sizet = sizet(cp.CrN) * TB_CR_SIZE
|
||||
_tb_wr_u64(cp.Cr, off + TB_CR_OFF_CALLER, uint64(caller))
|
||||
_tb_wr_u64(cp.Cr, off + TB_CR_OFF_CALLEE, uint64(callee))
|
||||
_tb_wr_u64(cp.Cr, off + TB_CR_OFF_FILE, uint64(file))
|
||||
_tb_wr_ptr(cp.Cr, off + TB_CR_OFF_CALLER, caller)
|
||||
_tb_wr_ptr(cp.Cr, off + TB_CR_OFF_CALLEE, callee)
|
||||
_tb_wr_ptr(cp.Cr, off + TB_CR_OFF_FILE, file)
|
||||
_tb_wr_u32(cp.Cr, off + TB_CR_OFF_LINE, uint64(line))
|
||||
_tb_wr_u32(cp.Cr, off + TB_CR_OFF_NEXT, uint64(TB_IDX_NONE))
|
||||
cp.CrN = cp.CrN + 1
|
||||
@@ -1830,8 +1879,8 @@ def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse*, sym: str, file: str, d
|
||||
cp.Fr = nb
|
||||
cp.FrCap = ncap
|
||||
off: sizet = sizet(cp.FrN) * TB_FR_SIZE
|
||||
_tb_wr_u64(cp.Fr, off + TB_FR_OFF_SYM, uint64(sym))
|
||||
_tb_wr_u64(cp.Fr, off + TB_FR_OFF_FILE, uint64(file))
|
||||
_tb_wr_ptr(cp.Fr, off + TB_FR_OFF_SYM, sym)
|
||||
_tb_wr_ptr(cp.Fr, off + TB_FR_OFF_FILE, file)
|
||||
_tb_wr_u32(cp.Fr, off + TB_FR_OFF_DEFLINE, uint64(defline))
|
||||
cp.FrN = cp.FrN + 1
|
||||
return 0
|
||||
@@ -1853,6 +1902,10 @@ def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str:
|
||||
got: LONG = f.read_all(buf, sizet(sz) + 2)
|
||||
f.close()
|
||||
if got < 0: return None
|
||||
# NUL-terminate at the actually read length. The pool buffer is NOT zero-filled (MemBuddy's
|
||||
# diagnostic fill is 0xCD), so without this the caller's strlen() walks into uninitialised
|
||||
# bytes and can run past the end of the arena.
|
||||
buf[got] = 0
|
||||
return buf
|
||||
|
||||
|
||||
@@ -1873,7 +1926,7 @@ def _tb_parse_f_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCal
|
||||
defline: int = int(_tb_parse_dec(s + p))
|
||||
p = f3 + 1
|
||||
file: str = _tb_dup_span(mb, s + p, b - p)
|
||||
if sym is None or file is None: return 0
|
||||
if _tb_str_ok(sym) == 0 or _tb_str_ok(file) == 0: return 0
|
||||
return _tb_cp_add_fr(mb, cp, sym, file, defline)
|
||||
|
||||
|
||||
@@ -1899,7 +1952,7 @@ def _tb_parse_c_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCal
|
||||
line: int = int(_tb_parse_dec(s + p))
|
||||
p = e4 + 1
|
||||
file: str = _tb_dup_span(mb, s + p, b - p)
|
||||
if caller is None or callee is None or file is None: return 0
|
||||
if _tb_str_ok(caller) == 0 or _tb_str_ok(callee) == 0 or _tb_str_ok(file) == 0: return 0
|
||||
return _tb_cp_add_cr(mb, cp, caller, callee, file, line)
|
||||
|
||||
|
||||
@@ -1967,7 +2020,7 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int:
|
||||
|
||||
def _tb_emit_call_row(mb: memhub.MemBuddy*, d: TbDump*, cp: TbCallParse*, img_lo: uint64, caller: str, callee: str, ret_va: uint64) -> int:
|
||||
"""Emit a row for a return address from the next unconsumed C record of (caller, callee)."""
|
||||
if caller is None or callee is None or cp.Grp is None or ret_va < img_lo: return 0
|
||||
if _tb_str_ok(caller) == 0 or _tb_str_ok(callee) == 0 or cp.Grp is None or ret_va < img_lo: return 0
|
||||
slot: int = _tb_grp_get(cp.Grp, cp.GrpCap, caller, callee, 0)
|
||||
if slot < 0: return 0
|
||||
goff: sizet = sizet(slot) * TB_GRP_SIZE
|
||||
@@ -1984,11 +2037,11 @@ 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
|
||||
if _tb_str_ok(sym) == 0 or cp.Fr is None or cp.FrN <= 0 or addr < img_lo: return 0
|
||||
for i in range(int(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:
|
||||
if _tb_str_ok(s) != 0 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)
|
||||
@@ -2066,7 +2119,7 @@ def _tb_scan_objdump(mb: memhub.MemBuddy*, dump: str, img_lo: uint64, d: TbDump*
|
||||
j: sizet = lb
|
||||
while j < le and _tb_cc(dump, j) != 62: j += 1
|
||||
cur_func = _tb_dup_span(mb, dump + lb, j - lb)
|
||||
if cur_func is not None: _tb_emit_entry_row(mb, d, cp, img_lo, laddr, cur_func)
|
||||
if _tb_str_ok(cur_func) != 0: _tb_emit_entry_row(mb, d, cp, img_lo, laddr, cur_func)
|
||||
continue
|
||||
# ---- instruction line `ADDR: bytes mnemonic operands` ----
|
||||
k: sizet = ls
|
||||
@@ -2275,7 +2328,14 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
pool_need: sizet = 1
|
||||
i = 0
|
||||
while i < uniq:
|
||||
pth: str = rawptr(_tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FILE))
|
||||
fptr: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FILE)
|
||||
# fail-fast: Windows x64 user addresses stay below 0x7FFF_FFFF_FFFF; anything else is a
|
||||
# wild pointer (0, -1 or an uninitialised slot). Report the record instead of letting
|
||||
# strlen walk off into unmapped memory (ASan access-violation at 0xffffffffffffffff).
|
||||
if fptr < 65536 or fptr > 0x7FFFFFFFFFFF:
|
||||
VLogger.error(f"--traceback: internal error: line record {i} carries an invalid file-path pointer ({fptr})", "TRACEBACK")
|
||||
return 1
|
||||
pth: str = rawptr(fptr)
|
||||
pool_need += string.strlen(pth) + 1
|
||||
i += 1
|
||||
# our rows carry the function name directly (string pool); DWARF rows take it from the subprogram table.
|
||||
@@ -2283,13 +2343,21 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
while i < uniq:
|
||||
fp: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FUNC)
|
||||
if fp != 0:
|
||||
if fp > 0x7FFFFFFFFFFF:
|
||||
VLogger.error(f"--traceback: internal error: line record {i} carries an invalid function-name pointer ({fp})", "TRACEBACK")
|
||||
return 1
|
||||
fns: str = rawptr(fp)
|
||||
if fns is not None: pool_need += string.strlen(fns) + 1
|
||||
pool_need += string.strlen(fns) + 1
|
||||
i += 1
|
||||
i = 0
|
||||
while i < fkept:
|
||||
nm0: str = rawptr(_tb_rd_u64(d.FuncBuf, sizet(i) * TB_FUNC_SIZE + 16))
|
||||
if nm0 is not None: pool_need += string.strlen(nm0) + 1
|
||||
nmf: uint64 = _tb_rd_u64(d.FuncBuf, sizet(i) * TB_FUNC_SIZE + 16)
|
||||
if nmf != 0:
|
||||
if nmf > 0x7FFFFFFFFFFF:
|
||||
VLogger.error(f"--traceback: internal error: subprogram record {i} carries an invalid name pointer ({nmf})", "TRACEBACK")
|
||||
return 1
|
||||
nm0: str = rawptr(nmf)
|
||||
pool_need += string.strlen(nm0) + 1
|
||||
i += 1
|
||||
p: TbPool* = TbPool()
|
||||
if p is None:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
@@ -368,10 +367,10 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg
|
||||
class_names_buf: bytes = mb.alloc(sizet(Phase1.MAX_CLASSES) * Phase1.CLASS_NAME_LEN)
|
||||
parent_names_buf: bytes = mb.alloc(sizet(Phase1.MAX_CLASSES) * Phase1.CLASS_NAME_LEN)
|
||||
def_sha1s_buf: bytes = mb.alloc(Phase1.MAX_CLASSES * Phase1.SHA1_LEN)
|
||||
topo_order: t.CPtr = mb.alloc(4 * Phase1.MAX_FILE_DEPS)
|
||||
topo_count_box: t.CPtr = mb.alloc(4)
|
||||
generic_file_indices: t.CPtr = mb.alloc(4 * Phase1.MAX_FILE_DEPS)
|
||||
generic_file_count_box: t.CPtr = mb.alloc(4)
|
||||
topo_order: rawptr = mb.alloc(4 * Phase1.MAX_FILE_DEPS)
|
||||
topo_count_box: rawptr = mb.alloc(4)
|
||||
generic_file_indices: rawptr = mb.alloc(4 * Phase1.MAX_FILE_DEPS)
|
||||
generic_file_count_box: rawptr = mb.alloc(4)
|
||||
if generic_file_indices is not None: string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS)
|
||||
if generic_file_count_box is not None: string.memset(generic_file_count_box, 0, 4)
|
||||
topo_count: int = 0
|
||||
@@ -427,7 +426,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg
|
||||
file_idx: int = int(i)
|
||||
if topo_count > 0:
|
||||
od_addr: uint64 = uint64(topo_order) + i * 4
|
||||
od_ptr: int* = (int*)(t.CPtr(od_addr))
|
||||
od_ptr: int* = int*(od_addr)
|
||||
if od_ptr is not None: file_idx = od_ptr[0]
|
||||
|
||||
entry_addr_r: uint64 = uint64(result.Entries) + file_idx * entry_size
|
||||
|
||||
@@ -1,31 +1,14 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import sys
|
||||
import win32.fileio as fileio
|
||||
import win32.win32file
|
||||
import win32.win32base
|
||||
import ast
|
||||
import mlirlite
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HandlesTranslator
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as GenGenerator
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.Phase.BuildPipeline as BuildPipeline
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Stub.StubGen.Converter as StubConverter
|
||||
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
|
||||
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
|
||||
import lib.Stub.StubMerger.StubMergerIR as StubMergerIR
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
|
||||
import lib.Phase.Phase1.Phase1Scan as Phase1Scan
|
||||
import lib.Phase.Phase1.Phase1Topo as Phase1Topo
|
||||
import lib.Phase.Phase1 as Phase1
|
||||
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
@@ -40,7 +23,7 @@ import lib.core.Gen.GenApi as GenApi
|
||||
|
||||
# _ScanClassInheritance - pre-scan includes files, parse ASTs and collect ClassDef
|
||||
# names/parent names into flat byte arrays; returns the class count (-1 on failure).
|
||||
def _ScanClassInheritance(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, generic_file_indices: t.CPtr, generic_file_count_box: t.CPtr) -> int:
|
||||
def _ScanClassInheritance(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, generic_file_indices: rawptr, generic_file_count_box: rawptr) -> int:
|
||||
"""Pre-scan includes files and collect class inheritance info."""
|
||||
if result is None: return -1
|
||||
# The three flat buffers are mb.alloc'ed by the caller; a NULL buffer would make
|
||||
@@ -322,7 +305,7 @@ def _AnnIsContainer(ann: ast.AST*) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _ScanTreeForContainers(node: ast.AST*, need_list_box: t.CPtr, need_dict_box: t.CPtr, depth: int = 0):
|
||||
def _ScanTreeForContainers(node: ast.AST*, need_list_box: rawptr, need_dict_box: rawptr, depth: int = 0):
|
||||
"""Recursively scan the AST for list/dict container usage."""
|
||||
# Recursion depth guard: a self-referential AST cycle would recurse until the
|
||||
# stack is exhausted; fail-fast abort.
|
||||
|
||||
@@ -1,30 +1,14 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import win32.fileio as fileio
|
||||
import win32.win32file
|
||||
import win32.win32base
|
||||
import ast
|
||||
import mlirlite
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HandlesTranslator
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.core.Gen.Generator as GenGenerator
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.Phase.BuildPipeline as BuildPipeline
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Stub.StubGen.Converter as StubConverter
|
||||
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
|
||||
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
|
||||
import lib.Stub.StubMerger.StubMergerIR as StubMergerIR
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
|
||||
import lib.Phase.Phase1.Phase1Scan as Phase1Scan
|
||||
import lib.Phase.Phase1.Phase1Topo as Phase1Topo
|
||||
import lib.Phase.Phase1 as Phase1
|
||||
|
||||
# Phase1Topo - topologically sort source files by class inheritance and import dependencies.
|
||||
@@ -32,7 +16,7 @@ import lib.Phase.Phase1 as Phase1
|
||||
|
||||
# _TopoSortFiles - topologically sort files by class inheritance (Kahn).
|
||||
# Builds a "file SHA1 -> dependency SHA1 set" map, computes in-degrees (parent-file first), then outputs the order; returns 0 or -1.
|
||||
def _TopoSortFiles(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, class_count: int, out_order: t.CPtr, out_count: t.CPtr, temp_dir: str, td_len_ts: sizet) -> int:
|
||||
def _TopoSortFiles(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, class_count: int, out_order: rawptr, out_count: rawptr, temp_dir: str, td_len_ts: sizet) -> int:
|
||||
"""Topologically sort files by class inheritance and import dependencies."""
|
||||
if result is None or out_order is None or out_count is None: return -1
|
||||
|
||||
@@ -44,9 +28,9 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, re
|
||||
# 取消整数提升后,模块属性 CDefine(Phase1.MAX_*) 按最小位宽物化为 i16/i8;三段乘积 256*16*17=69632 会在 i16 回绕,
|
||||
# 首乘数显式 sizet() 加宽到 64 位。上一行 256*17=4352 未超 i16,故无需改。
|
||||
file_deps_buf: bytes = mb.alloc(sizet(Phase1.MAX_FILE_DEPS) * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
|
||||
file_dep_counts: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_indegrees: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_processed: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_dep_counts: rawptr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_indegrees: rawptr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
file_processed: rawptr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
|
||||
|
||||
if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None:
|
||||
if file_sha1s_buf is not None: mb.free(file_sha1s_buf)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import string
|
||||
@@ -38,8 +37,7 @@ define SRC_BUF_SIZE = 1048576
|
||||
# Max source files (recursive scanning grows the count; too small truncates the list -> undefined symbol)
|
||||
define MAX_SRC_FILES = 128
|
||||
|
||||
@t.NoVTable
|
||||
class SrcFileEntry:
|
||||
novirtual class SrcFileEntry:
|
||||
"""Source file entry"""
|
||||
Path: str # full path
|
||||
Sha1: str # first 16 chars of SHA1
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
@@ -112,6 +110,17 @@ def Load_project_config(path: str) -> int:
|
||||
# Read linker.flags array, join into a space-separated string
|
||||
ld_flags_val: JsonValue* = linker["flags"]
|
||||
LinkerFlags = _join_flags_array(ld_flags_val)
|
||||
# mingw-w64:同时链接 -lmsvcrt 与 -lucrt 时,GNU ld 会从两个 import 库各拉出一个都定义
|
||||
# __imp_<name> 的成员(现场:__imp_ldexp 同时出现在 libmsvcrt 与
|
||||
# libapi-ms-win-crt-math),直接报 "multiple definition"。lld 按需解析 import 库不会冲突,
|
||||
# 仓库默认链接命令也一直是 lld;项目配置漏写 -fuse-ld 时在这里补齐,避免逐个测试改配置。
|
||||
if LinkerCmd is not None and LinkerFlags is not None and string.strstr(LinkerCmd, "clang") is not None:
|
||||
if string.strstr(LinkerFlags, "-fuse-ld") is None and string.strstr(LinkerFlags, "-lucrt") is not None:
|
||||
lf_cap: sizet = string.strlen(LinkerFlags) + 32
|
||||
lf_new: str = _mbuddy.alloc(lf_cap)
|
||||
if lf_new is not None:
|
||||
viperlib.snprintf(lf_new, lf_cap, "-fuse-ld=lld %s", LinkerFlags)
|
||||
LinkerFlags = lf_new
|
||||
# Read linker.static_libs array: explicit static libs (.a/.obj); joined raw here,
|
||||
# then resolved to abs paths against project_dir in resolve_paths.
|
||||
sl_val: JsonValue* = linker["static_libs"]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
|
||||
from .Config import Load_project_config, resolve_paths
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.VLogger as VLogger
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import string
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import string
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
@@ -197,9 +196,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
# 2b. --traceback: force the traceback runtime module into the reachable set (TPC: used_includes.add('traceback')).
|
||||
# Its Install() symbol and the @llvm.global_ctors ctor come only from compiling this module, so a missing file is fail-fast.
|
||||
if BuildPipeline._traceback_mode != 0:
|
||||
tb_abs: t.CPtr = stdlib.malloc(8)
|
||||
tb_rel: t.CPtr = stdlib.malloc(8)
|
||||
tb_inc: t.CPtr = stdlib.malloc(8)
|
||||
tb_abs: rawptr = stdlib.malloc(8)
|
||||
tb_rel: rawptr = stdlib.malloc(8)
|
||||
tb_inc: rawptr = stdlib.malloc(8)
|
||||
tb_found: int = -1
|
||||
if tb_abs is not None and tb_rel is not None and tb_inc is not None:
|
||||
tb_abs_slot: sizet* = (sizet*)(tb_abs)
|
||||
@@ -230,7 +229,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
processed[0] = '\0'
|
||||
proc_len: sizet = 0
|
||||
reachable_count: int = 0
|
||||
wl_pos: t.CPtr = stdlib.malloc(8)
|
||||
wl_pos: rawptr = stdlib.malloc(8)
|
||||
if wl_pos is None:
|
||||
stdlib.free(worklist)
|
||||
stdlib.free(processed)
|
||||
@@ -289,9 +288,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
continue
|
||||
|
||||
# includes: resolve on demand via the filesystem (unreferenced includes are never touched)
|
||||
out_abs: t.CPtr = stdlib.malloc(8)
|
||||
out_rel: t.CPtr = stdlib.malloc(8)
|
||||
out_inc: t.CPtr = stdlib.malloc(8)
|
||||
out_abs: rawptr = stdlib.malloc(8)
|
||||
out_rel: rawptr = stdlib.malloc(8)
|
||||
out_inc: rawptr = stdlib.malloc(8)
|
||||
if out_abs is None or out_rel is None or out_inc is None:
|
||||
if out_abs is not None: stdlib.free(out_abs)
|
||||
if out_rel is not None: stdlib.free(out_rel)
|
||||
@@ -299,10 +298,10 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
stdlib.free(mod_buf)
|
||||
continue
|
||||
# Defensive init of the output slots (the success path always writes all). The slot union must use (sizet*):
|
||||
# t.CPtr* collapses to t.CPtr and [0] becomes a 1-byte access, truncating the pointer (0x2e crash root cause).
|
||||
abs_slot: sizet* = (sizet*)(out_abs)
|
||||
rel_slot: sizet* = (sizet*)(out_rel)
|
||||
inc_slot: sizet* = (sizet*)(out_inc)
|
||||
# rawptr* collapses to rawptr and [0] becomes a 1-byte access, truncating the pointer (0x2e crash root cause).
|
||||
abs_slot: sizet* = sizet*(out_abs)
|
||||
rel_slot: sizet* = sizet*(out_rel)
|
||||
inc_slot: sizet* = sizet*(out_inc)
|
||||
abs_slot[0] = 0
|
||||
rel_slot[0] = 0
|
||||
inc_slot[0] = 0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
|
||||
@@ -1,29 +1,11 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import mlirlite
|
||||
import win32.win32file as win32file
|
||||
import win32.win32base as win32base
|
||||
import win32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Gen.Translator as HandlesTranslator
|
||||
import lib.Phase.BuildPipeline as BuildPipeline
|
||||
import lib.Stub.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
import lib.Stub.StubMerger.StubMergerIR as StubMergerIR
|
||||
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
|
||||
# StubMergerTopo - reverse-topological sort of reachable includes (dependencies first).
|
||||
# Functions live in this module; cross-module globals are accessed via StubMerger._xxx.
|
||||
@@ -33,9 +15,9 @@ import lib.Stub.StubMerger as StubMerger
|
||||
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, store_mod_arr: bytes, reachable_set: bytes, reachable_count: int, sorted_idx: sizet*) -> int:
|
||||
"""Reverse-topologically sort reachable includes (dependencies first); store indices go to sorted_idx."""
|
||||
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None: return 0
|
||||
indegree: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
|
||||
queue: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
|
||||
rel_idx: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
|
||||
indegree: sizet* = sizet*(stdlib.malloc(8 * (store_count + 1)))
|
||||
queue: sizet* = sizet*(stdlib.malloc(8 * (store_count + 1)))
|
||||
rel_idx: sizet* = sizet*(stdlib.malloc(8 * (store_count + 1)))
|
||||
if indegree is None or queue is None or rel_idx is None:
|
||||
if indegree is not None: stdlib.free(indegree)
|
||||
if queue is not None: stdlib.free(queue)
|
||||
|
||||
@@ -1,22 +1,5 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import mlirlite
|
||||
import win32.win32file as win32file
|
||||
import win32.win32base as win32base
|
||||
import win32.fileio as fileio
|
||||
import viperlib
|
||||
import sys
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.Gen.Translator as HandlesTranslator
|
||||
import lib.Phase.BuildPipeline as BuildPipeline
|
||||
import lib.Stub.StubGen.VpiReader as VpiReader
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
# StubMerger - merges dependency stub declarations into the main IR (Phase2 core):
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
import memhub
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import stdio
|
||||
@@ -38,7 +37,7 @@ define DIAG_MAX_FRAMES = 32 # 调用链上限(与 TypeGenMixin.TRACE_MAX 对
|
||||
# (import 触发依赖加载 / 泛型特化 / 函数体翻译)时的触发点,
|
||||
# 用于"从错误发生点向外展示触发过程"。
|
||||
# 所有字符串都用 stdlib 深拷贝:编译期池会回绕,不能借用池内指针。
|
||||
class DiagEntry:
|
||||
struct DiagEntry:
|
||||
# 字段名不要与"本模块 import 的类名"重名:TPC 的类型/符号表按**非限定名**索引
|
||||
# (Gen.structs / SymbolTable / _mangle_func_name),曾把本字段的 `File` 与
|
||||
# `win32.fileio.File` 撞在一起,导致同模块 `fileio.File(...)` 的构造调用把
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -922,7 +921,7 @@ novirtual class AssignGenMixin:
|
||||
return 0
|
||||
|
||||
def _annotation_has_cptr_marker(self, annot: ast.AST*) -> int:
|
||||
"""Return 1 if the annotation union carries a CPtr marker (the star form `<base> | t.CPtr`)."""
|
||||
"""Return 1 if the annotation union carries a CPtr marker (the star form `<base> | rawptr`)."""
|
||||
if annot is None: return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
@@ -2796,6 +2795,10 @@ novirtual class AssignGenMixin:
|
||||
lv_target_ty: mlirlite.LLVMType* = None
|
||||
if alloca.Ty is not None: lv_target_ty = alloca.Ty.Pointee
|
||||
rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, lv_target_ty, "local variable annotation")
|
||||
if rhs_val is None:
|
||||
# fail-fast: 右值翻译失败时绝不能静默跳过整条声明(此前直接落到 `if rhs_val is
|
||||
# not None` 之外,变量永远保持未初始化,运行期读到栈垃圾后断言崩溃)。
|
||||
self.Gen.TypeGenErr.fatal_error(aa, f"the right-hand side of the declaration of '{nm.id}' could not be translated (type inference failed; see the preceding diagnostic)", "TypeError")
|
||||
if rhs_val is not None:
|
||||
# Fix degraded annotation: rebuild the alloca with the precise RHS struct type
|
||||
precise_rhs_ty: mlirlite.LLVMType* = None
|
||||
@@ -3239,10 +3242,16 @@ novirtual class AssignGenMixin:
|
||||
if sub_alloca is not None and sub_alloca.Ty is not None and sub_alloca.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(sub_alloca.Ty) != 0:
|
||||
sub_pointee: mlirlite.LLVMType* = sub_alloca.Ty.Pointee
|
||||
cls_nm_set: str = self.Gen.StructGen.get_class_name_by_type(pool, sub_pointee)
|
||||
obj_val_set: mlirlite.Value* = mlirlite.build_load(builder, sub_pointee, sub_alloca)
|
||||
# Pointer variable (X*): sub_pointee is Ptr(Struct); load it to inspect the inner struct
|
||||
if cls_nm_set is None and obj_val_set is not None and self.Gen.ExprGenBase.is_ptr_type(sub_pointee) != 0 and sub_pointee.Pointee != 0:
|
||||
cls_nm_set = self.Gen.StructGen.get_class_name_by_type(pool, sub_pointee.Pointee)
|
||||
obj_val_set: mlirlite.Value* = None
|
||||
# 值类型对象槽(`d: dict = dict(bd)`):槽地址就是 self 指针。
|
||||
# 此前无条件 load,值类型会传出整个 struct 值当 self(非法),
|
||||
# 指针类型才需要先 load 出对象指针。
|
||||
if cls_nm_set is not None: obj_val_set = sub_alloca
|
||||
else:
|
||||
obj_val_set = mlirlite.build_load(builder, sub_pointee, sub_alloca)
|
||||
# Pointer variable (X*): sub_pointee is Ptr(Struct); load it to inspect the inner struct
|
||||
if obj_val_set is not None and self.Gen.ExprGenBase.is_ptr_type(sub_pointee) != 0 and sub_pointee.Pointee != 0:
|
||||
cls_nm_set = self.Gen.StructGen.get_class_name_by_type(pool, sub_pointee.Pointee)
|
||||
if cls_nm_set is not None and obj_val_set is not None:
|
||||
key_val_set: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_asgn.slice, None, 0, trans)
|
||||
if key_val_set is not None:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import mlirlite
|
||||
|
||||
@@ -2,7 +2,6 @@ import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.Translator as HT
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -130,9 +129,9 @@ novirtual class CallGenBase:
|
||||
def _auto_addr_mode(self, name: str, idx: int) -> int:
|
||||
"""Return the value-reference mode for parameter idx of a callee symbol name (0 if none/unknown)."""
|
||||
if self.AutoAddrModes is None or name is None or idx < 0: return 0
|
||||
v: t.CPtr = self.AutoAddrModes.__getitem__(name)
|
||||
v: rawptr = self.AutoAddrModes.__getitem__(name)
|
||||
if v is None: return 0
|
||||
modes: str = t.CPtr(v)
|
||||
modes: str = rawptr(v)
|
||||
i: int = 0
|
||||
while i < idx and modes[i] != char(0): i += 1
|
||||
if i != idx: return 0
|
||||
@@ -1298,7 +1297,7 @@ novirtual class CallGenBase:
|
||||
if use_bare != 0: viperlib.snprintf(key_buf, key_len, "%s.%s", class_sha1, method_name)
|
||||
else:
|
||||
viperlib.snprintf(key_buf, key_len, "%s.%s.%s", class_sha1, class_name, method_name)
|
||||
v: t.CPtr = ht.__getitem__(key_buf)
|
||||
v: rawptr = ht.__getitem__(key_buf)
|
||||
stdlib.free(key_buf)
|
||||
if v is None: return None
|
||||
return rawptr(v)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -786,8 +785,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
string.memset(operands, 0, operand_size * ASM_MAX_OPERANDS)
|
||||
|
||||
# Clobber name array: 8 bytes/slot, capacity ASM_MAX_CLOBBERS, decoupled from
|
||||
# the operand limit; a single-level t.CPtr buffer with slots cast to str*.
|
||||
clobbers: t.CPtr = pool.alloc(8 * ASM_MAX_CLOBBERS)
|
||||
# the operand limit; a single-level rawptr buffer with slots cast to str*.
|
||||
clobbers: rawptr = pool.alloc(8 * ASM_MAX_CLOBBERS)
|
||||
if clobbers is None: return None
|
||||
string.memset(clobbers, 0, 8 * ASM_MAX_CLOBBERS)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -343,7 +342,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
while tail is not None and mlirlite.value_get_next(tail) is not None: tail = mlirlite.value_get_next(tail)
|
||||
# Default-argument filling: if the call site supplies fewer args than the
|
||||
# definition, fill the missing ones (defined default, else zero).
|
||||
mdf_defaults: t.CPtr = None
|
||||
mdf_defaults: rawptr = None
|
||||
mdf_default_count: int = 0
|
||||
mdf_param_count: int = 0
|
||||
if trans is not None and trans._funcs is not None:
|
||||
@@ -1191,7 +1190,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
|
||||
# Default-argument filling when the call supplies fewer args than the
|
||||
# definition; look up the function's defaults info.
|
||||
mdf_defaults: t.CPtr = None
|
||||
mdf_defaults: rawptr = None
|
||||
mdf_default_count: int = 0
|
||||
mdf_param_count: int = 0
|
||||
if trans is not None and trans._funcs is not None:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -149,7 +148,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile, cargs)
|
||||
if new_ptr is not None:
|
||||
storage_ptr = new_ptr
|
||||
# __new__ declares `-> t.CPtr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# __new__ declares `-> rawptr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# Using it directly degrades method dispatch; bitcast is a zero-cost type-layer fix.
|
||||
if new_ptr.Ty is not None:
|
||||
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
|
||||
@@ -711,7 +710,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name, "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct, is_volatile, cargs)
|
||||
if new_ptr is not None:
|
||||
storage_ptr = new_ptr
|
||||
# __new__ declares `-> t.CPtr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# __new__ declares `-> rawptr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# Using it directly degrades method dispatch; bitcast is a zero-cost type-layer fix.
|
||||
if new_ptr.Ty is not None:
|
||||
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
|
||||
@@ -1184,7 +1183,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans, None, gc_volatile, gc_arg_nodes)
|
||||
if new_ptr is not None:
|
||||
storage_ptr = new_ptr
|
||||
# __new__ declares `-> t.CPtr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# __new__ declares `-> rawptr` (i8*) but the class type is Ptr(struct_ty).
|
||||
# Using it directly degrades method dispatch; bitcast is a zero-cost type-layer fix.
|
||||
if new_ptr.Ty is not None:
|
||||
nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty)
|
||||
|
||||
@@ -2,7 +2,6 @@ import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Expr.ExprGenCls as ExprGenCls
|
||||
import lib.core.Gen.Expr.ExprGenName as ExprGenName
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -28,7 +27,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
|
||||
# _tc_h0_generic_func - generic function call: infer/specialize type args, then emit the call.
|
||||
# Must run before normal function/constructor dispatch; hit_box marks handled void calls.
|
||||
def _tc_h0_generic_func(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h0_generic_func(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
if cl is None or trans is None: return None
|
||||
if self.Gen.ClassGenGeneric.GenericFuncKeys is None: return None
|
||||
if cl.func is None: return None
|
||||
@@ -148,7 +147,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
if string.strcmp(kw.arg, ag.arg) == 0: return int(ki)
|
||||
return -1
|
||||
|
||||
def _emit_generic_func_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, cl: ast.Call*, spec_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _emit_generic_func_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, cl: ast.Call*, spec_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Emit the specialized-function call, coercing args to the specialized param types."""
|
||||
func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name)
|
||||
if func is None:
|
||||
@@ -189,7 +188,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
# 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)
|
||||
|
||||
def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Compile-time super()/ctraits detection; sets hit_box on interception, else returns None."""
|
||||
# super().method(args) -> static call to the parent method. Must intercept before attribute
|
||||
# dispatch, else Call(super) is treated as a plain function call and lookup hits self/vtable.
|
||||
@@ -221,7 +220,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return mlirlite.const_int32(pool, 0)
|
||||
return None
|
||||
|
||||
def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Special c.Deref/Asm/LLVMIR calls; marks hit_box for void calls, else returns None."""
|
||||
# __asm__(...) / __llvmir__(...) sugar: bare calls equal c.Asm(...) / c.LLVMIR(...). Must
|
||||
# intercept before the c.* attribute branch, since the bare cl.func is a Name.
|
||||
@@ -301,7 +300,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return self.Gen.AsyncGen.translate_coro_gather(builder, pool, mod, cl, trans)
|
||||
return None
|
||||
|
||||
def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
def _tc_h3_stdarg_cast(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
"""stdarg sugar and str/int/bool built-in casts; returns None when unmatched."""
|
||||
# stdarg sugar (va_arg / arg / va_start / va_end): these are declared as pass bodies in
|
||||
# stdarg.vp and handled here at translation time by emitting LLVM va_arg / intrinsic calls.
|
||||
@@ -362,16 +361,16 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return None
|
||||
return None
|
||||
|
||||
def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
"""t.XXX / typedef type casts; returns None when unmatched."""
|
||||
# Detect t.XXX type casts (uint64(ptr), t.CPtr(val), int(val), ...): when func is t.XXX and
|
||||
# Detect t.XXX type casts (uint64(ptr), rawptr(val), int(val), ...): when func is t.XXX and
|
||||
# XXX is a known type, treat it as a cast; once confirmed, never fall through to cross-module calls.
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
tc_at: ast.Attribute* = ast.Attribute*(cl.func)
|
||||
if tc_at.value is not None and tc_at.value.kind() == ast.ASTKind.Name:
|
||||
tc_mod_nm: ast.Name* = ast.Name*(tc_at.value)
|
||||
if tc_mod_nm.id is not None and string.strcmp(tc_mod_nm.id, "t") == 0:
|
||||
# t.CType(value, TypeName, t.CPtr) casts value to TypeName*; TypeName is a type
|
||||
# t.CType(value, TypeName, rawptr) casts value to TypeName*; TypeName is a type
|
||||
# name (not a value), so it must be handled explicitly or it falls through to a FATAL.
|
||||
if string.strcmp(func_name, "CType") == 0 and can >= 2:
|
||||
cty_node: ast.AST* = cargs.get(1)
|
||||
@@ -388,7 +387,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
cty_arg3: ast.AST* = cargs.get(2)
|
||||
cty_is_cptr: int = 0
|
||||
if cty_arg3 is not None:
|
||||
# Form 1: t.CPtr (Attribute)
|
||||
# Form 1: rawptr (Attribute)
|
||||
if cty_arg3.kind() == ast.ASTKind.Attribute:
|
||||
cty_at3: ast.Attribute* = ast.Attribute*(cty_arg3)
|
||||
if cty_at3.attr is not None and string.strcmp(cty_at3.attr, "CPtr") == 0:
|
||||
@@ -413,7 +412,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
if cty_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cty_val, ctype_target, cty_arg0, trans)
|
||||
# t.CType confirmed: even if type resolution fails, do not fall through to a cross-module FATAL
|
||||
return None
|
||||
# CConst is a const marker: CConst(val, t.CPtr) -> Ptr(i8) (const void*). Without
|
||||
# CConst is a const marker: CConst(val, rawptr) -> Ptr(i8) (const void*). Without
|
||||
# this it emits an undefined @CConst; single-arg CConst(x) returns the value unchanged.
|
||||
if string.strcmp(func_name, "CConst") == 0:
|
||||
if can >= 2:
|
||||
@@ -425,13 +424,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
target_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name)
|
||||
if target_ty is not None:
|
||||
tc_effective_can: sizet = can
|
||||
# Two-arg form: int(val, t.CPtr) -> Ptr(target_ty). void* is illegal in LLVM,
|
||||
# Two-arg form: int(val, rawptr) -> Ptr(target_ty). void* is illegal in LLVM,
|
||||
# so CVoid* must be represented as i8*.
|
||||
if can == 2:
|
||||
tc_arg2_node: ast.AST* = cargs.get(1)
|
||||
tc_arg2_is_cptr: int = 0
|
||||
if tc_arg2_node is not None:
|
||||
# Form 1: t.CPtr (Attribute form)
|
||||
# Form 1: rawptr (Attribute form)
|
||||
if tc_arg2_node.kind() == ast.ASTKind.Attribute:
|
||||
tc_arg2_at: ast.Attribute* = ast.Attribute*(tc_arg2_node)
|
||||
if tc_arg2_at.attr is not None and string.strcmp(tc_arg2_at.attr, "CPtr") == 0:
|
||||
@@ -513,13 +512,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
imp_gp = trans._imported_modules
|
||||
fi_gp = trans._from_imports
|
||||
bare_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, gp_ast, imp_gp, fi_gp, trans, 0)
|
||||
# Generic two-arg form T(val, t.CPtr) -> Ptr(T), aligned with int(val, t.CPtr) -> Ptr(i32);
|
||||
# Generic two-arg form T(val, rawptr) -> Ptr(T), aligned with int(val, rawptr) -> Ptr(i32);
|
||||
# without it the two-arg call misses the can==1 branch and misreports an undefined bare call.
|
||||
if bare_ty is not None and can == 2:
|
||||
bare_arg2_node: ast.AST* = cargs.get(1)
|
||||
bare_arg2_is_cptr: int = 0
|
||||
if bare_arg2_node is not None:
|
||||
# Form 1: t.CPtr (Attribute form)
|
||||
# Form 1: rawptr (Attribute form)
|
||||
if bare_arg2_node.kind() == ast.ASTKind.Attribute:
|
||||
bare_arg2_at: ast.Attribute* = ast.Attribute*(bare_arg2_node)
|
||||
if bare_arg2_at.attr is not None and string.strcmp(bare_arg2_at.attr, "CPtr") == 0:
|
||||
@@ -552,7 +551,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
|
||||
return None
|
||||
|
||||
def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
def _tc_h5_sizeof_len_isinst(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*:
|
||||
"""__sizeof__/len/isinstance built-ins; returns None when unmatched."""
|
||||
# Detect ClassName.__sizeof__() and return the struct size constant (i64); it is a builtin,
|
||||
# not a cross-module call. Supports e.g. Argument.__sizeof__() and module-qualified classes.
|
||||
@@ -616,7 +615,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
# dot after a sha1 prefix. Union types (X*) and rawptr[X] both have pointer size 8.
|
||||
if string.strstr(sz_cls_name, "|") is not None: return mlirlite.const_int64(pool, 8)
|
||||
if string.strncmp(sz_cls_name, "rawptr[", 7) == 0: return mlirlite.const_int64(pool, 8)
|
||||
# A trailing '*' means pointer size 8 (rawptr[T] == t.CPtr[T] == T*). Must check
|
||||
# A trailing '*' means pointer size 8 (rawptr[T] == rawptr[T] == T*). Must check
|
||||
# trailing, not strrchr, since containers like list[{sha}.AST*] also contain '*'.
|
||||
_sz_len_s: sizet = string.strlen(sz_cls_name)
|
||||
while _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == ' ': _sz_len_s -= 1
|
||||
@@ -828,7 +827,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return mlirlite.build_call(builder, len_mangled_x, len_self_x, 1, len_ret_x, 0)
|
||||
# fail-fast: the class has no __len__ (compile-time error, matching TPC
|
||||
# HandlesExprBuiltin._FailFastLenUnsupported wording).
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use t.CPtr[Element] and maintain the element count explicitly", "TypeError")
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError")
|
||||
# Non-struct: str (Ptr(Int8)) uses strlen; other types fail fast
|
||||
len_arg_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(len_val)
|
||||
len_is_str: int = 0
|
||||
@@ -861,7 +860,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
return mlirlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0)
|
||||
# fail-fast: not a string/array/object, so length is unavailable (matching TPC
|
||||
# HandlesExprBuiltin._FailFastLenUnsupported wording).
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use t.CPtr[Element] and maintain the element count explicitly", "TypeError")
|
||||
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError")
|
||||
|
||||
# Detect isinstance(): runtime vtable subclass-set comparison. obj's head vtable pointer must
|
||||
# be in {Cls and all subclass vtables}; NoVTable targets fall back to a compile-time check.
|
||||
@@ -873,7 +872,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
|
||||
return None
|
||||
|
||||
def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: t.CPtr = None) -> mlirlite.Value*:
|
||||
def _tc_h6_method_dispatch(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*:
|
||||
"""Static class/method/receiver/self.field/list built-ins; sets hit_box, else returns None."""
|
||||
# REnum.kind() compiles to a __tag read (offset 0, type from the field declaration): bitcast obj
|
||||
# to __tag* + load. Four criteria detect REnum, incl. pointee __tag and X.field annotations.
|
||||
@@ -917,7 +916,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
rk_ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, rk_nm.id)
|
||||
rk_annot_raw: str = self.Gen.VarGen.var_annot_class_name(rk_ve)
|
||||
if rk_annot_raw is not None:
|
||||
# Truncate the union/generic suffix (" | t.CPtr" / "[...]")
|
||||
# Truncate the union/generic suffix (" | rawptr" / "[...]")
|
||||
rk_ae: sizet = 0
|
||||
while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[': rk_ae += 1
|
||||
rk_ab: str = pool.alloc(rk_ae + 1)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -863,7 +862,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
return None
|
||||
|
||||
|
||||
def add_func_to_table(self, funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: mlirlite.Function*, max_count: int, defaults: t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
|
||||
def add_func_to_table(self, funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: mlirlite.Function*, max_count: int, defaults: rawptr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
|
||||
"""Add a function to a func table; returns 0 on success"""
|
||||
if name is None or func is None or funcs is None: return 1
|
||||
if func_count >= max_count: return 1
|
||||
@@ -1021,7 +1020,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
return 1
|
||||
|
||||
|
||||
def _register_global_defaults(self, name: str, defaults: t.CPtr, default_count: int, param_count: int, def_sha1: str = None) -> int:
|
||||
def _register_global_defaults(self, name: str, defaults: rawptr, default_count: int, param_count: int, def_sha1: str = None) -> int:
|
||||
"""Register a function's default arguments in the global table; returns 0 on success"""
|
||||
if name is None or defaults is None: return 1
|
||||
if self._init_global_defaults_table() == 0: return 1
|
||||
@@ -1066,7 +1065,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
string.memset(kinds, 0, default_count * 4)
|
||||
string.memset(ints, 0, default_count * 8)
|
||||
string.memset(strs, 0, default_count * 8)
|
||||
dl: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(uint64(defaults))
|
||||
dl: list[ast.AST*]* = list[ast.AST*]*(uint64(defaults))
|
||||
di: int
|
||||
for di in range(int(default_count)):
|
||||
dnode: ast.AST* = dl.get(di)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
import lib.Stub.StubGen.VpiReader as VpiReader
|
||||
@@ -148,7 +145,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
cur_param = mlirlite.param_get_next(cur_param)
|
||||
return 0
|
||||
|
||||
def translate_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
def translate_call(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate a Call node and return the result Value."""
|
||||
cl: ast.Call* = ast.Call*(node)
|
||||
# Static symbols must not be used cross-module: fail fast on mod.fn(...) hitting another
|
||||
@@ -276,7 +273,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
if h0_hit_val != 0: return None
|
||||
# super()/ctraits detection: a void method yields None but is handled, so hit_box must
|
||||
# separate "handled" from "missed"; otherwise super() falls through and reports undefined.
|
||||
h1_hit: t.CPtr = stdlib.malloc(4)
|
||||
h1_hit: rawptr = stdlib.malloc(4)
|
||||
if h1_hit is not None: h1_hit[0] = 0
|
||||
_tc_h1_super_ctraits_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h1_hit)
|
||||
h1_hit_val: int = 0
|
||||
@@ -340,7 +337,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# c.Asm/c.LLVMIR special calls return None when void but are handled, so use hit_box to
|
||||
# separate "missed"; otherwise they fall through to the external-function path and mis-report.
|
||||
h2_hit: t.CPtr = stdlib.malloc(4)
|
||||
h2_hit: rawptr = stdlib.malloc(4)
|
||||
if h2_hit is not None: h2_hit[0] = 0
|
||||
_tc_h2_c_special_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h2_hit)
|
||||
h2_hit_val: int = 0
|
||||
@@ -363,7 +360,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# Method dispatch may succeed yet return None (e.g. void __before_init__/__init__), so hit_box
|
||||
# must separate "recognized method" from "missed"; otherwise the object name is looked up as a module.
|
||||
h6_hit: t.CPtr = stdlib.malloc(4)
|
||||
h6_hit: rawptr = stdlib.malloc(4)
|
||||
if h6_hit is not None: h6_hit[0] = 0
|
||||
_tc_h6_method_dispatch_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h6_hit)
|
||||
h6_hit_val: int = 0
|
||||
@@ -781,7 +778,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
found_func = bi_decl
|
||||
# Use accessors to bypass stub type restrictions.
|
||||
found_ret_ty: mlirlite.LLVMType* = None
|
||||
found_params: t.CPtr = None
|
||||
found_params: rawptr = None
|
||||
if found_func is not None:
|
||||
found_ret_ty = mlirlite.function_get_ret_ty(found_func)
|
||||
found_params = mlirlite.function_get_params(found_func)
|
||||
@@ -912,7 +909,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
return self.Gen.CallGenLeafKit.translate_closure_call(pool, builder, mod, fp_alloca, cargs, can, trans)
|
||||
# ---- M3: session-function table hit -> take the ctx function-pointer slot and call indirectly ----
|
||||
# Placed last in the found_func-is-None block so locals/closures shadow session functions; only foreign bare names reach the table.
|
||||
sfn_box: t.CPtr = None
|
||||
sfn_box: rawptr = None
|
||||
if trans is not None and trans.ReplCtx is not None and (cl.func is None or cl.func.kind() == ast.ASTKind.Name):
|
||||
sfn_box = stdlib.malloc(4)
|
||||
if sfn_box is not None:
|
||||
@@ -1069,7 +1066,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
# Default-argument filling: when fewer args than params, fill the gaps; the defaults array is
|
||||
# right-aligned to args (defaults[0] maps to args[offset], offset = param_count - default_count).
|
||||
if can > 0 or (can == 0 and cargs is not None):
|
||||
df_defaults: t.CPtr = None
|
||||
df_defaults: rawptr = None
|
||||
df_default_count: int = 0
|
||||
df_param_count: int = 0
|
||||
# Compute the callee module SHA1 as a qualifier key (module.func -> that module; bare -> current),
|
||||
@@ -1142,7 +1139,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
df_arg_val: mlirlite.Value* = None
|
||||
if gd_entry is not None: df_arg_val = self.Gen.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, df_di, trans, builder)
|
||||
if df_arg_val is None and df_defaults is not None:
|
||||
df_defaults_list: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(uint64(df_defaults))
|
||||
df_defaults_list: list[ast.AST*]* = list[ast.AST*]*(df_defaults)
|
||||
df_default_node: ast.AST* = df_defaults_list.get(df_di)
|
||||
if df_default_node is not None: df_arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, df_default_node, None, 0, trans)
|
||||
if df_arg_val is not None:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -17,7 +16,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
# _func_has_eh_params - whether callee signature has try-except EH out params (main excluded)
|
||||
# ============================================================
|
||||
|
||||
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, arg_node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, arg_node: ast.AST*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Return the alloca pointer of a va_list variable without loading it."""
|
||||
if arg_node is None: return None
|
||||
# Name node: look up the alloca pointer from the symbol table (no load)
|
||||
@@ -37,7 +36,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
# Type node present but unresolvable: fail-fast, never fall back to i32 (would read the vararg slot at the wrong width)
|
||||
self.Gen.TypeGenErr.fatal_error(type_node, "va_arg type resolution failed", "TypeError")
|
||||
return mlirlite.Int32(pool)
|
||||
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit a va_arg instruction reading the next variadic argument from the va_list."""
|
||||
if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -67,7 +66,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
|
||||
# Emit the va_arg instruction
|
||||
return mlirlite.build_va_arg(builder, ap_ptr, read_ty)
|
||||
def _translate_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit va_arg reading from the enclosing variadic's own va_list or a forwarded va_list."""
|
||||
# arg() has two forms:
|
||||
# (1) Own-variadic form: inside `def f(a, *args)`, trans._va_list_ptr is the i8* address of
|
||||
@@ -104,7 +103,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
|
||||
# Emit va_arg, using va_ptr as the va_list address (own buffer or forwarded pointer)
|
||||
return mlirlite.build_va_arg(builder, va_ptr, read_ty)
|
||||
def _translate_va_start_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_va_start_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit llvm.va_start to initialize the va_list (the second C-ABI argument is unused)."""
|
||||
if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -122,7 +121,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase):
|
||||
void_ty_vs: mlirlite.LLVMType* = mlirlite.Void(pool)
|
||||
mlirlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
|
||||
return mlirlite.const_int32(pool, 0)
|
||||
def _translate_va_end_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
def _translate_va_end_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*:
|
||||
"""Emit llvm.va_end to clean up the va_list (a no-op on most platforms)."""
|
||||
if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -579,7 +578,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
if self.GenericClassNames is None or class_name is None: return None
|
||||
# Assign the list to a local to trigger type inference (avoids field __len__ failure)
|
||||
names_local: list[str]* = self.GenericClassNames
|
||||
nodes_local: list[ast.ClassDef*] | t.CPtr = self.GenericClassNodes
|
||||
nodes_local: list[ast.ClassDef*]* = self.GenericClassNodes
|
||||
cn: sizet = len(names_local)
|
||||
i: sizet
|
||||
for i in range(int(cn)):
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
from . import ClassGenBase
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import mlirlite
|
||||
import memhub
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.Gen.Translator as HT
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.Projectrans.Utils as Utils
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
@@ -28,7 +27,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
|
||||
"""Expression-handling mixin (pure methods, no state fields)."""
|
||||
|
||||
# Translate a value expression (RHS dispatch) - module-level version.
|
||||
def translate_value(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr = None, func_count: int = 0, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*:
|
||||
def translate_value(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: rawptr = None, func_count: int = 0, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*:
|
||||
"""Translate a value expression to an LLVM Value (depth-guard wrapper; see _translate_value_impl).
|
||||
target_ty = assignment/parameter type context; use_ctx = real call site for CDefine width checks."""
|
||||
if trans is not None:
|
||||
@@ -38,7 +37,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
|
||||
if trans is not None: trans.TranslateDepth -= 1
|
||||
return rv
|
||||
|
||||
def _translate_value_impl(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr = None, func_count: int = 0, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*:
|
||||
def _translate_value_impl(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: rawptr = None, func_count: int = 0, trans: HT.Translator* = None, target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*:
|
||||
"""Translate a value expression to an LLVM Value."""
|
||||
if node is None: return None
|
||||
k: int = node.kind()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -592,6 +591,24 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
elem_ptr_ty_v: mlirlite.LLVMType* = mlirlite.Ptr(pool, elem_ty_v)
|
||||
casted_v: mlirlite.Value* = mlirlite.build_bitcast(builder, elem_addr_v, elem_ptr_ty_v)
|
||||
if casted_v is not None: return mlirlite.build_load(builder, elem_ty_v, casted_v)
|
||||
# 值类型类实例(`d: dict = dict(bd)`):槽里就是对象本身,`d[k]` 必须按
|
||||
# 类的 `__getitem__` 调用编译,self 传槽地址(= &对象)。此前这里直接
|
||||
# return None,调用方(AnnAssign)又对 None 静默不写,整条语句凭空消失
|
||||
# ——现场:p1/p2/p3 全未赋值,随后解引用栈垃圾断言崩溃。
|
||||
cls_nm_val: str = self.Gen.StructGen.get_class_name_by_type(pool, pointee)
|
||||
if not (cls_nm_val is None):
|
||||
gi_lookup_val: str = pool.alloc(128)
|
||||
if gi_lookup_val is not None:
|
||||
viperlib.snprintf(gi_lookup_val, 128, "%s.__getitem__", cls_nm_val)
|
||||
if self.Gen.CallGenBase.find_func_in_module(mod, gi_lookup_val) is not None:
|
||||
arg_vals_val: sizet* = pool.alloc(8)
|
||||
if not (arg_vals_val is None):
|
||||
arg_vals_val[0] = sizet(idx_val)
|
||||
ret_val_sub: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_val, "__getitem__", alloca, arg_vals_val, 1, trans, sub)
|
||||
if not (ret_val_sub is None): return ret_val_sub
|
||||
# 非 list、无 __getitem__ 的结构体值不可下标:按对象大小 GEP 是非法 IR,
|
||||
# 明确 fail-fast,绝不静默返回 None(调用方会把整条语句丢掉)。
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"cannot subscript the value-type object '{nm.id}' of type '{lsn_v}' (the class defines no __getitem__); use a pointer variable ('T*') or define __getitem__", "TypeError")
|
||||
return None
|
||||
case mlirlite.LLVMType.Ptr(inner_ty):
|
||||
# Check whether inner_ty is list[T]; list subscripts go through __getitem__ (inline), not pointer traversal
|
||||
@@ -876,6 +893,19 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
if ptr_val is None: return None
|
||||
gep_r: mlirlite.Value* = mlirlite.build_gep(builder, inner_ty, ptr_val, idx_val)
|
||||
return gep_r
|
||||
case mlirlite.LLVMType.Struct(_fs_gsp, _fc_gsp, _lsn_gsp):
|
||||
# 值类型类实例(`d: dict = dict(bd)`):槽里是对象本身,`d[k] = v`
|
||||
# 只能走类的 `__setitem__`。定义了 __setitem__ 时返回 None,交由
|
||||
# 赋值路径的 __setitem__ 重载分支(self 用槽地址);否则按对象数组
|
||||
# GEP 会生成非法 IR,明确 fail-fast 而不是静默。
|
||||
cls_nm_val_gsp: str = self.Gen.StructGen.get_class_name_by_type(pool, pointee)
|
||||
if not (cls_nm_val_gsp is None):
|
||||
si_lookup_val: str = pool.alloc(128)
|
||||
if si_lookup_val is not None:
|
||||
viperlib.snprintf(si_lookup_val, 128, "%s.__setitem__", cls_nm_val_gsp)
|
||||
if self.Gen.CallGenBase.find_func_in_module(mod, si_lookup_val) is not None: return None
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"cannot index the value-type object '{nm.id}' of type '{_lsn_gsp}' (the class defines no __setitem__); use a pointer variable ('T*') or define __setitem__", "TypeError")
|
||||
return None
|
||||
case _:
|
||||
# Plain scalar pointee (e.g. i64/i32/i8): GEP directly to the idx-th element; union type
|
||||
# (IsPtrElement=1, pointee i8 but 8-byte pointer elements) uses an i8* stride instead.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -208,6 +207,17 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
mod_nm: ast.Name* = ast.Name*(at.value)
|
||||
if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0 and at.attr is not None:
|
||||
if self._type_name_unsigned(at.attr) != 0: return 1
|
||||
return 0
|
||||
# Plain function call: widen by the callee's **declared return type**. Without this,
|
||||
# `uint64(f())` with `def f() -> uint32` emitted `sext i32 -> i64` (verified in the
|
||||
# generated IR), so a u32 with bit 31 set grew 0xFFFFFFFF in the high half — a real
|
||||
# value 0x88691F61 became 0xFFFFFFFF88691F61 (stackmap pointers were mangled this way).
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
|
||||
func_nm_u: ast.Name* = ast.Name*(cl.func)
|
||||
if func_nm_u.id is not None:
|
||||
fe_fn_u: GenTypes.FuncEntry* = self.Gen.CallGenLeafKit.find_func_entry_global(func_nm_u.id)
|
||||
if fe_fn_u is not None and fe_fn_u.Spec is not None:
|
||||
if TSpec.SpecIsUnsigned(fe_fn_u.Spec.Ret) != 0: return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name* = ast.Name*(node)
|
||||
@@ -774,7 +784,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
case mlirlite.LLVMType.Func(_, _, _):
|
||||
# 函数指针变量(嵌套函数名在符号表里是 Ptr(Func)):变量本身就是
|
||||
# 那个函数地址,`&f` 应给出它的值 Ptr(Func)(一级),而不是变量
|
||||
# 地址 Ptr(Ptr(Func))(二级)——否则传给 callback: t.CPtr 会因
|
||||
# 地址 Ptr(Ptr(Func))(二级)——否则传给 callback: rawptr 会因
|
||||
# 级数不符报 CastError(source level 2 -> target level 1)。
|
||||
fp_ty_ao: mlirlite.LLVMType* = mlirlite.Ptr(pool, ao2)
|
||||
return mlirlite.build_load(builder, fp_ty_ao, v_ao)
|
||||
@@ -835,7 +845,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
return tmp_slot_ao
|
||||
# translate_boolop - BoolOp(op, values): short-circuit evaluation returning i1.
|
||||
# and: a false short-circuits to merge (returns a's i1); or: a true short-circuits; the last value is evaluated then branches to merge; merge phis all i1 edges.
|
||||
def translate_boolop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr = None, func_count: int = 0, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
def translate_boolop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: rawptr = None, func_count: int = 0, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate boolean and/or with short-circuit evaluation, returning i1."""
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bo is None: return None
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Func.FuncGenMixin as FuncGenMixin
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -173,7 +172,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
# Extract default-argument info. Note: assign the attribute to an explicitly typed list[...]* local before
|
||||
# calling __len__(), otherwise the list type is not recognized and the GEP base becomes i32 0 (llc error).
|
||||
fd_args_node: ast.Arguments* = fd.args
|
||||
fd_defaults: t.CPtr = None
|
||||
fd_defaults: rawptr = None
|
||||
fd_default_count: int = 0
|
||||
fd_param_count: int = 0
|
||||
if fd_args_node is not None:
|
||||
@@ -510,7 +509,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
if func_section is not None: mlirlite.function_set_attr_group(func, func_section)
|
||||
|
||||
# Extract default-argument info
|
||||
tfd_defaults: t.CPtr = None
|
||||
tfd_defaults: rawptr = None
|
||||
tfd_default_count: int = 0
|
||||
tfd_param_count: int = 0
|
||||
if args_node is not None:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -83,7 +82,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
# types go into the param_tys buffer (CVoid skipped, aligning with alloca indices).
|
||||
imported_modules: str = trans._imported_modules
|
||||
from_imports: str = trans._from_imports
|
||||
param_tys: t.CPtr = pool.alloc(8 * 64)
|
||||
param_tys: rawptr = pool.alloc(8 * 64)
|
||||
if param_tys is not None: string.memset(param_tys, 0, 8 * 64)
|
||||
param_count: int = 0
|
||||
if fd.args is not None:
|
||||
@@ -192,8 +191,8 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
old_insw: int = trans._in_switch_case
|
||||
# Separate nonlocal buffer: sharing [0] would overwrite the parent's set (ClosureTest2
|
||||
# Test 7: level2's b clobbers level1's a). Restored after translation.
|
||||
saved_nl_names: t.CPtr = trans._nonlocal_names
|
||||
saved_nl_types: t.CPtr = trans._nonlocal_types
|
||||
saved_nl_names: rawptr = trans._nonlocal_names
|
||||
saved_nl_types: rawptr = trans._nonlocal_types
|
||||
|
||||
# 7. Switch to the nested function scope and clear scope names
|
||||
trans._cur_func = func
|
||||
@@ -778,7 +777,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# ============================================================
|
||||
# _collect_chain_nonlocals - recursively gather nonlocal names in the nested chain (deduped)
|
||||
def _collect_chain_nonlocals(self, trans: HT.Translator*, node: ast.AST*, names: t.CPtr, count: int) -> int:
|
||||
def _collect_chain_nonlocals(self, trans: HT.Translator*, node: ast.AST*, names: rawptr, count: int) -> int:
|
||||
"""Recursively collect all nonlocal declaration names in a nested FunctionDef chain (deduped)"""
|
||||
if node is None or names is None: return count
|
||||
fd: ast.FunctionDef* = ast.FunctionDef*(node)
|
||||
@@ -898,7 +897,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
param_names: str = pool.alloc(32 * 64) # 64 params x 32-byte names
|
||||
if param_names is None: return None
|
||||
string.memset(param_names, 0, 32 * 64)
|
||||
param_tys: t.CPtr = pool.alloc(8 * 64) # LLVMType pointer slots
|
||||
param_tys: rawptr = pool.alloc(8 * 64) # LLVMType pointer slots
|
||||
if param_tys is None: return None
|
||||
string.memset(param_tys, 0, 8 * 64)
|
||||
param_count: int = 0
|
||||
@@ -935,10 +934,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
cap_names: str = pool.alloc(64 * 64) # 64 captures x 64-byte names
|
||||
if cap_names is None: return None
|
||||
string.memset(cap_names, 0, 64 * 64)
|
||||
cap_allocas: t.CPtr = pool.alloc(8 * 64) # Parent alloca pointer slots
|
||||
cap_allocas: rawptr = pool.alloc(8 * 64) # Parent alloca pointer slots
|
||||
if cap_allocas is None: return None
|
||||
string.memset(cap_allocas, 0, 8 * 64)
|
||||
cap_tys: t.CPtr = pool.alloc(8 * 64) # Capture variable type slots
|
||||
cap_tys: rawptr = pool.alloc(8 * 64) # Capture variable type slots
|
||||
if cap_tys is None: return None
|
||||
string.memset(cap_tys, 0, 8 * 64)
|
||||
cap_count: int = self._lambda_scan_body(trans, lam.body, param_names, param_count, cap_names, cap_allocas, cap_tys, 0)
|
||||
@@ -1148,7 +1147,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# ============================================================
|
||||
# _lambda_scan_body - recursively collect outer Name refs into cap_names/cap_allocas/cap_tys
|
||||
def _lambda_scan_body(self, trans: HT.Translator*, node: ast.AST*, param_names: str, param_count: int, cap_names: str, cap_allocas: t.CPtr, cap_tys: t.CPtr, cap_count: int) -> int:
|
||||
def _lambda_scan_body(self, trans: HT.Translator*, node: ast.AST*, param_names: str, param_count: int, cap_names: str, cap_allocas: rawptr, cap_tys: rawptr, cap_count: int) -> int:
|
||||
"""Recursively scan lambda body Name references and collect captured variables"""
|
||||
if node is None or trans is None: return cap_count
|
||||
k: int = node.kind()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import string
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import stdlib
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
@@ -213,7 +212,7 @@ novirtual class ImportsGenMixin:
|
||||
# lookup; else fall back to scanning. orig None means a first occurrence with no alias.
|
||||
if from_imports == self.CurFromImportsPtr and self.CurFromImportsOrigs is not None:
|
||||
if self.CurFromImportsOrigs.__contains__(local_name) != 0:
|
||||
v_o: t.CPtr = self.CurFromImportsOrigs.__getitem__(local_name)
|
||||
v_o: rawptr = self.CurFromImportsOrigs.__getitem__(local_name)
|
||||
if v_o is not None: return rawptr(v_o)
|
||||
# Index miss or None value never returns None directly (the real string may still
|
||||
# contain the name); fall through to scanning (correctness first).
|
||||
@@ -275,10 +274,10 @@ novirtual class ImportsGenMixin:
|
||||
name_is_star: int = 0
|
||||
if string.strlen(name) == 1 and name[0] == '*': name_is_star = 1
|
||||
if name_is_star == 0:
|
||||
v_f: t.CPtr = self.CurFromImportsMods.__getitem__(name)
|
||||
v_f: rawptr = self.CurFromImportsMods.__getitem__(name)
|
||||
if v_f is not None: return rawptr(v_f)
|
||||
if allow_star_fallback != 0:
|
||||
sv_f: t.CPtr = self.CurFromImportsMods.__getitem__("*")
|
||||
sv_f: rawptr = self.CurFromImportsMods.__getitem__("*")
|
||||
if sv_f is not None: return rawptr(sv_f)
|
||||
# Neither exact nor star hit in the index never returns None (an incomplete index
|
||||
# misses imported names, causing _op_head NameError); fall through to scanning.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -511,6 +510,15 @@ novirtual class StmtGenCifMixin:
|
||||
ret_val_ty: mlirlite.LLVMType* = None
|
||||
cur_func_rv: mlirlite.Function* = trans._cur_func
|
||||
if cur_func_rv is not None: ret_val_ty = mlirlite.function_get_ret_ty(cur_func_rv)
|
||||
# `return <闭包变量>` 且返回注解是 t.Callable:闭包对象是 {fn_ptr, env_ptr},
|
||||
# 不是裸函数指针。调用方把结果存进 t.Callable 变量后 `f()` 会按裸函数指针直调,
|
||||
# 跳到堆地址崩溃(ClosureCallTest 现场)。这里明确 fail-fast,要求用 rawptr/t.CPtr。
|
||||
if rt.value.kind() == ast.ASTKind.Name and trans is not None and trans.CurFuncRetAnnot is not None:
|
||||
clo_nm_rv: ast.Name* = ast.Name*(rt.value)
|
||||
if clo_nm_rv.id is not None and self.Gen.CallGenLeafKit.is_closure_name(clo_nm_rv.id) != 0:
|
||||
clo_ret_rv: mlirlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, trans.CurFuncRetAnnot, trans._imported_modules, trans._from_imports, trans)
|
||||
if clo_ret_rv is not None:
|
||||
self.Gen.TypeGenErr.fatal_error(rt, f"the return annotation is t.Callable (a bare function pointer) but the returned value is the closure variable '{clo_nm_rv.id}'. A closure is a (fn_ptr, env_ptr) object; storing it where a t.Callable is expected makes the caller jump into heap data. Annotate the return as rawptr / t.CPtr instead", "TypeError")
|
||||
# [C1] return-annotation context: record this return's direct value node so a bare
|
||||
# generic ctor (`return Stack()` in `-> Stack[int]`) specializes via CurFuncRetAnnot.
|
||||
trans.CurRetNode = rt.value
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Call.CallGenFd as CallGenFd
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -204,7 +203,7 @@ novirtual class Translator:
|
||||
_lambda_count: int
|
||||
# Set of nonlocal variables across the function chain (collected by pre-scan).
|
||||
# The outermost function allocates their heaps and stores addresses in @nlheap.{sha1}.{name}.
|
||||
_nl_chain_names: t.CPtr
|
||||
_nl_chain_names: rawptr
|
||||
_nl_chain_count: int
|
||||
# Chain-nonlocal heap built flag (built once per function): reset to 0 on entering a function,
|
||||
# set to 1 by _prepare_chain_nonlocals. Shared by nested definitions to avoid double malloc.
|
||||
@@ -694,8 +693,8 @@ novirtual class Translator:
|
||||
"""Detect list/dict container usage and inject container-class visibility."""
|
||||
if tree is None or tree.children is None: return
|
||||
# Use stack buffers to pass detection results (4-byte int pointers across helper calls)
|
||||
need_list_box: t.CPtr = stdlib.malloc(4)
|
||||
need_dict_box: t.CPtr = stdlib.malloc(4)
|
||||
need_list_box: rawptr = stdlib.malloc(4)
|
||||
need_dict_box: rawptr = stdlib.malloc(4)
|
||||
if need_list_box is None or need_dict_box is None:
|
||||
if need_list_box is not None: stdlib.free(need_list_box)
|
||||
if need_dict_box is not None: stdlib.free(need_dict_box)
|
||||
@@ -809,7 +808,7 @@ novirtual class Translator:
|
||||
stdlib.free(nm_buf)
|
||||
return 0
|
||||
|
||||
def _scan_container_usage(self, node: ast.AST*, need_list_box: t.CPtr, need_dict_box: t.CPtr):
|
||||
def _scan_container_usage(self, node: ast.AST*, need_list_box: rawptr, need_dict_box: rawptr):
|
||||
"""Recursively scan AST statement structure for list/dict container usage."""
|
||||
if node is None: return
|
||||
k: int = node.kind()
|
||||
@@ -843,7 +842,7 @@ novirtual class Translator:
|
||||
n_s: sizet = len(ch_s)
|
||||
for ci_s in range(int(n_s)): self._scan_container_usage(ch_s.get(ci_s), need_list_box, need_dict_box)
|
||||
|
||||
def _check_container_type_node(self, node: ast.AST*, need_list_box: t.CPtr, need_dict_box: t.CPtr):
|
||||
def _check_container_type_node(self, node: ast.AST*, need_list_box: rawptr, need_dict_box: rawptr):
|
||||
"""Check whether a type-position node is list/dict, recursing through Name/Subscript/BinOp."""
|
||||
if node is None: return
|
||||
k: int = node.kind()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import lib.core.Gen.Type.TypeGenMixin as TypeGenMixin
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import hashtable
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -8,13 +6,7 @@ import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import sys
|
||||
import win32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Diag as Diag
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.Gen.Translator as HT
|
||||
|
||||
import lib.core.Gen.Type.TypeGenBase as TypeGenBase
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import sys
|
||||
import stdlib
|
||||
import viperlib
|
||||
import win32.fileio as fileio
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.core.Gen.Type.TypeGenBase as TypeGenBase
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import lib.core.Gen.GenTypes as GenTypes
|
||||
import lib.core.Gen.GenApi as GenApi
|
||||
import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Type.TypeGenCType as TypeGenCType
|
||||
import lib.core.Gen.Type.TypeGenMixin as TypeGenMixin
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -11,21 +8,18 @@ import memhub
|
||||
import hashtable
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Gen.Translator as HT
|
||||
import lib.Stub.StubMerger as StubMerger
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
import lib.Stub.StubGen.VpiReader as VpiReader
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
import lib.core.Gen.Type.TypeGenBase as TypeGenBase
|
||||
import lib.core.Gen.Type.TypeGenCDef as TypeGenCDef
|
||||
import win32.fileio as fileio
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeGenResolve - split out of TypeGenMixin (stage D): type mapping / annotation resolution.
|
||||
novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
@@ -1198,10 +1192,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
key_buf[mod_len] = '|'
|
||||
string.strncpy(key_buf + mod_len + 1, attr, attr_len)
|
||||
key_buf[key_len] = '\0'
|
||||
v: t.CPtr = self.LibTypedefTypeMap.__getitem__(key_buf)
|
||||
v: rawptr = self.LibTypedefTypeMap.__getitem__(key_buf)
|
||||
stdlib.free(key_buf)
|
||||
if v is None: return None
|
||||
return t.CPtr(v)
|
||||
return rawptr(v)
|
||||
def _lookup_library_typedef(self, pool: memhub.MemBuddy*, mod: str, attr: str) -> str:
|
||||
"""Look up "attr: t.CTypedef = TYPE" in a library module source, returning TYPE or None."""
|
||||
if mod is None or attr is None: return None
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import mlirlite
|
||||
import memhub
|
||||
@@ -115,8 +114,7 @@ def SpecSignFromTypeName(name: str) -> int:
|
||||
|
||||
# TypeSpec - type descriptor. PtrLevel alone is ambiguous for Ptr(i8), so element
|
||||
# semantics use the (ElemBits, IsElemPtr, DerefBase) triple replacing IsPtrElement.
|
||||
@t.NoVTable
|
||||
class TypeSpec:
|
||||
novirtual class TypeSpec:
|
||||
"""Unified type descriptor"""
|
||||
Kind: int # one of TS_*
|
||||
Bits: int # bit width; 0 for non-int/float
|
||||
@@ -140,8 +138,7 @@ class TypeSpec:
|
||||
|
||||
|
||||
# TypeSpecArena - interning table (object-owned, not global): Keys/Specs/Count/Cap.
|
||||
@t.NoVTable
|
||||
class TypeSpecArena:
|
||||
novirtual class TypeSpecArena:
|
||||
"""TypeSpec interning table; dedups by canonical text key (one instance per type)"""
|
||||
Keys: bytes
|
||||
Specs: sizet*
|
||||
|
||||
@@ -3,7 +3,6 @@ import lib.core.Gen.Generator as Generator
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
from MatchGenMixin import SCOPE_MATCH
|
||||
import lib.core.Gen.Translator as HT
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import mlirlite
|
||||
@@ -934,7 +933,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# ---- repl_try_session_func_call - indirect call to a session function (M3 core) ----
|
||||
# On a hit, load the address from the ctx slot, prepend ctx, coerce args to the table signature, and call_indirect (hit=1).
|
||||
def repl_try_session_func_call(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, func_name: str, cargs: list[ast.AST*]*, can: int, kw_count: int, node: ast.AST*, hit: t.CPtr) -> mlirlite.Value*:
|
||||
def repl_try_session_func_call(self, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, func_name: str, cargs: list[ast.AST*]*, can: int, kw_count: int, node: ast.AST*, hit: rawptr) -> mlirlite.Value*:
|
||||
"""Session function call: return the call result on hit (void returns None but hit is set)"""
|
||||
if trans is None or trans.ReplCtx is None or pool is None or builder is None: return None
|
||||
if func_name is None or hit is None: return None
|
||||
@@ -965,7 +964,7 @@ novirtual class VarGenMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to read the address of session function '{func_name}'", "InternalCompilerError")
|
||||
return None
|
||||
# (2) Resolve param types before building the signature (token -> LLVM type; unsupported -> error)
|
||||
ptypes: t.CPtr = pool.alloc(8 * GenTypes.REPL_FUNC_PARAM_MAX)
|
||||
ptypes: rawptr = pool.alloc(8 * GenTypes.REPL_FUNC_PARAM_MAX)
|
||||
if ptypes is None: return None
|
||||
string.memset(ptypes, 0, 8 * GenTypes.REPL_FUNC_PARAM_MAX)
|
||||
ai_chk: int
|
||||
@@ -1347,7 +1346,7 @@ novirtual class VarGenMixin:
|
||||
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
|
||||
pv: mlirlite.Value* = val
|
||||
if val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0 and self.Gen.AssignGen._stg_ty_equal(pool, val.Ty, i8_ptr_ty) == 0:
|
||||
# Skip when already an i8 pointer (str/bytes/t.CPtr) - LLVM rejects same-type bitcast
|
||||
# Skip when already an i8 pointer (str/bytes/rawptr) - LLVM rejects same-type bitcast
|
||||
pv = mlirlite.build_bitcast(builder, val, i8_ptr_ty)
|
||||
if pv is None: return 1
|
||||
# Pointer -> i64 (ptrtoint): the host reads it as an integer then inttoptrs it back to an address
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import win32.win32file as win32file
|
||||
import win32.win32base as win32base
|
||||
@@ -11,7 +9,6 @@ import hashlib
|
||||
import viperlib
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
# IncludesScanner - recursive scan of the includes directory (Win32 FindFirstFileA/
|
||||
@@ -311,8 +308,8 @@ def _PathExistsA(path: str) -> int:
|
||||
|
||||
|
||||
# _TryResolveModuleFile - try one candidate path and write outputs (1=hit, 0=miss);
|
||||
# out_abs_path/out_rel_path/out_inc_dir are t.CPtr output slots.
|
||||
def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, suffix: str, out_abs_path: t.CPtr, out_rel_path: t.CPtr, out_inc_dir: t.CPtr) -> int:
|
||||
# out_abs_path/out_rel_path/out_inc_dir are rawptr output slots.
|
||||
def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, suffix: str, out_abs_path: rawptr, out_rel_path: rawptr, out_inc_dir: rawptr) -> int:
|
||||
if inc_dir is None or rel_seg is None or suffix is None: return 0
|
||||
inc_len: sizet = string.strlen(inc_dir)
|
||||
suf_len: sizet = string.strlen(suffix)
|
||||
@@ -346,7 +343,7 @@ def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, suffix:
|
||||
return 0
|
||||
string.strcpy(inc_buf, inc_dir)
|
||||
# Write output slots (stdlib deep copies; caller frees). Slots must be cast to
|
||||
# (sizet*): t.CPtr* folds to t.CPtr and [0] becomes a 1-byte access.
|
||||
# (sizet*): rawptr* folds to rawptr and [0] becomes a 1-byte access.
|
||||
if out_abs_path is not None:
|
||||
abs_slot: sizet* = (sizet*)(out_abs_path)
|
||||
abs_slot[0] = sizet(cand)
|
||||
@@ -363,7 +360,7 @@ def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, suffix:
|
||||
|
||||
# ResolveModuleToPath - module name -> file path, resolved on demand (no full scan).
|
||||
# Tries each includes dir, preferring file modules over packages. Returns 0 found, 1 not.
|
||||
def ResolveModuleToPath(includes_dirs: str, mod_name: str, out_abs_path: t.CPtr, out_rel_path: t.CPtr, out_inc_dir: t.CPtr) -> int:
|
||||
def ResolveModuleToPath(includes_dirs: str, mod_name: str, out_abs_path: rawptr, out_rel_path: rawptr, out_inc_dir: rawptr) -> int:
|
||||
if includes_dirs is None or mod_name is None: return 1
|
||||
mn_len: sizet = string.strlen(mod_name)
|
||||
if mn_len == 0: return 1
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import stdlib
|
||||
import memhub
|
||||
import sys
|
||||
import win32.win32console as win32cmd
|
||||
@@ -33,7 +31,7 @@ def repl_abort() -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def set_repl_jmpbuf(buf: t.CPtr) -> int:
|
||||
def set_repl_jmpbuf(buf: rawptr) -> int:
|
||||
"""Register the REPL jmp_buf; idempotent at each fragment entry."""
|
||||
global _repl_jmpbuf
|
||||
_repl_jmpbuf = buf
|
||||
@@ -196,7 +194,7 @@ log: Logger*
|
||||
def init_logger():
|
||||
"""Initialize the global logger instance."""
|
||||
global logger, log
|
||||
raw: t.CPtr = _mbuddy.alloc(Logger.__sizeof__())
|
||||
raw: rawptr = _mbuddy.alloc(Logger.__sizeof__())
|
||||
# if raw is None: return None (memory management still unclear)
|
||||
logger = raw
|
||||
logger.__before_init__()
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
"""Compiler-side implementation of the `viperbuild` built-in macro library (--src Pass 0)."""
|
||||
import t, c
|
||||
from stdint import *
|
||||
from win32.win32base import *
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import ast
|
||||
import win32.win32file as win32file
|
||||
import lib.Projectrans.Utils as Utils
|
||||
@@ -796,9 +793,9 @@ def _ResolveModuleToFile(module_name: str) -> str:
|
||||
"""Resolve a module name to a local project file path; None if not found."""
|
||||
if module_name is None or _search_dirs is None: return None
|
||||
if string.strlen(module_name) == 0: return None
|
||||
out_abs: t.CPtr = stdlib.malloc(8)
|
||||
out_rel: t.CPtr = stdlib.malloc(8)
|
||||
out_inc: t.CPtr = stdlib.malloc(8)
|
||||
out_abs: rawptr = stdlib.malloc(8)
|
||||
out_rel: rawptr = stdlib.malloc(8)
|
||||
out_inc: rawptr = stdlib.malloc(8)
|
||||
if out_abs is None or out_rel is None or out_inc is None:
|
||||
if out_abs is not None: stdlib.free(out_abs)
|
||||
if out_rel is not None: stdlib.free(out_rel)
|
||||
|
||||
@@ -21,7 +21,6 @@ import memhub
|
||||
import argparse
|
||||
import win32.win32console as win32cmd
|
||||
import win32.win32base as win32base
|
||||
import win32.fileio as fileio
|
||||
import sys
|
||||
import ast
|
||||
import os
|
||||
@@ -31,10 +30,6 @@ import os.path
|
||||
import shutil
|
||||
import mlirlite
|
||||
import subprocess
|
||||
import viperlib
|
||||
import t, c
|
||||
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
|
||||
import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
|
||||
import lib.Phase.Phase1.Phase1Main as Phase1Main
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user