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;