From bcbc7142be6aeb8edbc22d153efe54c7a6afd071 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 13:20:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(subscript):=20=E6=8C=87=E9=92=88=E4=B8=8B?= =?UTF-8?q?=E6=A0=87=20GEP=20=E8=A1=A5=20zext=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20i8=20=E4=B8=8B=E6=A0=87=E8=A2=AB=E7=AC=A6=E5=8F=B7=E6=89=A9?= =?UTF-8?q?=E5=B1=95=EF=BC=88uint8ptr[200]=20->=20p[-56]=20=E8=B6=8A?= =?UTF-8?q?=E7=95=8C=EF=BC=89=EF=BC=8Czlib=20=E6=BC=8F=E8=AE=A1=E5=AD=97?= =?UTF-8?q?=E8=8A=82>=3D128=20=E6=A0=B9=E5=9B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Call/CallGenCBuiltin.vp | 3 +++ App/lib/core/Gen/Expr/ExprGenName.vp | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 810fad9..f44bf23 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -478,6 +478,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if arr_val is None or arr_val.Ty is None: return None idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_addr.slice, None, 0, trans) if idx_val is None: return None + # 与 ExprGenName 的指针下标路径同口径:窄整数下标(i8/i16)必须 zext + # 到 i32,否则 LLVM 按符号扩展(uint8ptr[200] → p[-56])越界。 + idx_val = self.Gen.ExprGenBase._zext_index_to_i32(builder, idx_val) arr_pointee_ca: llvmlite.LLVMType* = None if self.Gen.ExprGenBase.is_ptr_type(arr_val.Ty) != 0: arr_pointee_ca = arr_val.Ty.Pointee diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index 08bf13e..91a42b3 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -746,6 +746,14 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 翻译索引 idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.slice, None, 0, trans) if idx_val is None: return None + # 窄整数下标(i8/i16)在 GEP 中会被 LLVM 按**符号扩展**:uint8ptr[200] + # 变成 p[-56],写到数组之前 / 读越界。_zext_index_to_i32 的注释记录的 + # 正是这个现象("字节 >= 128 的乱码根因"),但此前只接在数组 GEP 路径; + # 裸指针下标(UINT8PTR / INTPTR / 各类 rawptr)走 build_gep,漏了 zext + # ——zlib 的 lit_freqs[data[pos]] 漏计字节 >=128 即由此而来。 + # 下标语义为非负,故在唯一入口统一 zext(i32 及以上不动,p[-1] 这类 + # i32 负偏移不受影响;下游 coerce_to_type/sizet(...) 均为 i32→i64 拓宽)。 + idx_val = self._zext_index_to_i32(builder, idx_val) # 嵌套下标读取: a[i][j] —— 递归取内层指针后 load # (与 get_subscript_ptr 嵌套分支对称;如 gfx.vp 的 @@ -1086,6 +1094,14 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 翻译索引 idx_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.slice, None, 0, trans) if idx_val is None: return None + # 窄整数下标(i8/i16)在 GEP 中会被 LLVM 按**符号扩展**:uint8ptr[200] + # 变成 p[-56],写到数组之前 / 读越界。_zext_index_to_i32 的注释记录的 + # 正是这个现象("字节 >= 128 的乱码根因"),但此前只接在数组 GEP 路径; + # 裸指针下标(UINT8PTR / INTPTR / 各类 rawptr)走 build_gep,漏了 zext + # ——zlib 的 lit_freqs[data[pos]] 漏计字节 >=128 即由此而来。 + # 下标语义为非负,故在唯一入口统一 zext(i32 及以上不动,p[-1] 这类 + # i32 负偏移不受影响;下游 coerce_to_type/sizet(...) 均为 i32→i64 拓宽)。 + idx_val = self._zext_index_to_i32(builder, idx_val) # 嵌套下标: a[i][j] = v —— 递归解析内层下标指针后 GEP # (如 gfx.vp Mat4.m: t.CArray[t.CArray[float, 4], 4] 的 m.m[0][0] = 1;