fix(tpc): 局部 str*/str|t.CPtr 注解不再被压平成 i8*(补 PtrCount<=1 豁免)

类别 b(机制漏豁免):`TypeInfo.IsStr` 对**任何** CChar + 指针层都为真,
局部 AnnAssign 处却无条件把 PtrCount 压成 1,导致 `argv_arr: str*` 被声明为
i8*,而同名模块级全局 `_argv: str*` 走 HandlesAssign._EmitGlobalAnnAssignLlvm
的 FromNode 得到 i8**,于是 `_argv = argv_arr` 被
「指针隐式转换已禁止(层数不同):i8* → i8**」拦下(includes/sys.vp:114、
_init_argv_posix 同款 L148)。

同一规则在 HandlesFunctions.py:599 / 690 / 722 / 1434 / 1514 / 1602 / 1662 与
HandlesImports.py:1440 / 1542 都已带 `IsStr and PtrCount <= 1` 豁免(注释写明
"str | t.CPtr 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平"),
唯独 HandlesAnnAssign.py:452 漏了这一条 —— 本次补齐:只压平 PtrCount<=1,
`str*` / `str | t.CPtr` 保持 i8**;_str 影子结构与 var_ptr_element(8 字节步长)
标记仍照旧执行。

判据(不猜):
1. TPV 参考实现产物 Test/SysLibTest/.tpv_build/temp/0c/0cc16828640f94b7.ll:
   `@"0cc16828640f94b7._argv" = global i8**`、_init_argv_win32 内
   `alloca i8**`(argv_arr)、`store i8** %x, i8*** @"..._argv"` —— 局部与全局
   同为 i8**。
2. TPC 全局侧 FromNode 对 `str*` 给出 PtrCount=2(CChar + str 的 1 层 + CPtr 的 1 层)。

重编即可验证 sys.vp 第 84/114 行一致。
This commit is contained in:
TermiNexus committed 2026-09-29 13:33:54 +08:00
1 parent 25cda80995
commit 8c831a38d3
1 file changed
+12 -4
+12 -4
View File
@@ -450,10 +450,18 @@ class AnnAssignHandle(BaseHandle):
Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
return
if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'):
TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CChar()
TypeInfo.PtrCount = 1
IsPtr = True
# 仅指针层数 <= 1 才算裸 str/bytes(i8*),可以压平:`str | t.CPtr` /
# `str*` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 指针数组),
# 压平会让局部变量比模块级同名全局槽少一层指针
# (全局走 HandlesAssign._EmitGlobalAnnAssignLlvm 的 FromNode,得到 i8**),
# 于是 includes/sys.vp `_argv = argv_arr` 被指针隐式转换 fail-fast 拦下。
# 与 HandlesFunctions.py:599 / HandlesImports.py:1440 的
# `IsStr and PtrCount <= 1` 同一条规则源。
if TypeInfo.PtrCount <= 1:
TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CChar()
TypeInfo.PtrCount = 1
IsPtr = True
# FakeDuck: 为 str 变量创建影子结构体 a__meta__ (栈上, per-instance)
# a 保持为 char* 用于 printf; a__meta__ 存储 __data__ 和 __mbuddy__ 字段
# 仅对 str 类型创建,bytes 和 t.CChar|t.CPtr 不创建