refactor(subscript): 删除调用侧下标 zext 与 _zext_index_to_i32,统一交给 build_gep(单一真源)
This commit is contained in:
1 parent
bcbc7142be
commit
df1ffa4c2a
3 files changed
+15
-44
No files matched your search
@@ -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
|
||||
|
||||
@@ -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 - 检查类型是否为已注册的自定义结构体
|
||||
#
|
||||
# 处理两种情况:
|
||||
|
||||
@@ -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__
|
||||
|
||||
Reference in new issue
Block a user