TermiNexus
a7af34bd7e
修正了部分代码的表达方式,最后可用版本,mlirlite 已基本完善
2026-09-23 17:41:49 +08:00
TermiNexus
951b89be36
修正了部分代码的表达方式,最后可用版本,正在为 mlirlite 做准备
2026-09-23 16:09:32 +08:00
TermiNexus
a5ceb3d4eb
增加 JIT REPL
2026-09-21 16:17:19 +08:00
TermiNexus
9910e05760
修复了一些错误,更改了一点语法
2026-09-18 20:00:40 +08:00
TermiNexus
9e2ccbfab7
将部分 | t.CPtr 修正为 rawptr[T]
2026-09-18 17:56:24 +08:00
TermiNexus
eb01a45024
修复了一些问题
2026-09-17 14:51:18 +08:00
TermiNexus
cb0836de8a
清理了 t.CVoid
2026-09-16 16:06:48 +08:00
TermiNexus
9a191daa8d
错拼 rowptr 改为 rawptr
2026-09-16 11:42:28 +08:00
TermiNexus
7cba4cbc95
chore: 清理超长历史注释,并一并提交并行会话的代码改动
...
注释清理(65 文件 / 约 -2578 行 / 约 516 处):删除/压缩叙述式历史注释——多行根因叙事、工作代号段(D25/D30/N11/B5/S4/阶段E 等)、改前改后与先例叙述、逐条推导块,压成一行讲清作用信息;契约类注释(用途、参数与返回、关键约束与不变量、IR 结构说明)与被注释掉的代码一律保留
存疑 标记 6 处一字未动:StubMergerStore.vp、VpiReader.vp、VLogger.vp、AssignGenMixin.vp、CallGenLib.vp、CallGenLeafKit.vp
本次一并带入并行会话的代码改动(同批文件,按文件粒度无法拆分):fileio.File -> rowptr[fileio.File] 等
已知副作用/残留:① CallGenDispatch.vp 有 2 行非注释行的行尾被 LF->CRLF 规范化(纯字节变化,无文本改动);② core/Gen 区约 24 处压缩因并行会话整文件覆写被写回原样,尚未生效(StmtGenCifMixin/ClassGenVTable/FuncGenDef/ClassGenEnum/StructGenMixin/TypeSpec 等)
清单与复跑判据见 Debugger/comment_cleanup_summary.md(该目录不受版本控制)
2026-09-16 11:27:05 +08:00
TermiNexus
b28f20cce7
chore: 清理调试打印与失效 import
...
CallGenCall.vp: 前次清理 DBG 打印后 import stdio 已无使用者,删除(该文件全文无 stdio. 调用,亦无经本模块的外部访问)
Test/App/nested_match_test.vp: 删除 _init_mbuddy 与 test_single_match 中的 8 处 [DBG] 进度打印;该测试的判定只看 --- Test N --- / OK / FAIL 行,test_main.vp 亦只取返回码,无断言引用这些文本
未改动任何逻辑(保留 FAIL: malloc for arena failed 等错误分支的真实输出)
2026-09-16 10:32:40 +08:00
TermiNexus
429de97083
fix(call): 泛型特化类跨模块 declare 按模板 vpi 注解对齐形参口径
...
特化名({sha}.list[str].__init__)在 vpi 参数注解缓存中无精确键——键段取自 class 行文本,只存模板 list[T]——定义侧形参注解取不到,调用点 declare 停在调用点实参口径(elem_size 字面量 i32 vs 定义侧 t.CSizeT=i64;池实参 MemBuddy*/i8* vs 定义侧 MemManager*),并经 .stub.ll 传播到未调用该函数的消费方模块
新增 VpiReader._resolve_vpi_param_annot_seg_template:按 {sha1}.{base}[T].{method} 定位模板条目、用特化实参替换段内类型形参 token 后再解析,未命中返回 None 不兜底;_coerce_args_to_def_params 在精确键未命中且类名含 [ 时改走模板退查并置 tpl_src,使 _coerce_arg_value_to_ty 对同为具体结构体指针但基类型不同补 bitcast;_call_method_on_ptr 的跨模块分支补建 declare 前的 coerce(先例 a83d183 的三处调用点)
同时把 {sha}.{cls}.{method} 的切分由首个 . 改为末个 .(CallGenLib/CallGenBase 两处):method 不含 .,首个 . 会把含模块限定名的类型实参截断(list[3571eabe5a83d798.AST|t.CPtr] 截成无 ] 的类名 ⇒ 模板退查必 miss)
另修 VpiReader 一处 double-free:_subst_template_arg 早退分支返回入参本身,替换前释放原缓冲需先判同一性(三条路径各释放一次)
效果: 危险级签名不一致 TransPyV 8->4->0、Test/AstTest 6->2->0,ZlibTest/WebTest/FakeDuckTest/ListTest/GenericTest2/VectorGenericTest 保持 0;4 个目标符号 define/declare 共 148 处全部统一为 MemManager*+i64(0 处旧口径);自举达全树逐字节不动点(exe sha256 相同、temp/** 635 文件零差异);AstTest 及既有测试全 PASS 且无 ASan 报告
2026-09-16 09:31:57 +08:00
TermiNexus
a83d183abb
fix(gen/call): 跨模块调用 SSA 整型实参按定义侧形参扩宽
...
declare 由调用点实参链建立,而 _coerce_arg_value_to_ty 对非常量(SSA)整型此前原样返回,导致 declare/call 停在调用点窄宽度(string.strncpy 第三参 i32),与定义侧(vpi 注解 n: t.CSizeT => i64)不一致,并经 .stub.ll 传播到未调用该函数的消费方模块
现按源符号性 zext/sext 扩宽(真源 ExprGenBase._zext_or_sext_val,先例 CallGenCtor._translate_t_type_cast),实参 AST/trans 下传;self_off 模块级 0、方法 1
效果: WebTest 危险级签名不一致 1 => 0
2026-09-15 23:58:40 +08:00
TermiNexus
31b8dccffd
fix(stub): declare 侧识别 t.CPtr[...] 段,与定义侧指针层级口径对齐
...
t.CUInt8T | t.CPtr[t.CPtr] 在定义侧(TypeGenResolve._is_cptr_subscript)按指针层级合并得 i8**,但声明侧段判据只认整段等于 t.CPtr/CPtr,下标段落入普通段解析后取首段 => i8,造成跨模块 define/declare 签名不一致(实参 1 字节 vs 写入 8 字节)
新增 t.CPtr[/c.CPtr[ 段的识别与递归解析(与同文件 rowptr[...] 分支同构),数外层 Ptr 层数 N 后按 Ptr^N 合并;裸 t.CPtr 段路径未动,未放宽 fail-fast
注: TPC 侧 LLVMTypeMapper._resolve_bitor 与 SymbolUtils.IsCPtrNode 同源缺陷未改,两套编译器需同时修以免产物分叉
2026-09-15 23:58:39 +08:00
TermiNexus
de86a1ed70
fix(gen/for): 负数字面量 stop 的 range 循环退回有符号谓词,修复 _find_provider 死循环
...
stop 边界为负数字面量(如 range(top - 1, -1, -1))时,3.6 的边界推导把无符号 start(UINT64 字段)判为无符号循环,负步长分支随即由 sgt 覆盖为 ugt;而比较在 stop 类型(i32)上进行,-1 在无符号域是 UINT32_MAX,条件恒假 => 循环体成为死代码。_withcontent._find_provider 因此恒返回 NULL,with 上下文的 __mbuddy__ 注入永不生效(FakeDuckTest Test 9 FAIL,随后 _str.upper 解引用 NULL vtable 触发 ASan READ)
新增 3.7: stop 为负数字面量时撤销无符号谓词(判定与既有 step_neg_const 同口径),退回 slt/sgt;正步长非负 stop 的既有 ult 优化与 range(stop) 单参形态不受影响
2026-09-15 22:45:28 +08:00
TermiNexus
296f6a739e
fix(gen/renum): REnum 补齐 Assign 形式无载荷变体的变体表注册
...
根因: _translate_renum_def / _register_renum_variants 只认嵌套 ClassDef 变体,Empty = 1 / None_ = 0 这类无载荷 Assign 变体既不计入 variant_count 也不写变体表 => match 查不到 tag(-1) => 本会话硬校验 fail-fast,此前则静默丢 case(Test\EdgeCaseTest 旧产物 ac0d686cb2cc783b.text.ll:117-119 仅 1 个 case,臂体 match.case.11.1 结构性不可达)
修复: 按 TPC 口径(HandlesClassDef._EmitREnumLlvm / SymbolExtractor)两遍处理——先取 Assign 显式值上界,ClassDef 变体从 max(显式值)+1 起编号(避免与显式值撞号),Assign 变体 tag = 显式整数值;表槽号与 tag 值解耦。纯 ClassDef REnum(含 LLVMType)生成结果不变。硬校验保留不动
2026-09-15 22:45:28 +08:00
TermiNexus
617d4ea911
fix(gen/assign): 模块级与 nonlocal 分支补写赋值注解上下文通道
...
模块级 AnnAssign 的 mod_glob 分支与 global 语句分支、以及 nonlocal 分支此前均未写入 trans.CurAssignAnnot/CurAssignNode,导致模块级/闭包内 s: Stack[int] = Stack() 在泛型裸名构造处 fail-fast、x: int = c.Deref(p) 退化为 i8 单字节读取
按主分支既有先例(AssignGenMixin set 在 RHS 翻译前 / clear 在返回前)在三处分支补齐同款 set/clear,并覆盖全部分支的提前 return 与末尾出口,避免通道残留污染后续 c.Deref 读取宽度与泛型构造类型实参推断
影响面: 全仓 模块级/global/nonlocal 的 X: T = c.Deref(...) 与 X: Generic[...] = Ctor(...) 均 0 处,属纯增量
2026-09-15 21:52:42 +08:00
TermiNexus
5a59432733
fix(gen): 泛型裸名构造补齐注解上下文与关键字实参两条推断来源
...
- 赋值目标/返回注解上下文作为最后一级类型实参来源(s: Stack[int] = Stack()、-> Stack[int] 里 return Stack()),注解解析复用 _extract_type_args_from_slice,以 CurAssignNode/CurRetNode identity 限定直接值避免嵌套误用
- 仅关键字实参构造按 __init__ 形参名定位槽位(Box(v=42)、Pair(b=string, a=1) 乱序),泛型构造码生成不再静默丢弃 cl.keywords(此前会生成少一个实参的错误调用);形参名查无/槽位空洞 fail-fast
- 抽取共用 __init__ 形参遍历(_get_ctor_init_params),位置对齐语义保持不变
2026-09-15 21:52:41 +08:00
TermiNexus
6394ea30e2
fix(call): 泛型类裸名构造按 __init__ 签名对齐类型实参并禁止静默默认 int
...
- 删除按序号消费「过滤纯 int 的 hint 列表」的压缩逻辑(整型实参被剔除后 hint 下标与形参序号错位,Pair(1,字符串) 被误判为 Pair<str,str>),改为取 __init__ 中注解为该类型形参的形参位次所对应的位置实参推断(Vector[T].__init__(self,pool,capacity,_hint:T) => T 对齐第 3 个实参)
- _infer_generic_ctor_type_arg 对 Name/Attribute 实参改取真实类型(变量注解类名/字段注解类名),取不到即 fail-fast,不再回退 int
2026-09-15 21:33:54 +08:00
TermiNexus
b27633c86e
fix(Gen/Type): long/unsigned long 按目标平台取宽,Windows 对齐 TPC LLP64(ULONG/LONG => i32)
...
- map_t_type 对 CLong/CUnsignedLong 原为硬编码 Int64(64 位平台假设),导致 Windows 目标下 ULONG/LONG 出成 i64:83 个 Win32/posix 声明的 long 形参宽度错误,且 CRITICAL_SECTION 等结构体布局为 48B(正确 40B,真实 Win64 ABI)
- 新增 _long_llvm_ty:target triple 含 windows/win32/mingw/msvc => Int32,其余(LP64/裸机 ELF)保持 Int64;规则对齐 TPC lib/includes/t.py configure_platform;triple 嗅探写法对齐 StmtGenCifMixin.vp:95-109
- 定义侧与 stub/declare 侧共用同一 map_t_type,单点改动两侧同变;未改 includes/stdint.vp(ULONG=t.CUnsignedLong 的意图正确,错在宽度)
2026-09-15 20:56:52 +08:00
TermiNexus
813f0157e3
fix(Gen/Expr): 类名不再被当模块级全局变量制造引用,消除 ASan 构建 undefined symbol
...
ExprGenAttr._resolve_module_attribute_global 在未命中已注入全局时会新建 @<sha>.ClassName = external global i8* 并 load;该 load 无使用者,非 ASan 构建被 llc 删除,ASan 插桩后其全局地址参与 shadow 检查无法删除 => ld.lld: undefined symbol 481fd55266ff1187.LLVMType (.refptr)。若属性名是已注册类/结构体/REnum(StructGen.find_struct 命中)则直接返回 None,交给类/REnum 路径。
2026-09-15 20:47:15 +08:00
TermiNexus
592400a1ea
fix(asan): 并行 llc 任务在 ASan 模式下改用插桩后的 .asan.ll 作输入
...
Phase B 的 init_llc_task 先前用未插桩的 ir_path 拼 LlcCmd,opt 产出的 .asan.ll 只写进 OptCmd,worker 先跑 opt 再跑 llc 却读回原 .ll,导致 App 侧 76/76 个 obj 无 __asan 符号(ASan 内存排查半盲)。现将 llc 输入统一为 compile_input,与串行路径 compile_ll_to_obj 及 TransPyC 参考实现同口径;非 ASan 分支命令逐字不变。
2026-09-15 20:47:14 +08:00
TermiNexus
8312e653e8
fix(CodeGen): 裸结构体形参按 C ABI 按值、修正 |t.CPtr 指针层级,对齐 TPC 并消除签名发散
...
- FuncGenDef/VpiReader._AggregateParamTy: C ABI 外部声明(t.CExtern/t.State)的裸结构体形参按值 %Struct(可取完整定义时),真 opaque 降级 i64;TPV 内部函数/方法维持 Ptr(struct)。三处(定义侧/函数注入侧/方法注入侧)同口径
- TypeGenResolve/VpiReader: BinOp(A|t.CPtr) 的指针别名守卫改为 pointee 为已注册 struct 才吸收,否则追加一层 => VOIDPTR|t.CPtr 由 i8* 修正为 i8**(对齐 TPC)
- 效果: SetConsoleScreenBufferSize 等 6 个符号由 i64/%COORD* 双形态收敛为按值,同符号多形态数 193->186
2026-09-15 20:47:14 +08:00
TermiNexus
31df298341
fix(gen): 修 REnum match case 静默丢弃与 CDefine 负 64 位常量截断,补 void 注解放行、移植类型定义前移
...
- MatchGenMixin: 2a 路径查变体 tag 改用裸类名(注解书写形态带模块前缀,与变体表裸名注册口径不一致致 tag=-1、case 被静默丢弃、match 全走 default),并在 build_switch 前硬校验 应提交 case 数==sw_count,不再静默丢
- ExprGenCdef: _const_int_for_cdefine 补 value < -2147483648 下限判据,修正 (0xA5A5A5A5<<32)|0xA5A5A5A5 等负 64 位模式被物化为 i32(写入 inttoptr 零扩展 vs 比较 sext 不一致,致 MemBuddy canary 假阳性 rc=6)
- FuncGenDef/ClassGenVTable: 掉尾检查新增注解级 void 判据(t.CVoid/裸名 CVoid/None),不再因 REnum match 退化误判 void 函数缺 return
- StubMergerBuild: 移植 TPC 的 类型定义前移 遍,满足 llc 对 by-value 具名类型需先定义的要求(invalid type for function argument)
- main.vp/Phase1Main.vp/project.vpj: 新增 --detection-deep 深诊断开关与 canary 哨兵、ASan 静态库声明
2026-09-15 19:11:54 +08:00
TermiNexus
60100fa6af
fix(type): 联合类型 A|t.CPtr 判据由白名单改为解析成功即保留,stub 侧同步
...
定义侧 TypeGenResolve.resolve_annotation_type 的 BinOp(A | t.CPtr) 分支:裸名
pointee 的保留判据由“硬编码名字白名单 + 必须是已注册 struct”改为“以解析是否
成功为准”——命中统一口径 resolve_typedef_or_map(CTypedef 动态表 → builtins
→ stdint/w32.win32base 库源 → map_t_type)且结果非指针即保留该已解析类型。
于是 sizet | t.CPtr ⇒ i64*(原静默退化为 i8*)。
修复前的故障:TPV2 Phase1 的 includes/ast/tokens.vp _kw_index_put 按 i8* 处理
哈希槽,slot[0] 只做 1 字节读写,指针被截断成低字节 0xd0,随后被当 KwEntry*
解引用 → ASan 读地址 0xd0 崩溃(TPC 侧同 sha 为 alloca i64*/load i64/store i64)。
stub/declare 侧 VpiReader._resolve_vpi_ret_annot_str 同步同一判据:新增
first_td 标记,对裸名(无 '.')、非白名单、非指针的解析结果复用同一个
GenApi.resolve_typedef_or_map 判定,命中即保留 pointee。声明侧与定义侧现在
同型(sizet/uint64/INT/u32 等别名两侧都得到 i64*/i32*),同型即收敛,
不再需要把 declare 侧坍缩为 i8* 去迁就定义侧。
既有路径行为不变:泛型参数名、内建标量白名单(int/char/str/bytes/bool/float/
double)、解析失败与裸枚举名的 i8* 兜底;指针别名(BYTEPTR/HANDLE/VOIDPTR)
因解析结果为 Ptr(...) 不置位 first_td,仍坍缩 i8*,与定义侧 td_res_is_ptr
守卫对称。
2026-09-15 13:52:21 +08:00
TermiNexus
c1859a111c
fix(tpv): 撤销 llc 输出重定向,回归继承父控制台并保留 GetLastError 与退出码诊断
...
病因:_run_cmd_wait 置 STARTF_USESTDHANDLES 后所有 llc 均无法启动(CreateProcessA 返回 0,GetLastError=87 ERROR_INVALID_PARAMETER),整条构建被阻断。已逐项核对生成的 IR 并排除:STARTUPINFOA 布局(偏移 80/88/96、size 104 正确)、si.cb=104、GEP 字段索引 11/15/16/17 正确、CreateFileA 的 access/share/disposition/flags 正确、dwFlags=256 正确、CreateProcessA 十个参数正确;静态证据无法再推进,故撤回重定向。
移除:_run_cmd_wait 的 log_path 形参、CreateFileA 打开 .llc.log、STARTF_USESTDHANDLES 与三个 hStd 句柄赋值、父侧 CloseHandle 守卫;连带删除失效链路 _log_captured_output、CMD_OUTPUT_MAX、LlcTask.LogPath 及其 init/free 与成功路径 DeleteFileA。进程创建回到继承父控制台(dwFlags 保持 memset 的 0),llc 输出直接外显。
保留诊断(用户要求):CreateProcessA 失败后立即取 GetLastError 并以 VLogger.warning 打印(worker 线程内不能用 error,它会 sys.exit);串行 compile_ll_to_obj 与并行 run_llc_parallel 失败时均打印 模块sha1、退出码、完整命令;LlcTask.ExitCode 保留。
2026-09-14 23:02:59 +08:00
TermiNexus
05d5bfbf37
fix(tpv): 修 CreateProcessA 重定向未启动外部命令,并把捕获输出移到 error 之前
...
主因:_run_cmd_wait 置 STARTF_USESTDHANDLES 时只设了 hStdOutput/hStdError,hStdInput 仍是 memset 后的 NULL(0);Windows 要求三个句柄都有效且可继承,故 CreateProcessA 直接返回 0(表现为 exit=4294967295 即 -1,且 .llc.log 恒空、一次也没有 llc 输出)。日志文件改以 GENERIC_WRITE|GENERIC_READ 打开并令 hStdInput 同指该文件(llc 不读 stdin),三态句柄均不泄漏;无重定向时不置 USESTDHANDLES、退回继承控制台的行为不变。
另在 CreateProcessA 失败处立即取 w32.win32base.GetLastError 并以 VLogger.warning 打印错误码+命令+重定向文件路径(warning 而非 error:error 会 sys.exit,而此处运行在 llc worker 线程内)。
同时修正一处使功能完全失效的顺序问题:_log_captured_output 原先排在 VLogger.error 之后,而 error 内部 sys.exit(1),故捕获到的 llc stderr|stdout 永远不会打印(这正是只看到一行 llc 编译失败、.llc.log 留空的原因)。串行 compile_ll_to_obj 与并行 run_llc_parallel 两处均改为先打印捕获输出、再报错。
2026-09-14 22:14:45 +08:00
TermiNexus
82f16127c0
fix(tpv): llc 日志文件句柄初始化改用 NULL,避免整数常量赋给指针类型
...
_run_cmd_wait 里 log_fh 原以 w32.win32base.INVALID_HANDLE_VALUE 初始化,而该常量是 CDefine = -1(整数),赋给 HANDLE 指针类型触发"整数隐式转指针已禁止"的 fail-fast(BuildPipeline.vp 原 595 行)。
改为以 None(NULL) 初始化;仓库既有惯例是只把 INVALID_HANDLE_VALUE 用于比较(全仓 20 余处同写法),故其余比较判断不变。因 NULL 与 INVALID 都不应参与关闭,父侧 CloseHandle 增加 None 守卫,避免对 NULL 调 CloseHandle。
2026-09-14 21:19:20 +08:00
TermiNexus
785741026f
fix(tpv): llc 失败日志附带 stderr|stdout、退出码与完整命令
...
此前 llc 失败只打 模块sha1 与命令行:llc 的 stdout/stderr 因继承控制台而外显,程序拿不到文本,导致无法定位 verifier 报错。
_run_cmd_wait 新增可选 log_path:非空时用可继承安全属性把子进程 stdout|stderr 重定向到临时文件(不用管道:写文件不会因缓冲满阻塞、天然无死锁;且 worker 线程禁用池分配,故不复用 includes/subprocess.vp),CreateProcessA 成功后立即关闭文件句柄;log_path 为空时行为与原先逐字节一致。
LlcTask 末尾追加 LogPath/ExitCode(构造点均按 __sizeof__ 与整体 memset 处理,既有字段偏移不变);worker 记录退出码;run_llc_parallel 与串行 compile_ll_to_obj 在失败时打印 模块sha1、退出码、完整命令 与捕获输出(上限 8KB,带截断标记;输出为空/打开失败/无文件 三态如实打印,不伪造),成功时删除捕获文件、零额外输出。
包装层(compile_module_to_obj 摘要、run_pipeline 的 ErrorMsg、Phase2 PhaseB/PhaseB+ 聚合终止语)本身拿不到输出,保持不动,详情由深层打印。
2026-09-14 20:21:57 +08:00
TermiNexus
51daf28297
fix(expr): 三元表达式 else 分支按 then 的指针类型下传目标类型
...
VpiReader.vp:1963 的 rel_path_rt if rel_path_rt is not None else 单字符问号 触发 CastError(探针 kind=35 IfExp、val.Ty=i32、target_ty=i8*)。根因并非跨模块函数返回类型未解析:then 分支 rel_path_rt 已是 i8*(解析成功,赋值处与已有 fail-fast 均未触发,三条独立证据);真正的整数来自 else 分支——单引号单字符字面量在词法层被判定为 CONST_CHAR,而 translate_ifexp 翻译 else 时未下传目标类型上下文,遂物化为 i32(63),随后在类型对齐阶段被按 then 的指针类型 coerce,撞上整数隐式转指针的 fail-fast。
改为:仅当 then 分支是指针时,把其类型作为 else 的 target_ty 下传;单字符字面量随即走 ExprGenConst 的指针目标分支物化为 1 字符字符串(对齐 TPC 的引号推断),两分支同为 i8*,不再进入 coerce。非指针 then 不下传,既有常量物化与位宽行为逐字节不变(如 base64.vp 中 then 为 char 的两处不受影响)。
另经核查:模块级函数返回类型并无静默默认 i32 的问题——「依赖已就绪却解析不到」已是 fail-fast(CallGenMixin 跨模块函数路径与方法侧 _fail_method_ret_ty 同构),保留 i32 的仅是多遍收敛中间态的占位,故本次不动。
2026-09-14 19:26:46 +08:00
TermiNexus
7fabf886fc
fix(vpi): 返回注解索引重建的键长常量拼写修正为 VPI_KEY_LEN
...
_vpi_rebuild_ret_idx 里把键长写成了不存在的 VPI_RET_KEY_LEN(参数侧另有 VPI_PARAM_KEY_LEN=224,本文件仅定义 VPI_KEY_LEN=224 与 VPI_PARAM_KEY_LEN)。此前该未定义标识符被旧规则按类型零值兜底编成 0,使重放偏移 ri*0 恒为 0(每条键都从第 0 条键位置读取),返回注解索引重建结果错误;因探测用 live 键比较,表现为未命中回退线性扫描——结果仍正确但索引形同无效。
这解释了此前实测中 _lookup_vpi_ret_annot 加索引后仍有约 913K 次 strcmp(返回侧索引一直未生效),而参数侧索引生效并从榜单消失。改为本文件既有且返回侧一致使用的 VPI_KEY_LEN(malloc/memset/查找/写入各处均用该常量)。
2026-09-14 16:54:36 +08:00
TermiNexus
a46391bf42
fix(expr): coerce_to_type 拓宽方向判定改传 builder.Pool,修正未定义实参 pool
...
coerce_to_type 作用域内并无 pool(其参数是 builder),L425 却把 pool 作为第 1 个实参传给 _zext_or_sext_val。此前该实参翻译失败会被静默按类型零值兜底,使传给 ExprGenOps.should_zext_widen 的池为空、变量注解符号性判定失效,从而在无符号拓宽时错走 sext(即该处注释所述的无符号扩展缺陷根因)。
改为传 builder.Pool(与同函数内 llvmlite.const_int64(builder.Pool, 0) 等一致,是共同值所处的池)。该未定义实参由本会话新增的「实参翻译失败即 fail-fast」规则暴露。
2026-09-14 15:48:09 +08:00
TermiNexus
b918321f77
perf(callgen): text.ll 存在性改属性查询 + 返回类型按模块一次性缓存
...
第 1 项:_dep_text_ll_exists 原以 fileio.File(MODE.R) 只读打开探测存在性(33,244 次调用,占总 create_file_utf8 46.6%,每次约 57us 的开句柄成本)。改用 GetFileAttributesA 并显式排除目录(对齐 IncludesScanner._PathExistsA 先例),无输出缓冲、零句柄。
第 2 项:_LookupMethodRetTyFromTextLL(29,974 次、约 380,505 tick/次、self 11.41e9 即 8.9%)原每次重开加重读加逐字节重扫整份 text.ll(实测约 2.47 tick/字节,均值 154KB)。新增 PermPool 缓存表(mangled 名 到 返回类型文本):某模块 text.ll 首次成功读入时登记其全部 define 行,同模块后续查询 O(1);命中后用调用方 pool 经 _ParseLLVMRetTyStr 重建类型,与原路径等价。
关键安全点:只存返回类型文本、绝不存会随每文件 reset_to 失效的 LLVMType*;同名只记首次(保持首个匹配优先);仅成功读到文件后才回写,未找到或文件暂不存在绝不缓存(Phase A 顺序生成依赖,负缓存会出错);缓存或分配失败一律回退原扫描。原扫描逻辑一字未改,保留为未命中路径。
2026-09-14 15:26:10 +08:00
TermiNexus
ce612c8e57
perf(lookup): 恢复名字索引可信未命中即确无的短路(Ty 索引保持停用)
...
4ed7f39 因 Ty 索引不等价,把名字索引的未命中短路一并回退了,导致 find_struct(8.25M)/lookup_ctypedef(5.64M) 等又回到全表扫描。
经逐处自证不变量后仅恢复名字键索引:名字或键只在注册时写入一次(中和仅置空名,空名查询显式回退扫描);索引在所有写入路径同步维护,判据 Built==Count 失败即失效回退;探测用 live 键且同键条目沿链按注册顺序排列(无空槽夹层)⇒ 可信未命中即原线性扫描亦无所获,短路逐字节等价。
恢复点:StructGenMixin.find_struct、TypeGenCType.lookup_ctypedef、CallGenLeafKit.find_func_in_table/find_func_entry_global、TypeGenCDef.lookup_cdefine_{constant,double,string}、VpiReader._lookup_vpi_param_annots/_lookup_vpi_ret_annot(后者保留泛型特化归一化兜底)。
find_struct_by_type 的 Ty 索引判定保持停用(事故根因);首字符预筛、Function.NameLen/FUNC_SIZE、includes 均未改动。
2026-09-14 12:59:27 +08:00
TermiNexus
4ed7f3909a
fix(lookup): 索引未命中一律回退原线性扫描,停用不可信的 Ty 索引判定
...
降低「索引可信且未命中即判定确无」语义带来的风险面(该语义是本轮构建 fail-fast 的最高嫌疑):索引只用于加速命中,未命中一律回退原线性扫描,使各查找函数在所有输入上的返回值与优化前逐字节一致。
StructGenMixin.find_struct:去掉「索引可信且查询名非空则跳过 O(n) 扫描」分支,未命中恢复原精确匹配全表扫描。
StructGenMixin.find_struct_by_type:整体停用 Ty 索引判定 —— 条目 Ty 会被深拷贝改写,槽按注册时 Ty 落位,改写后与 live 键脱钩,命中不保证是原线性首命中(不等价),故恢复原线性精确扫描;get_class_name_by_type(REnum.kind 识别路径)、register_struct 去重、lookup_field 首遍随之回到优化前语义。
CallGenLeafKit.find_func_in_table/find_func_entry_global、TypeGenCType.lookup_ctypedef、TypeGenCDef.lookup_cdefine_{constant,double,string}、VpiReader._lookup_vpi_param_annots/_lookup_vpi_ret_annot:可信未命中不再直接返回,一律落入原线性扫描。
未触碰:Function.NameLen/FUNC_SIZE、各处首字符预筛、includes/string.vp。
2026-09-14 12:41:27 +08:00
TermiNexus
e7f47735ed
perf(callgen): find_func_in_module 以 function_get_name_len 替代 strlen 热点
...
第二趟后缀匹配对每个函数节点调用 strlen(cur_name)(实测 2373 万次、占全程序 strlen 73.7%)改为读取 Function.NameLen;两处替换点:CallGenBase 约 563 与 597。
并在外部函数返回类型白名单登记 function_get_name_len 返回 i64(CSizeT),避免 stub 未注入时按默认 i32 导致签名不一致。匹配语义与返回顺序不变。
2026-09-14 08:26:18 +08:00
TermiNexus
cb430bf00a
perf(gen): 结构体/CTypedef 查名加索引,热点线性查名补首字符预筛
...
StructGenMixin.find_struct:索引可信且查询名非空时,未命中即判定确无同名条目,跳过 O(n) 精确扫描(此前索引只短路命中、未命中仍全表扫描,实测 527 万次逐条 strcmp 即源于此)。
TypeGenCType:新增 CTypedef 名索引(开放寻址、槽存 index+1、Built==len 才可信、不可信或未命中回退线性扫描、clear_ctypedefs 同步复位),消除 lookup_ctypedef 约 445 万次 strcmp。
补首字符预筛:StubMergerIR._FindSha1ByModName、CallGenBase._ensure_method_declare、VarGenMixin.find_var、CallGenLeafKit.find_func_entry_in_table(_owned)(首字符不等即判不等,匹配结果与顺序不变)。
2026-09-14 04:15:36 +08:00
TermiNexus
e8db102b9e
perf(gen): 结构体按模块查找与 ctypedef 跨度查找加首字节预筛
...
StructGenMixin.find_struct_by_module 的名与 ModuleSha1 两次 strcmp、TypeGenCType.lookup_ctypedef_span 的逐项名比较,均加首字符/首字节必要条件短路(首字节不等即判不等),并省去原逐项 strlen。匹配结果与返回顺序逐字节不变。
2026-09-14 00:09:06 +08:00
TermiNexus
16472a61d9
perf(lookup): 热点线性查找表加开放寻址名索引,O(n) 降为期望 O(1)
...
VpiReader 参数/返回注解键表(查表 + 写去重共用)、CallGenLeafKit 全局函数表、TypeGenCDef CDefine 表:由线性扫描改为开放寻址索引,对应热点约 117M + 17.8M + 10.5M 次 strcmp。
索引槽只存下标+1(不存键/节点指针),键表 realloc/移动后槽下标仍有效,无悬空指针;可信判据 Built==count,每次注册同步维护,不可信或未命中一律回退原线性扫描(正确性保证)。每次注册占一槽以保持首注册优先(探测链首个键相等者即原首个命中)。CallGenLeafKit 快速路径仅限 owner_sha1 为 None 的全局表查询,保持 owner 优先语义不变。
2026-09-14 00:05:12 +08:00
TermiNexus
a9819e4123
fix(gen): 方法分派与 list 内建判定改用接收者实际特化名,根治 list[int].get 截断
...
_translate_method_call 原以注解来源 class_name 构造被调名;同一函数作用域内同名变量被声明/赋值两次时该名退化(get_class_name_by_type 的类型后缀匹配会把 list[sha.AST] 误判为元素类 AST),使 list[ast.ASTptr].get 被误绑为 list[int].get(返回 i32)后 inttoptr 截断指针,读垃圾 AST 节点崩溃(MatchGenMixin._handle_renum_match / _handle_simple_match)。
现统一以接收者实际 LLVM 结构体类型名(IR 真值)为准:基名为泛型模板时,含类型实参则以实际特化名覆盖;退化为裸泛型基类则 fail-fast(D25 口径,禁止静默默认 list[int])。
抽出 CallGenProp._strip_module_sha1_prefix / _resolve_generic_receiver_name / _is_list_builtin_receiver 共用实现;CallGenDispatch 8 处 list 内建判据同步改为基于接收者实际类型(真实 list 命中与 __elem_size__/hit_box 行为不变,实际类型不可得时保留注解名回退)。lookup_name 缓冲改为按精确长度分配。
2026-09-13 21:11:33 +08:00
TermiNexus
76df3f0225
perf(gen): 结构体/类型查找去线性化并守卫全量遍历残量
...
StructGenMixin: 加「名 | Ty 指针值 -> 首注册下标」索引,find_struct/find_struct_by_module/find_struct_by_type 走 O(1) 快速路径;每次注册占槽保序,中和/改名后键不等自然跳过,未命中或索引不可信回退原扫描。并补 _struct_name_hash/_struct_ty_hash(32 位 FNV,常量均小于 2^63 以避开大十进制字面量解析风险)。
TypeSpec.InternSpec: 加「文本键 -> 驻留下标」开放寻址索引,去重由 O(n) 降为期望 O(1);命中返回原同一实例,注册顺序/容量 fail-fast 语义不变。
register_struct/lookup_field/get_class_name_by_type 的按 Ty 指针首匹配改走 find_struct_by_type;CallGenLeafKit/CallGenCall 的按序号全量遍历补守卫注释(避免后续误改为按名查找)。
2026-09-13 18:56:16 +08:00
TermiNexus
0dd7511a9b
fix(tpv): 修常量折成0致alloc(0)与多处fail-fast,并落地热点优化
...
TypeGenCDef: CDefine 表名深拷贝(vpi 注入名为零拷贝指针且 vpi_buf 提前释放,悬空名致常量查出错误值 0)
VpiReader: 模块级 SHA1_LEN(16) 改名 SHA1_HEX_LEN,消除与 Phase1.SHA1_LEN(17) 的跨模块同名冲突
CallGenCall: 实参翻译失败/漏传必需实参改 fail-fast,禁用零值兜底(堵住 SHA1_LEN 未解析变 alloc 0 的通路)
MatchGenMixin: 序列 match 的 case _ 分支补容量守卫(原先会越界写穿 pool 块、破坏空闲链)
Phase1Main/Phase1Scan: 预扫描缓冲分配失败改 fail-fast;加临时取证打点
CallGenBase: find_func_in_module 4 趟链表扫描合并为 2 趟
ImportsGenMixin: import 查找加哈希索引(键为 NUL 结尾副本,未命中回退原扫描)
TypeGenBase/TypeGenResolve: 库 typedef 按模块一次性门禁与缓存
VpiReader: vpi 注解解析补 rowptr[T] 分支
2026-09-13 17:50:03 +08:00
TermiNexus
af2c66e7d7
chore(tpv): 永久池扩容至 1 GiB
...
PERM_POOL_SIZE 由 512MB (536871176) 调整为 1 GiB (1073741824),为 REnum 注册表挂到 PermPool 后留足余量。
2026-09-12 23:14:52 +08:00
TermiNexus
eef84657a1
fix(tpv): 修正 REnum 表按名查找与 match 分派,恢复 str() 指针强转
...
str() 对整数(sizet/i64)走 snprintf 十进制格式化(Python 语义),不是 i8* 强转;用它读 sizet|t.CPtr 联合表元素再 strcmp 永不相等 => _is_renum_class_name 恒 0、变体名查不到(__types.vp:407 bits / :159 Void 根因)。IR 实证 output/a8891afb66d3eda4.text.ll L5551-5558。
- ClassGenEnum: RenumClassNames/RenumVariantNames 读侧统一改 (str)(t.CVoid(x, t.CPtr));新增 _is_renum_by_entry 与 RenumTableDump;REnum 注册静默早退改 fail-fast
- MatchGenMixin/CallGenMixin: match 分派 2a/2b 与变体构造入口并上 by_entry 判据
- TypeGenResolve: 泛型下标 Phase B 解析不出特化时 fail-fast
- CallGenProp: 泛型特化名末段按括号外点切分
- CompilerFactory/ClassGenBase: REnum 注册表改挂编译期单例
- ClassGenDef: CEnum/REnum 分派歧义 fail-fast
2026-09-12 23:14:23 +08:00
TermiNexus
e0e024ee93
fix(tpv): 注解裸名按 from-import 归属查找(D26 闭环)
...
stub 注入注解时 trans.ModuleSha1 是正在翻译的文件,而注解里的类归属 stub 源模块;仅靠当前模块 sha1 加全局可见性在 App 严格模式下查不到(AsyncGenMixin 未 import ast.Expression),导致 ast/__init__.vpi 的 parse_expression -> rowptr[Expression] 返回类型解析失败 fail-fast。TypeGenResolve 的 Name 分支在 own 之后、可见性之前插入 from_imports 归属查找(LookupModNameByAlias 到 LookupSha1ByModName 到 find_struct_by_module)。TPV 自举 Phase1 从 28/53 推进到 40/53
2026-09-12 19:37:55 +08:00
TermiNexus
ea2abba574
refactor(tpv): 删除 _deps_pending 置位面与 Phase A pending 多遍收敛机制
...
69 个工程成功编译且 _phaseA_pending.log 恒 0 字节,证实 14 个置位点全部零命中。删除 14 个 _MarkDepsPending 调用点(原「依赖未就绪」分支保留默认类型或原报错路径);删除 _MarkDepsPending 与 _AppendPhaseAPending 及 _phaseA_pending.log 读写;删除 Phase A 出口「pending 则不写盘、回滚 MethodsEmitted、continue」整段;删除 _deps_pending 与 _pf_dbg_pend_flagged 字段及全部读取分支;清理遗留探针 [PF-DBG] 与 [METHDBG]。16 files changed, +37 / -558
2026-09-12 19:24:52 +08:00
TermiNexus
17f109e204
fix(tpv): 修复 vpi 重导出包前缀与 D25 变量名悬垂,补齐 fatal_error 刷盘
...
VpiReader 包 __init__ 重导出补包前缀,类注册与方法声明两遍化,按需注入依赖 vpi(先登记后注入防环,失败撤销登记);VarGenMixin 的 add_var 深拷贝变量名,符号表条目不再依赖 AST tree 生命周期;CallGenCall 的 list 内建与泛型基类判定类名来源回退到接收者实际 struct 名;TypeGenErr 的 fatal_error 退出前 fflush;StubMergerBuild 每模块重置 vpi 注入去重表
2026-09-12 19:00:19 +08:00
TermiNexus
626f79cbd1
fix(tpv): vpi 相对导入补回包前缀(D26)
...
- vpi 只存 module=base(前导点记在 level),from-import 映射写字面 base 时,解析端按精确 LookupSha1ByModName 查不到 ast.base ⇒ 裸类名(AST 等)解析失败 ⇒ rowptr[AST] 等注解 fail-fast(TPV→TPV 自举 includes/ast/parser.vp parse 根因)
- 按 stub 自身相对路径还原包名(ast/parser.vp → ast),level==1 拼成 ast.base 再登记;_stub_add_imported 与 _stub_add_from 两处同步
2026-09-12 15:59:37 +08:00
TermiNexus
3c45895878
fix(tpv): alloca 退化守卫收窄到「裸泛型模板基类」形态(避免误杀同名重声明换类型)
...
- parser.vp:964 'node: rowptr[AST] = Slice(...)' 命中上一版守卫(旧 alloca 是 Tuple*)——但 Tuple* vs AST* 是同名重声明换具体类,两者都是 8 字节指针槽,属合法用法,不该 fatal
- 收窄判据:仅当旧 alloca 的 pointee 是**裸泛型模板基类**(剥 sha1 前缀后不含 '[' 且 _find_generic_template 命中)时才 fail-fast —— 这正是 D25 的退化形态(丢类型实参 → 方法调用按错误元素类型特化 → 截断)
2026-09-12 15:24:23 +08:00
TermiNexus
590a6a2bbe
fix(tpv): 复用的 alloca 与注解类型不一致时 fail-fast(D25 alloca 退化根治)
...
- get_or_create_sym 只用「名字+作用域」复用(ty 不参与判定),可能命中类型不同的旧 alloca(同名重声明 / 退化 alloca,如裸 list* 对上 list[ast.ASTptr]*)→ alloca 类型与使用点注解类型分裂 → 方法调用按错误元素类型特化 → inttoptr 截断
- 只比较「双方都是指针且 pointee 都是结构体」这一最典型退化形态:结构体名不同即 fatal_error,报出变量名与两个类型,直接暴露退化点(不兜底)
2026-09-12 15:13:41 +08:00
TermiNexus
b206e7d9c1
fix(tpv): 泛型类型实参禁止静默默认 int(D25 fail-fast 两处)
...
- CallGenMixin: 裸名泛型构造推断不出类型实参时不再默认 int,改 fatal(与 _infer_generic_ctor_type_arg 注释「绝不默认 int」对齐)
- CallGenCall._translate_method_call: 泛型模板基类(剥 sha1 前缀后不含 '[')上的非 list 内建方法调用改 fatal —— 此前静默按默认 list[int] 特化,元素按 i32 处理 → 方法返回 i32 → inttoptr 截断指针 → 读垃圾 AST 节点(D21/D25 崩溃族)
- list 内建方法仍走内联路径(运行时 __elem_size__),不受影响
2026-09-12 14:52:23 +08:00