diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index 821fc60..15a0d1e 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -927,8 +927,50 @@ novirtual class CallGenBase: return llvmlite.Ptr(pool, st_ty_st) return st_ty_st + # 命名类型(%"name" / %name)带指针:先解析到真实结构体/枚举类型再包 Ptr。 + # 为什么不许坍缩成通用 i8*:返回类型是「指向类对象」时,坍缩后调用方变量 + # 的 alloca 变成 i8*,下标语义随之从「类的 __getitem__」掉到「字节下标」。 + # 现场(Test/FakeDuckTest/App/main.vp:115 `p0: str = parts[0]`): + # includes/_fakeduck.vp `def split(self, delimiter: str) -> list[str]*`, + # 定义侧 text.ll 为 + # define %".list[str]"* @"._str.split"(...) + # 本函数若把 `%".list[str]"*` 当通用指针,parts 的 alloca 即 + # 退化为 i8* ⇒ parts[0] 取到整数 ⇒ 赋给 str 报 + # 「整数隐式转指针已禁止」(报文指不到真因)。 + # 解析不到登记项时保持原「通用指针」行为(名字可能来自尚未登记的模块)。 + if s < e and buf[s] == '%': + nm_s: sizet = s + 1 + nm_e: sizet = e + nm_star: int = 0 + while nm_e > nm_s and buf[nm_e - 1] == '*': + nm_star += 1 + nm_e -= 1 + while nm_e > nm_s and (buf[nm_e - 1] == ' ' or buf[nm_e - 1] == '\t'): + nm_e -= 1 + if nm_star > 0 and nm_e > nm_s: + if buf[nm_s] == '"' and buf[nm_e - 1] == '"': + nm_s += 1 + nm_e -= 1 + if nm_e > nm_s: + nm_len: sizet = nm_e - nm_s + nm_buf: bytes = stdlib.malloc(nm_len + 1) + if nm_buf is not None: + string.strncpy(nm_buf, buf + nm_s, nm_len) + nm_buf[nm_len] = '\0' + nm_ty: llvmlite.LLVMType* = GenApi.get_struct_type(nm_buf) + if nm_ty is None: + nm_ty = GenApi.get_enum_base_type(nm_buf) + stdlib.free(nm_buf) + if nm_ty is not None: + nm_wrap: llvmlite.LLVMType* = nm_ty + nm_i: int = 0 + while nm_i < nm_star: + nm_wrap = llvmlite.Ptr(pool, nm_wrap) + nm_i += 1 + return nm_wrap + # 检查是否含 * (指针类型) → 返回 i8* (通用指针) - # 包括 i8*, i32*, %"name"*, { i32, i8 }* 等 + # 包括 i8*, i32*, { i32, i8 }*,以及上面未登记命名的 %name* ci: sizet = s while ci < e: if buf[ci] == '*':