fix(gen): define 位宽/整数提升/移位/AugAssign 规则收敛,修 va_list 与 traceback 卡死
- define 位宽:cdefine_decl_bits 单一裁决(注解 → 右侧强转 → 值最小可存宽度),定义方与 VpiReader 两处跨模块注册共用;lookup_cdefine_bits 取最后一条非零记录;存储即截断;使用侧改按声明位宽;通用求值器加编译期除零/移位越界 fail-fast - 消除对无符号强转加宽方向的依赖:define_min_width 改 (value>>32)==0,截断改左移+算术右移,修 TPC/TPV 判定不一致导致 0x80000000 误判 64 位 - 整数提升:算术/移位、比较、一元 +/-/~ 提升到 i32;位运算保持同宽不提升 - AugAssign:y 有效宽度须 <= x、禁 y 显式有符号而 x 无符号;移位计数静态范围检查 - 函数入口复位 va_list 状态与 willFree 失效槽表(FuncGenDef/FuncGenMixin/VarGenMixin 等) - BuildPipeline:traceback 逐行扫描改 span 判定,去掉对全文 strlen 的 O(n^2)
This commit is contained in:
1 parent
be4db7b5d1
commit
4e46a25ab1
18 files changed
+1247
-843
No files matched your search
@@ -291,7 +291,7 @@ def ensure_dir(path: str) -> int:
|
||||
# Temporarily truncate at each separator and create every directory level.
|
||||
# CreateDirectoryA returns 0 when the dir exists (failure); ignore it.
|
||||
plen: int = int(path_len)
|
||||
for i in range(plen):
|
||||
for i in range(int(plen)):
|
||||
ch: int = buf[i]
|
||||
if ch == 47 or ch == 92: # '/' = 47, '\\' = 92
|
||||
saved: char = char(ch)
|
||||
@@ -639,7 +639,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
|
||||
if tasks is None or task_count <= 0: return 0
|
||||
# --phase2command mode: do not spawn threads; write all opt (ASan) + llc commands to the bat
|
||||
if _phase2_cmd_path is not None:
|
||||
for pi2 in range(task_count):
|
||||
for pi2 in range(int(task_count)):
|
||||
tsk_p: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(pi2) * LlcTask.__sizeof__())
|
||||
if tsk_p is None: continue
|
||||
if tsk_p.MlirOptCmd is not None: _phase2_write_cmd(tsk_p.MlirOptCmd)
|
||||
@@ -658,24 +658,24 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
|
||||
slot_size: sizet = LlcTask.__sizeof__()
|
||||
ret: int = 0
|
||||
# Batched execution: batch_start steps by max_threads (each batch spawn+join+close).
|
||||
for batch_start in range(0, task_count, max_threads):
|
||||
for batch_start in range(0, int(task_count), int(max_threads)):
|
||||
batch_n: int = max_threads
|
||||
if batch_start + batch_n > task_count: batch_n = task_count - batch_start
|
||||
# spawn this batch
|
||||
for j in range(batch_n):
|
||||
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.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))
|
||||
for j in range(batch_n):
|
||||
for j in range(int(batch_n)):
|
||||
h_j: t.CPtr = t.CPtr(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)
|
||||
# check this batch's results
|
||||
for j in range(batch_n):
|
||||
for j in range(int(batch_n)):
|
||||
tsk2: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size)
|
||||
if tsk2 is not None and tsk2.Result != 0:
|
||||
# Failure: use FailStage to pinpoint the step and print that step's command.
|
||||
@@ -942,7 +942,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, linker_cmd: str, link
|
||||
dt2len: sizet = dj - ds2
|
||||
if dt2len == dtlen:
|
||||
deq: int = 1
|
||||
for dk in range(dtlen):
|
||||
for dk in range(int(dtlen)):
|
||||
if dedup[ds2 + dk] != obj_paths[dstart + dk]:
|
||||
deq = 0
|
||||
break
|
||||
@@ -1147,6 +1147,20 @@ def _tb_contains(s: str, sub: str) -> int:
|
||||
return 1 if string.strstr(s, sub) is not None else 0
|
||||
|
||||
|
||||
def _tb_contains_span(s: str, ls: sizet, le: sizet, sub: str) -> int:
|
||||
"""Span-aware substring test: only s[ls, le) is searched.
|
||||
A tail-wide strstr would both scan the whole remaining objdump text (hundreds of MB) and
|
||||
match a substring belonging to a LATER line (e.g. ".text" found past a ".rdata" header)."""
|
||||
if s is None or sub is None: return 0
|
||||
sl: sizet = string.strlen(sub)
|
||||
if sl == 0 or le < ls or le - ls < sl: return 0
|
||||
i: sizet = ls
|
||||
while i + sl <= le:
|
||||
if string.strncmp(s + i, sub, sl) == 0: return 1
|
||||
i += 1
|
||||
return 0
|
||||
|
||||
|
||||
def _tb_startswith(s: str, pfx: str) -> int:
|
||||
if s is None or pfx is None: return 0
|
||||
pl: sizet = string.strlen(pfx)
|
||||
@@ -1154,6 +1168,18 @@ def _tb_startswith(s: str, pfx: str) -> int:
|
||||
return 1 if string.strncmp(s, pfx, pl) == 0 else 0
|
||||
|
||||
|
||||
def _tb_startswith_span(s: str, ls: sizet, le: sizet, pfx: str) -> int:
|
||||
"""Span-aware prefix test: only s[ls, le) is considered, never the tail.
|
||||
_tb_startswith on `s + ls` would run strlen over the WHOLE remaining text; llvm-objdump -d
|
||||
output is hundreds of MB for a large exe, so a per-line strlen makes the whole scan O(n^2)
|
||||
and the compilation appears to hang (it spins inside strlen for hours)."""
|
||||
if s is None or pfx is None: return 0
|
||||
if le < ls: return 0
|
||||
pl: sizet = string.strlen(pfx)
|
||||
if le - ls < pl: return 0
|
||||
return 1 if string.strncmp(s + ls, pfx, pl) == 0 else 0
|
||||
|
||||
|
||||
def _tb_ltrim(s: str) -> str:
|
||||
if s is None: return None
|
||||
i: sizet = 0
|
||||
@@ -1165,7 +1191,7 @@ def _tb_len_trimmed(s: str) -> sizet:
|
||||
if s is None: return 0
|
||||
n: sizet = string.strlen(s)
|
||||
while n > 0:
|
||||
c: int = _tb_cc(s, n - 1)
|
||||
c: int = int(_tb_cc(s, n - 1))
|
||||
if c == 32 or c == 9 or c == 13: n -= 1
|
||||
else: break
|
||||
return n
|
||||
@@ -1206,7 +1232,7 @@ def _tb_join(mb: memhub.MemBuddy*, base: str, name: str) -> str:
|
||||
nl: sizet = string.strlen(name)
|
||||
buf: str = mb.alloc(bl + nl + 2)
|
||||
if buf is None: return name
|
||||
last: int = _tb_cc(base, bl - 1)
|
||||
last: int = int(_tb_cc(base, bl - 1))
|
||||
if last == 47 or last == 92: viperlib.snprintf(buf, bl + nl + 2, "%s%s", base, name)
|
||||
else: viperlib.snprintf(buf, bl + nl + 2, "%s/%s", base, name)
|
||||
return buf
|
||||
@@ -1304,13 +1330,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(count):
|
||||
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))
|
||||
return None
|
||||
|
||||
|
||||
def _tb_file_rec(files: bytes, count: int, idx: int) -> int:
|
||||
for i in range(count):
|
||||
for i in range(int(count)):
|
||||
if int(_tb_rd_u32(files, sizet(i) * TB_FILE_SIZE)) == idx: return i
|
||||
return -1
|
||||
|
||||
@@ -1403,7 +1429,7 @@ def _tb_func_name_for(fbuf: bytes, fcount: int, rva: uint64) -> str:
|
||||
def _tb_intern(p: TbPool*, s: str) -> uint64:
|
||||
"""Intern s into the pool (linear scan; keeps offset 0 as the empty sentinel)."""
|
||||
if p is None or s is None: return 0
|
||||
for k in range(p.OffCount):
|
||||
for k in range(int(p.OffCount)):
|
||||
o: uint64 = _tb_rd_u64(p.Offs, sizet(k) * 8)
|
||||
if string.strcmp(p.Pool + sizet(o), s) == 0: return o
|
||||
off: uint64 = uint64(p.PoolLen)
|
||||
@@ -1450,7 +1476,7 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*:
|
||||
min_rva: uint64 = 0xFFFFFFFF
|
||||
found_text: int = 0
|
||||
have_sec: int = 0
|
||||
for si in range(nsec):
|
||||
for si in range(int(nsec)):
|
||||
base: sizet = sec_off + sizet(si) * 40
|
||||
if uint64(base) + 40 > uint64(got): break
|
||||
va: uint64 = uint64(_tb_rd_u32(head, base + 12))
|
||||
@@ -1744,7 +1770,7 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int)
|
||||
if grp is None or cap <= 0 or caller is None or callee is None: return -1
|
||||
mask: uint64 = uint64(cap - 1)
|
||||
hv: uint64 = (_tb_strhash(caller) * 0x100000001B3 + _tb_strhash(callee)) & mask
|
||||
for i in range(cap):
|
||||
for i in range(int(cap)):
|
||||
slot: int = int((hv + uint64(i)) & mask)
|
||||
off: sizet = sizet(slot) * TB_GRP_SIZE
|
||||
if uint64(_tb_rd_u32(grp, off + TB_GRP_OFF_USED)) == 0:
|
||||
@@ -1823,7 +1849,7 @@ def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str:
|
||||
if buf is None:
|
||||
f.close()
|
||||
return None
|
||||
# 容量全程用 sizet(与 sz 同宽):旧写法 ULONG(sz) + ULONG(2) 会在 sz >= 4GiB 时静默回绕
|
||||
# 容量全程用 sizet(与 sz 同宽):旧写法 ULONG(sz) + ULONG(2) 会在 sz >= 4GiB 时静默回绕
|
||||
got: LONG = f.read_all(buf, sizet(sz) + 2)
|
||||
f.close()
|
||||
if got < 0: return None
|
||||
@@ -1844,7 +1870,7 @@ def _tb_parse_f_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCal
|
||||
f3: sizet = p
|
||||
while f3 < b and _tb_cc(s, f3) != 9: f3 += 1
|
||||
if f3 >= b: return 0
|
||||
defline: int = _tb_parse_dec(s + p)
|
||||
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
|
||||
@@ -1870,7 +1896,7 @@ def _tb_parse_c_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCal
|
||||
e4: sizet = p
|
||||
while e4 < b and _tb_cc(s, e4) != 9: e4 += 1
|
||||
if e4 >= b: return 0
|
||||
line: int = _tb_parse_dec(s + p)
|
||||
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
|
||||
@@ -1901,7 +1927,7 @@ def _tb_parse_vpcall_file(mb: memhub.MemBuddy*, path: str, cp: TbCallParse*) ->
|
||||
|
||||
def _tb_load_vpcalls(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int:
|
||||
if _tb_vpcall_buf is None or _tb_vpcall_n <= 0: return 0
|
||||
for k in range(_tb_vpcall_n):
|
||||
for k in range(int(_tb_vpcall_n)):
|
||||
slot: str* = (str*)(uint64(_tb_vpcall_buf) + sizet(k) * 8)
|
||||
path: str = slot[0]
|
||||
if path is not None:
|
||||
@@ -1918,7 +1944,7 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int:
|
||||
VLogger.error("--traceback: failed to allocate call-site group table, aborting compilation", "TRACEBACK")
|
||||
return 1
|
||||
string.memset(cp.Grp, 0, sizet(cp.GrpCap) * TB_GRP_SIZE)
|
||||
for i in range(cp.CrN):
|
||||
for i in range(int(cp.CrN)):
|
||||
off: sizet = sizet(i) * TB_CR_SIZE
|
||||
caller: str = rawptr(_tb_rd_u64(cp.Cr, off + TB_CR_OFF_CALLER))
|
||||
callee: str = rawptr(_tb_rd_u64(cp.Cr, off + TB_CR_OFF_CALLEE))
|
||||
@@ -1959,7 +1985,7 @@ 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
|
||||
for i in range(cp.FrN):
|
||||
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:
|
||||
@@ -2016,10 +2042,10 @@ def _tb_scan_objdump(mb: memhub.MemBuddy*, dump: str, img_lo: uint64, d: TbDump*
|
||||
if pos < dlen: pos += 1
|
||||
if le > ls and _tb_cc(dump, le - 1) == 13: le -= 1
|
||||
if le <= ls: continue
|
||||
if _tb_startswith(dump + ls, "Disassembly of section") != 0:
|
||||
if _tb_startswith_span(dump, ls, le, "Disassembly of section") != 0:
|
||||
# section change: a pending callq at the previous section's end has no valid return address
|
||||
prev_is_call = 0
|
||||
if _tb_contains(dump + ls, ".text") != 0: in_text = 1
|
||||
if _tb_contains_span(dump, ls, le, ".text") != 0: in_text = 1
|
||||
else: in_text = 0
|
||||
continue
|
||||
if in_text == 0: continue
|
||||
@@ -2188,7 +2214,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
bl: uint64 = uint64(_tb_rd_u32(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_LINE))
|
||||
bp: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FILE)
|
||||
bf: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FUNC)
|
||||
j: int = i + 1
|
||||
j: int = int(i + 1)
|
||||
while j < kept and _tb_rd_u64(d.RowBuf, sizet(j) * TB_ROW_SIZE) == rv:
|
||||
lj: uint64 = uint64(_tb_rd_u32(d.RowBuf, sizet(j) * TB_ROW_SIZE + TB_ROW_OFF_LINE))
|
||||
if lj > bl:
|
||||
@@ -2209,7 +2235,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
return 1
|
||||
|
||||
# ---- 3) subprograms: normalise + sort by low_rva ----
|
||||
fcount: int = d.FuncCount
|
||||
fcount: int = int(d.FuncCount)
|
||||
fkept: int = 0
|
||||
dropped_funcs: int = 0
|
||||
fi: int = 0
|
||||
@@ -2283,7 +2309,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
if ro is None:
|
||||
VLogger.error("--traceback: failed to allocate record offset buffer, aborting compilation", "TRACEBACK")
|
||||
return 1
|
||||
for i in range(uniq):
|
||||
for i in range(int(uniq)):
|
||||
pth2: str = rawptr(_tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FILE))
|
||||
foff: uint64 = _tb_intern(p, pth2)
|
||||
noff: uint64 = 0
|
||||
@@ -2318,7 +2344,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
return 1
|
||||
# file_off must be >= 1: offset 0 is the empty-string sentinel and the runtime
|
||||
# rejects a whole map whose record file_off is 0.
|
||||
for ci in range(uniq):
|
||||
for ci in range(int(uniq)):
|
||||
fo: uint64 = uint64(_tb_rd_u32(ro, sizet(ci) * 8))
|
||||
if fo == 0:
|
||||
VLogger.error("--traceback self-check failed: a record has file_off==0 (empty path; runtime would reject that sidecar file), aborting compilation", "TRACEBACK")
|
||||
@@ -2338,7 +2364,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
_tb_wr_u32(out, 8, uint64(uniq))
|
||||
_tb_wr_u32(out, 12, uint64(p.OffCount))
|
||||
_tb_wr_u32(out, 16, uint64(p.PoolLen))
|
||||
for ri2 in range(uniq):
|
||||
for ri2 in range(int(uniq)):
|
||||
roff2: sizet = 20 + sizet(ri2) * 20
|
||||
rv3: uint64 = _tb_rd_u64(d.RowBuf, sizet(ri2) * TB_ROW_SIZE)
|
||||
ln3: uint64 = uint64(_tb_rd_u32(d.RowBuf, sizet(ri2) * TB_ROW_SIZE + TB_ROW_OFF_LINE))
|
||||
|
||||
Reference in new issue
Block a user