diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index f44bf23..fc7b91b 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -478,9 +478,8 @@ 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) + # 下标 zext 由 llvmlite.build_gep / build_gep_array 内部统一处理 + # (唯一真源),此处不再自行 zext。 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/ExprGenBase.vp b/App/lib/core/Gen/Expr/ExprGenBase.vp index 7e758aa..0ede3c9 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -195,24 +195,6 @@ novirtual class ExprGenBase: case _: return 0 # ============================================================ - # _zext_index_to_i32 - 数组下标索引零扩展 - # - # LLVM GEP 对窄整数索引默认符号扩展:i8 0xE2(226) 会被当成 -30, - # 导致数组下标越界读(字节 >= 128 的乱码根因)。 - # 数组下标语义为非负,<32 位整数索引一律 zext 到 i32。 - # 仅用于数组 GEP;指针负偏移(p[-1])不经过此路径,不受影响。 - # ============================================================ - def _zext_index_to_i32(self, builder: llvmlite.IRBuilder*, - idx_val: llvmlite.Value*) -> llvmlite.Value*: - """将 <32 位整数下标零扩展到 i32(数组下标非负语义)""" - if idx_val is None or idx_val.Ty is None or builder is None: - return idx_val - idx_bits: int = self.get_llvm_type_bits(idx_val.Ty) - if idx_bits != 0 and idx_bits < 32: - i32_ty: llvmlite.LLVMType* = llvmlite.Int32(builder.Pool) - return llvmlite.build_zext(builder, idx_val, i32_ty) - return idx_val - # ============================================================ # _get_custom_struct_cls_nm - 检查类型是否为已注册的自定义结构体 # # 处理两种情况: diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index 91a42b3..f18b451 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -691,7 +691,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): arr_ptr_nl: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_nl, llvmlite.Ptr(pool, nl_ty)) if arr_ptr_nl is None: return None - return llvmlite.build_gep_array(builder, nl_ty, elem_ty_nl, arr_ptr_nl, self._zext_index_to_i32(builder, idx_val)) + return llvmlite.build_gep_array(builder, nl_ty, elem_ty_nl, arr_ptr_nl, idx_val) case llvmlite.LLVMType.Ptr(inner_nl): arr_ptr_nl2: llvmlite.Value* = llvmlite.build_bitcast(builder, raw_nl, llvmlite.Ptr(pool, nl_ty)) if arr_ptr_nl2 is None: return None @@ -746,14 +746,9 @@ 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) + # 窄整数下标(i8/i16)的 zext 已下沉到 llvmlite.build_gep / + # build_gep_array 内部(唯一真源),此处不再自行 zext——否则裸指针 + # 下标(build_gep)会漏掉,字节 >= 128 的索引被 LLVM 符号扩展成负数。 # 嵌套下标读取: a[i][j] —— 递归取内层指针后 load # (与 get_subscript_ptr 嵌套分支对称;如 gfx.vp 的 @@ -766,7 +761,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if inner_elem_r is None: return None match inner_elem_r: case llvmlite.LLVMType.Array(arr_ie_r, _): - elem_ptr_r: llvmlite.Value* = llvmlite.build_gep_array(builder, inner_elem_r, arr_ie_r, inner_ptr_r, self._zext_index_to_i32(builder, idx_val)) + elem_ptr_r: llvmlite.Value* = llvmlite.build_gep_array(builder, inner_elem_r, arr_ie_r, inner_ptr_r, idx_val) if elem_ptr_r is not None: return llvmlite.build_load(builder, arr_ie_r, elem_ptr_r) return None @@ -804,7 +799,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): match pointee: case llvmlite.LLVMType.Array(elem_ty, count): # 数组遍历: getelementptr [N x elem_ty], ... , i32 0, i32 %idx - elem_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, pointee, elem_ty, alloca, self._zext_index_to_i32(builder, idx_val)) + elem_ptr: llvmlite.Value* = llvmlite.build_gep_array(builder, pointee, elem_ty, alloca, idx_val) if elem_ptr is not None: return llvmlite.build_load(builder, elem_ty, elem_ptr) return None @@ -978,7 +973,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 数组类型: 双索引 GEP + load 元素 match elem_ty2: case llvmlite.LLVMType.Array(arr_elem_ty2, arr_count2): - elem_ptr3: llvmlite.Value* = llvmlite.build_gep_array(builder, elem_ty2, arr_elem_ty2, ptr_val, self._zext_index_to_i32(builder, idx_val)) + elem_ptr3: llvmlite.Value* = llvmlite.build_gep_array(builder, elem_ty2, arr_elem_ty2, ptr_val, idx_val) if elem_ptr3 is not None: return llvmlite.build_load(builder, arr_elem_ty2, elem_ptr3, vol_sub_gen) return None @@ -1094,14 +1089,9 @@ 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) + # 窄整数下标(i8/i16)的 zext 已下沉到 llvmlite.build_gep / + # build_gep_array 内部(唯一真源),此处不再自行 zext——否则裸指针 + # 下标(build_gep)会漏掉,字节 >= 128 的索引被 LLVM 符号扩展成负数。 # 嵌套下标: a[i][j] = v —— 递归解析内层下标指针后 GEP # (如 gfx.vp Mat4.m: t.CArray[t.CArray[float, 4], 4] 的 m.m[0][0] = 1; @@ -1115,7 +1105,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if inner_elem is None: return None match inner_elem: case llvmlite.LLVMType.Array(arr_ie, _): - return llvmlite.build_gep_array(builder, inner_elem, arr_ie, inner_ptr, self._zext_index_to_i32(builder, idx_val)) + return llvmlite.build_gep_array(builder, inner_elem, arr_ie, inner_ptr, idx_val) case _: return llvmlite.build_gep(builder, inner_elem, inner_ptr, idx_val) @@ -1136,7 +1126,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): match pointee: case llvmlite.LLVMType.Array(elem_ty, count): # 数组遍历 - return llvmlite.build_gep_array(builder, pointee, elem_ty, alloca, self._zext_index_to_i32(builder, idx_val)) + return llvmlite.build_gep_array(builder, pointee, elem_ty, alloca, idx_val) case llvmlite.LLVMType.Ptr(inner_ty): # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针, # 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。 @@ -1234,7 +1224,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 数组类型: 双索引 GEP (getelementptr [N x ty], ptr, i32 0, i32 idx) match elem_ty2: case llvmlite.LLVMType.Array(arr_elem_ty, arr_count): - return llvmlite.build_gep_array(builder, elem_ty2, arr_elem_ty, ptr_val, self._zext_index_to_i32(builder, idx_val)) + return llvmlite.build_gep_array(builder, elem_ty2, arr_elem_ty, ptr_val, idx_val) case _: pass # 自定义结构体 (如 self._ht[key]): 仅当类定义了 __setitem__