TermiNexus
f2d7b748ea
fix(func): 末尾收尾的可达性判据只认 _ctrl_merge_reachable(删掉“穷尽通配臂即不可达”的错误推断)
...
症状:includes/llvmlite/__types.vp::_TypePrintDepth 末句 match ty:(各臂只 snprintf 后 br 到 merge)被生成 match.end: unreachable;llc 不给可达 unreachable 生成任何指令 ⇒ 执行掉进布局紧随其后的同一 switch 跳转表,用上一条 snprintf 的返回值 3 当 tag 取 table[3]=Array 臂 ⇒ 把 Int 的 Bits(32) 当指针递归解引用 ⇒ AV at 0x20(裸 0xC0000005;ASan 下同一崩溃被转为 0x80000003 = -2147483645)
根因:last_is_ctrl and (_ctrl_merge_reachable == 0 or MatchHasWildcardArm(...)) 的“追加92”通配臂子句——穷尽性只保证匹配总能命中某臂,不保证各臂都终止且不 br 到 merge;而 _ctrl_merge_reachable 恰是逐臂真正 br end_bb 时才置 1 的精确信号(MatchGenMixin:717 写回)
修法:两处收尾判据(FuncGenDef 模块级函数 / ClassGenVTable 方法)都只在 _ctrl_merge_reachable == 0 时 build_unreachable;merge 可达时走既有分支正常收尾(void→ret void;无注解→ConstZero;有非 void 注解→fail-fast,不发明返回值)
删除随之失效的 MatchHasWildcardArm 与其私有 helper _IsWildcardPattern(全仓已无引用)
2026-09-28 12:41:04 +08:00
TermiNexus
5e100e2195
fix(match): REnum 变体字段绑定不再静默跳过(__types.vp bits NameError)
...
根因:_handle_renum_match step6 用 renum_name 查 struct 且不校验 Ty;拿不到 entry/Ty 时 step7 的 _bind_variant_fields 被整段静默跳过 -> case 绑定名在 body 里未定义,最终只报 NameError(bits),真因藏到下游
1) 名字回退:变体表与 struct 注册都按裸类名,而 renum_name 来自注解 SourceName(Attribute 可带模块限定名)-> 精确查找失配;与 tag 查表同一裸名推导(tag_cls_bare)
2) 新增 StructGenMixin.find_struct_entry_with_ty:跳过 D30 重注册时就地中和的旧 entry(Name[0]=0/Ty=None/FieldCount=0),避免命中它拿到 Ty=None
3) 禁止静默:仍有 REnum 判据为真却无法绑定时 fail-fast,打印 class/查表名/entry/FieldCount/ty_present(对齐 D30/D32 的响亮失败口径)
2026-09-27 23:58:15 +08:00
TermiNexus
a79e723e8d
fix(dwarf): DIFile 改用绝对路径,栈转储显示完整路径并回读源码行
...
根因:CurrentFile 是项目相对路径(./Test/LLvmLiteTest/App/main.vp),LLVM 把该目录写成 CU 的 DW_AT_comp_dir,主文件条目用 dir_index: 0 指向 comp_dir;stackmap 写入端只解析 --debug-line(无 comp_dir)⇒ 行记录退化成裸名 main.vp,运行期既显示不全也无法按路径重读源码行
改法:DIFile filename 保留整条绝对路径(相对路径先经 w32file.GetCurrentDirectoryA 前置 CWD,与 Repl.vp 同款低层调用,不经 os._mbuddy);directory 另存目录前缀。无论 LLVM 保留整条 name 还是拆成 dir+basename,写端都得到绝对路径,故无需改写入端
2026-09-27 19:18:16 +08:00
TermiNexus
bb864dff6f
fix(traceback): stackmap 的文件名全部退化为 ?? —— _tb_parse_dec 不跳前导空格
...
dwarfdump 的方括号索引右对齐(file_names[ 1] / include_directories[ 12]),_tb_bracket_idx 把 ' 1]' 交给 _tb_parse_dec,首字符非数字使循环体一次不进 -> 全部 pidx=0;行记录 fidx=1..N 永不匹配 -> 每条记录落到 '??'(实证 9146/9146 条共用同一个 '??' 串,而函数名/行号均正确)
_tb_parse_dec 增跳前导空格与制表符(修复文件名与目录索引两处)
dir_index: 偏移 st+9 指向冒号本身,恒解析为 0 -> 相对文件名拼不出绝对路径;改为 st+10
2026-09-27 19:01:23 +08:00
TermiNexus
31898ab4a5
fix(stubmerger): define→declare 降级时剥掉行尾函数级元数据附加(!dbg !N)
...
llc 对 declare 不接受元数据附加,报 expected = here(实证 LLvmLiteTest 949685246c8e241c.ll:898:104 的 declare ... !dbg !71)
根因:降级只删尾部 ' {',源 define 头行的 ' !dbg !71 ' 被原样抄下;declare 无函数体,!dbg 无意义(FunctionPrint 对 declare 从不打印 !dbg)
判据:参数表之后、括号深度 0、不在双引号内的 ' !';连同前导空白一起截断
2026-09-27 18:30:39 +08:00
TermiNexus
66e697e8df
feat(codegen): 模块级 extern 全局生成外部声明(@裸名 = external global T)
...
注解含 t.CExtern/t.State → is_global_extern:裸名(无 SHA1 头)、Linkage=external、不写初始值、不建 storage
与 export 全局(本模块定义 + 裸名)区分;配合 includes f854f7e 的 export/extern 变量语法
2026-09-27 17:56:51 +08:00
TermiNexus
d82f24e17a
fix(diag): AST 解析失败日志行内联 行/列 + 原因
...
四处解析失败上报点(Phase2 的 [Phase A-pre-vpi]、Phase1 的 [Phase 1b-pre] 与单文件、main.vp 单文件)此前只打 AST 解析失败,看不到定位与原因;现内联 第 N 行第 M 列: <原因>,与 dump_parse_traceback 的完整 traceback 同源(原因由 includes/ast/parser.vp 的 _record_* 与 parse_tokens 出口兜底补记提供)。另:App/main.vp 同时带上你工作区既有的 define 迁移/版本号改动。
2026-09-27 17:32:34 +08:00
TermiNexus
e65f04f16b
fix(codegen): 字段表↔槽位一致性护栏豁免联合体
...
union 的字段表有 N 条(每成员一条)但 LLVM 布局只有 1 个槽位(成员全偏移 0、按最大成员定宽),二者本不相等;字段访问走 bitcast 到字段类型后的 GEP,不依赖槽位下标。误报实证:EdgeCaseTest 的 class Data(t.CUnion)(i_val/f_val 两成员 → 1 槽)被护栏拦下。
2026-09-27 17:26:04 +08:00
TermiNexus
0279965074
fix(codegen): 指针强转基座 T*(x) 的字段读写补按需过滤类名通道
...
(ast.Call*(vinner)).IsVolatile 报属性写入失败:T*(x) 被 parser 的 _consume_ptr_suffix_call 解析成 (T | t.CPtr)(x) 强转调用,结果类型是联合简化后的 i8*,lookup_field(i8,...) 必失败,而按需过滤的类名提取只认 Name/Attribute。新增 _base_class_from_cast_base:从强转注解(func 是 BitOr 联合)取裸类名,读路径、写路径、属性链递归父节点三处接入。取裸名而非模块限定名——lookup_field_by_class 的模块限定分支对「包名可解析、类注册在子模块」的形态会 fail-fast。
2026-09-27 16:02:04 +08:00
TermiNexus
beccb36b66
feat(codegen): 单目 & 支持对构造调用/函数调用结果取址
...
&ViperKernel() 此前被左值检查拒绝(只在 Name/Attribute/Subscript 放行)。构造调用 _translate_struct_ctor 返回的就是入口 alloca 的栈存储指针,取址即原样返回该指针;其它返回值落到入口临时槽 alloca+store。复用 translate_unaryop 已求值结果,避免构造被求值两遍(__before_init__/__init__ 跑两次)。
2026-09-27 15:15:59 +08:00
TermiNexus
4255ab9d32
fix(fstr): f-string 改回每站点栈缓冲 + 禁止逃逸,逃逸点改 stdlib 拷贝
...
ExprGenFstr._fstr_finalize:结果缓冲改回每站点栈 alloca(线程安全、零运行时依赖;每站点各建一个,站点之间不再共享),docstring 与文件头写明语义:f-string 结果是当前函数内的临时值。
GenApi 新增唯一判据 fail_if_fstring_escape 与唯一拷贝出口 escape_fstring_copy(stdlib.malloc + string.strcpy);逃逸位置接护栏:translate_return(函数返回值)、translate_assign(字段/元素/全局变量赋值)、handle_module_level_var(模块级 AnnAssign 初始化)。
编译器自身 7 处逃逸点(ExprGenBase._cast_fail_where 6 处、AssignGenMixin.const_assign_msg 1 处)改为 escape_fstring_copy 显式拷贝——正是造成 ASan stack-buffer-underflow in vsnprintf 的那条路径。
残留(已在 GenApi 头注释诚实记录):间接逃逸(把 f-string 传进会保存它的函数、或放进容器后带走容器)静态判不出;类字段默认值路径未接护栏。全仓自查:TransPyV/App、includes、ViperApps 均无 容器/字段/全局 存 f-string 的写法,也无残留 return f-string。
2026-09-27 14:45:28 +08:00
TermiNexus
72a3c483e4
fix(fstr): f-string 结果缓冲改为模块级全局,修 return f-string 的悬空栈指针
...
现象:--asan 下 ASan stack-buffer-underflow(READ size 1,地址落在栈左红区)in vsnprintf,栈为 ExprGenBase.coerce_to_type:409 的 f-string 报文;非 asan 构建表现为随机乱码或 0xC0000005。
根因:_fstr_finalize 用 _alloca_at_entry 在当前函数开一个 [FSTR_BUF_SIZE x i8] 栈缓冲并返回其指针;而 f-string 结果在全仓被大量 return 带出函数(ExprGenBase._cast_fail_where、AssignGenMixin.const_assign_msg、CallGenLib 报文构造等),返回后再作 %s 喂给 snprintf 即读已弹栈的帧;且同一函数内多个 f-string 共用同一个 entry alloca 会互相覆盖。
修法:结果缓冲改为每个 f-string 站点一个模块级可写全局 internal unnamed_addr global [N x i8] zeroinitializer,经 bitcast 取 i8*(与 ExprGenConst.create_global_string 同一构造路径,符号链接期解析)。被否决的中间方案记录在注释里:编译期池缓冲 + inttoptr 常量地址会把编译进程的宿主地址烘进 .ll,对产出程序无效,绝不可用。
已知取舍(注释中写明,与 C 的 static char buf[N] 惯用法同):同一站点反复求值且同时保留多个结果时后者覆盖前者;多线程避免共享同一站点结果。彻底消除需运行时字符串分配器(当前无)。
2026-09-27 14:33:54 +08:00
TermiNexus
ca5473304f
fix(gen): 结构体字段表与 LLVM 槽位一致性 fail-fast 护栏
...
新增 StructGenMixin.verify_field_slot_consistency:字段表条数必须等于结构体槽位数,且每条目 Ty 与 Index 槽位同类(指针性/整数位宽/浮点位宽);不一致即 fatal_error 并指名 类/字段/下标/两侧类型。由 lookup_field 第一遍调用。
背景(真实崩溃):模块 8a96a2885bae09ca(ExprGenOps)把 ast.Name.id 编译成 GEP 下标 9(该槽是 ctx,i32),同一次构建里 320b55907b889d59(AssignGenMixin)用下标 8(i8*),两者共用同一 %struct 布局。后果:nm.id 读成 ctx(ASTCtx.Store=1)- inttoptr i32 1 - strlen(0x1) - ASan access-violation at 0x1。
2026-09-27 14:00:18 +08:00
TermiNexus
12bd7b7a16
fix(gen): 收敛 static 跨模块拦截为独立方法,消除类型推断污染
...
新增五个独立方法承载 static 检查与登记:_CheckStaticCrossModule(mod.name 取值)、_CheckStaticCallCrossModule(mod.fn 调用)、_CheckStaticFromImport(from-import)、_RegisterStaticModuleVar(模块级变量登记)、_RegisterStaticFunc(函数登记)。调用点只保留一行调用——内联新增分支会改变超大函数的类型推断,曾导致 translate_attribute 后续 match obj_ptr.Ty 报指针隐式转整数已禁止。
删除 _resolve_module_attribute_global 内与入口检查重复的 static 拦截(其两个调用点均在 _CheckStaticCrossModule 之后)。
2026-09-27 13:12:22 +08:00
TermiNexus
dd56580855
feat(gen,static): static 符号禁止跨模块使用(定义侧登记 + 引用侧三处拦截)
...
语义 = C 的 internal linkage:static 符号(函数/变量)只在定义模块内可见,任何跨模块引用一律 fail-fast(NameError)。
- 登记表:CallGenBase 新增 StaticSha1Arr/StaticNameArr/StaticCount(PermPool 定长槽,与 CexportSha1Arr 同款)+ RegisterStaticSymbol/IsStaticSymbol(按 (符号名, 模块 SHA1) 精确配对,避免跨模块同名误判)。
- 定义侧登记:FuncGenDef 识别注解形态(-> t.CVoid | t.CStatic)与装饰器形态(@t.CStatic;裸 static def 已由解析层归一为装饰器)→ 登记函数名;TranslatorGenMixin.handle_module_level_var 识别注解形态(static x: int 已归一为 t.CStatic | int)→ 登记变量名。
- 引用侧拦截(三处,覆盖全部跨模块形态):ExprGenAttr.translate_attribute 入口统一拦截 mod.name(含 import 别名还原);CallGenMixin.translate_call 入口拦截 mod.fn(...) 调用(按 AST 形态一次覆盖 found_func/vpi/裸名兜底各分支);ImportsGenMixin.translate_import_from_names 拦截 from mod import name。
- 性能:三处检查均以 StaticCount > 0 快速短路——项目中无 static 符号时零开销(不触碰逐条线性扫描与 sha1 解析)。
- 同模块自引用(sha1 相同)与非模块基座(self.method / obj.field / Class.static_method)一律放行。
2026-09-27 12:58:51 +08:00
TermiNexus
424dbd7379
chore(gen): 加 [MODSHA1] 临时诊断定位 string.split 模块名解析失败(定位后删除)
...
在 translate_call 的模块限定分支加两条探针:
- [MODSHA1]:mod_ret_sha1 为 None 时打印 mod_path_ret / func_name / exact / suffix / ctrl_stdint(对照模块,必在 includes)——可区分 store 整体为空 与 store 有内容但缺该模块。
- [MODSHA1-D]:裸名兜底分支里,若 cl.func 仍是 Attribute(模块限定却解析不出模块的异常组合)则打印 mod_path_ret 与 func_name——覆盖 mod_path_ret 为 None 的情形。
同时把 mod_path_ret 的声明从 if 块内移到 if 外(与 mod_ret_sha1 一致),避免下游分支读未声明局部取到栈垃圾。
证据链:报错来自本函数 861 行(全仓唯一 fatal_if_unknown=1 的调用点),条件恒为 _resolve_module_sha1 对 string 返回 None;但 _sha1_map.txt 有 includes/string.vp、其 vpi 有 def split -> int、Phase1Main:390 是唯一写 map 处 ⇒ 静态无法解释,需运行时诊断。
2026-09-27 12:52:03 +08:00
TermiNexus
87f5b1026c
chore(gen): 删除 CallGenDispatch 的 [MDISP] 临时探针及其专用 import stdio
...
该探针(并排取证 __with_ctx.__enter__ 与 pool.alloc 的 H6 判据命中差异)为定位 MpoolOopTest 的「跨模块调用 pool.alloc 找不到模块 SHA1」临时加入,现缺陷已定位,探针与其唯一使用者 import stdio 一并移除;非 local 对象分派逻辑不变。
2026-09-27 12:32:52 +08:00
TermiNexus
9455db0eec
feat(gen,type): callable[] / callable[[]] / callable[[A,B],R] 与 t.Callable 逐点等价
...
- 判据单一真源:_SubscriptAttrIsCallable 扩为 _IsCallableSubscriptValue,同时认 Attribute(attr=Callable) 与裸名 Name(callable | Callable)。
- Subscript 分支在 Name 路径(泛型特化 / CArray / builtins typedef 兜底)之前拦截裸名 callable/Callable → i8*;否则 callable[] 会先撞 slice=None 的 fail-fast、callable[[]] 会被当泛型类名查空。
- TypeGenErr.try_extract_callable_ret 改用同一判据:callable[[A, B], R] 现在也会注册返回类型 R(可间接调用),无签名形态([]、[[]])仍返回 None。
2026-09-27 12:30:47 +08:00
TermiNexus
a76cf55a2d
feat(gen,type): 注解位置的小写裸名 callable 等价 t.Callable(i8*)
...
支持 func: callable = 函数名 的写法:Name 分支兜底 map_t_type 命中 callable → Ptr(Int8),与 t.Callable / t.Callable[] / t.Callable[[]] 同一 LLVM 表示(无签名函数指针,只取地址不作间接调用)。
同时明确大写裸名 Callable 同时服务 from t import Callable 与 Attribute 分支的 t.Callable。
2026-09-27 12:28:58 +08:00
TermiNexus
c387926977
feat(gen,type): 支持无签名函数指针 t.Callable / t.Callable[] / t.Callable[[]]
...
三种写法统一解析为 i8*(与带完整签名的 t.Callable[[A,B], Ret] 同表示;函数值按 TPV 惯例 bitcast 为 i8* 存储):
- map_t_type 新增 Callable → Ptr(Int8):裸 t.Callable 此前落空导致 AnnAssign 注解类型解析失败。
- resolve_annotation_type 的 Subscript 分支:slice 为 None 时先放行 Callable(t.Callable[] 走空下标解析),其它类型仍 fail-fast 缺少 slice。
- 新增 _SubscriptAttrIsCallable 判据。
无签名形态不注册返回类型(try_extract_callable_ret 对非 Tuple slice 返回 None)⇒ 只适用于取地址/内联汇编操作数,不作编译器间接调用。
2026-09-27 12:25:52 +08:00
TermiNexus
7c53a8744d
fix(gen,match): 穷尽 match 不再误报流程掉出末尾;default 臂直译不再经 def_arr 反查
...
现象:函数末句为 match 且含 case _: 穷尽臂、各臂均 return 时,仍报 TypeError 函数流程掉出函数末尾(ioctl 4 具体臂 + case _)。
- FuncGenDef / ClassGenVTable:收尾判据由「_ctrl_merge_reachable == 0」扩为「或末句 match 含无 guard 的 case _ 通配臂」。穷尽 match 不存在全臂不命中的路径,与 If/While 全分支 return 同语义,应生成 unreachable 而非 fail-fast。
- MatchGenMixin 新增 MatchHasWildcardArm / _IsWildcardPattern:识别 MatchAs(pattern=None)(含 as/or 组合),带 guard 的 case _ if c 不算穷尽。
- MatchGenMixin:_handle_simple_match / _handle_renum_match / _handle_sequence_match 三条路径改为 pass1 显式记录 default_case_node,default 块直译该节点;原实现经 def_arr[di] 反查 cases_list[di],collected 下标与原始下标在「有臂被跳过」时错位 → default_bb 空转 → merge 误判可达(同时 case _ 臂不生成 IR)。
2026-09-27 12:17:14 +08:00
TermiNexus
cf815b17de
feat(gen): volatile 构造写入落 LLVM volatile(逐字段 store + 构造三方法屏障)
...
值位置 volatile 前缀(a: int = volatile f() / a: S = volatile S(...))此前只在调用点无落点。LLVM 的 call 指令没有 volatile 限定符,故语义只能落在内存存取上:
- AssignGenMixin:赋值目标的结果槽按 volatile 存取(本次 store 立即带 volatile,并登记 VarEntry.IsVolatile 使后续 load/store 亦带);对已存在的 global/nonlocal/mod_glob 条目在分支前统一登记。
- CallGenCtor:_translate_struct_ctor / _translate_struct_ctor_kw / _translate_renum_construct / _apply_struct_defaults 增加 is_volatile 参数,清零、tag、默认值、逐字段 store 全部带 volatile;_translate_generic_ctor_call 直接从 cl.IsVolatile 取。
- CallGenCall._call_method_on_ptr 增加 is_volatile 参数:__new__/__before_init__/__init__ 的写入发生在被调函数内部,调用点无法逐条附加 volatile,故在调用后对该 self 指针追加一次 i8 volatile load 作为内存屏障,使构造写入不被优化器消除或跨越重排。
- CallGenMixin / CallGenDispatch:结构体、关键字、泛型、REnum 构造调用点统一透传 cl.IsVolatile。
2026-09-27 12:01:22 +08:00
TermiNexus
7d28c9649e
feat(gen,err): CastError 定位到出错表达式;vpi 生成 fail-fast;函数属性接受直接形态
...
- ExprGenBase:新增 _cast_fail_where,指针/整数隐式转换失败时打印出错表达式与列号(多实参调用可定位到具体实参,如 Name 'toggle_ptr')
- Converter:import / from-import 别名列表为空、Alias 指针为空、name 为空分别 fail-fast,不再写出 import , 这类残缺 vpi 行(该残缺会让包重导出注册失效,报出与根因无关的 NameError)
- FuncGenBase.extract_func_attrs:接受直接 @t.attr.<name> 装饰器形态(与类侧 _has_decorator 同口径),使 inline def 在无 import c 的文件里也生效
- 附:CallGenDispatch 内保留一处临时 [MDISP] 探针(MpoolOopTest pool.alloc 定位用)
2026-09-27 11:41:11 +08:00
TermiNexus
f084da7c01
feat(gen): 重复声明改为无条件失败(不再比较类型),global 后再注解同样报错
...
- 判据改为:模块级已有同名变量 + 函数内再次用注解声明同名变量 ⇒ TypeError 重复声明,不再比较注解类型是否与全局一致(此前仅在类型不一致时报错)
- 有 global/nonlocal 声明后再带注解声明同名变量也报错(注解与既有全局声明重复)
- 检查点前移到注解解析之前(紧跟 REPL 分支),保证优先于 coerce_to_type 报错
- 合法写法只剩两种:global + 无注解赋值修改全局;或换不重名的局部变量
2026-09-27 08:55:08 +08:00
TermiNexus
78fc7313fb
feat(gen): 同名全局 + 注解冲突优先报重复定义
...
- translate_annassign: 函数内(无 global/nonlocal、非模块级)再次注解同名变量时,若注解类型与模块级变量类型内容不一致 ⇒ TypeError 重复定义 fail-fast,不再延后到 RHS 的 coerce_to_type 报无关的「指针隐式转整数」(PointerTest/App/main.vp:46 _g_ptr: int = None,全局已是 t.CUInt32T | t.CPtr)
- 注解与全局一致时仍按 Python 语义遮蔽为独立局部变量(既有行为不变)
- 该检查走 _stg_ty_equal 内容比较(TypePrint),非地址比较,避免 Int32()/Ptr() 新实例造成误判
2026-09-27 08:50:18 +08:00
TermiNexus
f0309e4904
fix(gen,renum): 指针操作符目标写入落盘 + REnum tag 三侧口径统一,修 kind() CastError
...
- AssignGenMixin: 补 UnaryOp(Deref) 赋值目标分支(*p = v / *&x = *&y),非 Deref 的 &x/-x/~x fail-fast;*p += v 真正实现;Tuple/List 目标合并
- CallGenDispatch: kind() 改四级 REnum 判据(变体表 / struct __tag / pointee 带 __tag / X.field 声明类型反推);修正 build_load 第一参数误传指针类型 rk_tag_p(生成 load i32*, i32* 使返回值 Ty 为 i32*,导致 CallGenLib.vp:355 vk_a: int = val.Ty.kind() 报指针隐式转整数的 CastError),rk_load 分支同步改 rk_ty.Pointee
- CallGenCtor / MatchGenMixin: __tag 读/写/比统一取字段声明类型 FieldEntry.Ty
- Test/FieldReadTest: 字段读取探针
2026-09-27 00:19:44 +08:00
TermiNexus
bcf66edebe
fix(vpi): 防环访问表表满不再静默丢标记,改为 ×2 扩容 + fail-fast
...
表满时曾静默 return(丢标记)⇒ 防环失效 ⇒ 递归闭包反复重解析同一批 .vpi,每个 vpi 的 Lexer/Token/AST 都从池分配且本段不回收 ⇒ 单次 translate 吃数百 MB ⇒ 1 GiB 主池 OOM
改为可扩容(ResetVpiTypedefVisited 同步复位容量),分配/扩容失败立即报错终止
2026-09-26 21:25:23 +08:00
TermiNexus
373a20c3e5
perf(prof,gen): 编译热点优化 + 内存池 OOM 诊断接线 + REnum 指针载荷修正
...
CallGenBase: 模块返回类型文本表改单趟登记+查找,find_func_in_module 合并为单趟链表遍历(PROF 热点)
BuildPipeline: ensure_dir 增加快速路径(已存在目录直接返回)
AssignGenMixin/Translator: alloc 失败打印 Pool/PermPool 统计与阶段上下文(SetAllocCtx)
CallGenCtor: REnum 指针载荷补显式 build_ptrtoint 再 coerce/store;新增 DebugInfoGen.vp
其余为历史累积改动一并入库
2026-09-26 19:27:23 +08:00
TermiNexus
676c19c362
feat(asm,err,typedef): 支持 __asm__/__llvmir__ 裸名与 typedef 语法糖;解析报错统一 Python 风格 traceback
...
CallGenCBuiltin/CallGenDispatch: __asm__/__llvmir__ 裸名调用,asminp/asmout/irinp/irout 与裸 ASM_DESCR。
AssignGenMixin: 支持 define NAME: T = V 形式的 CDefine 浮点值恢复;负浮点(-1e308)剥一层 UnaryOp(USub)。
Phase1Main/Phase2: AST 解析失败改调 GenApi.dump_parse_traceback(Traceback + File/行 + 源码行 + caret)。
TypeGenResolve/TypeGenCType: typedef 文本扫描统一支持 typedef 语法糖(builtins/库/单文件三处共用同一解析)。
2026-09-25 13:11:16 +08:00
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