fix(subscript): 指针下标 GEP 补 zext,修复 i8 下标被符号扩展(uint8ptr[200] -> p[-56] 越界),zlib 漏计字节>=128 根因

This commit is contained in:
TermiNexus committed 2026-10-03 13:20:11 +08:00
1 parent ab0ee723b3
commit bcbc7142be
2 files changed
+19

No files matched your search

+3
View File
@@ -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
+16
View File
@@ -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;