fix(transpyv): CallGenCBuiltin 的 clobbers 改为单级 t.CPtr,并同步该文件语法迁移
【类别 c 源码违规】clobbers 声明的指针层数与 alloc/memset 不一致。
现象:
翻译 App/lib/core/Gen/Call/CallGenCBuiltin.vp 报
「指针隐式转换已禁止(层数不同):不能用指针类型 i8* 初始化 clobbers: i8**」
出错表达式 'pool.alloc(8 * ASM_MAX_CLOBBERS)'(Call 形态,CallGenCBuiltin.vp:955:33)。
判据(三条,缺一不可):
1. memhub.MemBuddy.alloc(size: sizet) -> t.CPtr(includes/memhub.vp)即 i8* 单级;
2. str | t.CPtr 是 i8**(CChar + PtrCount 2),即字符串指针数组视图;
3. MemoryOps._ClassifyPtrImplicitConvert 判定顺序为**先比层数**,层数不同直接禁,
通用指针通配(void*)不跨层。
故 i8* 结果不能隐式初始化 i8** 变量 —— 与是否同名 str 无关。
取证补充:同函数下一行 string.memset(clobbers, 0, ...) 首参同样是 t.CPtr
(includes/string.vp: memset(ptr: t.CPtr, value: int, num: sizet)),
即便只给 clobbers 加 cast,memset 一样会挂 —— 必须把声明本身改回单级。
修法:clobbers 声明改回单级裸缓冲 t.CPtr,每槽按 8 字节字符串指针的写入沿用
下方既有的显式 cast 槽视图写法
(cl_ptr: str | t.CPtr = (str | t.CPtr)(cl_addr)),
与 includes/_dict.vp 的「缓冲单级 t.CPtr、槽视图 str | t.CPtr 显式 cast」范式一致。
此改**不引入新 cast、不绕过检查**,只是把声明修正到与真实分配/清零层数相符。
同类扫描:全 App + includes 内 str | t.CPtr = *.alloc(...) 形态仅此一处;
includes/sys.vp 两处早已是显式 str*(...) 转换。
同时并入本文件他人已完成的语法迁移(同文件合并提交):
- 常量声明 t.CDefine: T = 值 → define NAME = 值 语法糖(_CEXPORT_MAX /
ASM_MAX_OPERANDS / ASM_MAX_CLOBBERS / ASM_TEXT_BUF_SIZE / ASM_CONST_BUF_SIZE /
ASM_ARGS_BUF_SIZE / ASM_LINE_BUF_SIZE / LLVMIR_MAX_OPS / LLVMIR_TEMPLATE_BUF);
- @t.NoVTable + class → novirtual class;
- 删除常量块内已失效的注释与多余空行。
1 file changed, 17 insertions(+), 18 deletions(-)
This commit is contained in:
1 parent
1f93550b6d
commit
07f2f2e9fc
1 file changed
+17
-18
@@ -18,41 +18,34 @@ from . import CallGenBase
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 TPC 侧 HandlesExprCall 保持一致)
|
||||
#
|
||||
# GLOBAL_FUNC_MAX / GLOBAL_DEFAULTS_MAX / MAX_CLOSURE_NAMES /
|
||||
# MAX_FUNC_PTR_SIGS / ISINSTANCE_CLASS_MAX:唯一来源在 CallGenBase.vp
|
||||
# (本文件不使用,故不留副本;消费方 CallGenLeafKit.vp 经 CallGenBase.<NAME> 引用)。
|
||||
# ============================================================
|
||||
_CEXPORT_MAX: t.CDefine = 256
|
||||
ASM_MAX_OPERANDS: t.CDefine = 16
|
||||
define _CEXPORT_MAX = 256
|
||||
define ASM_MAX_OPERANDS = 16
|
||||
# clobber(~{...})容量独立于操作数上限:vipersimd ×8 内核单条 c.Asm
|
||||
# 需 21 项(memory + ymm0-15 + rcx/r8-r11)。此前复用 ASM_MAX_OPERANDS=16
|
||||
# 导致 21 项静默截断为 16,靠后的 GPR clobber(rcx/r8-r11)丢失 → llc 把
|
||||
# "r" 输入分进 asm 硬编码寄存器 → 现场 r8/r10=4、vmovupd [r8] 读 0x4 崩溃。
|
||||
ASM_MAX_CLOBBERS: t.CDefine = 32
|
||||
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
|
||||
ASM_CONST_BUF_SIZE: t.CDefine = 512
|
||||
ASM_ARGS_BUF_SIZE: t.CDefine = 512
|
||||
ASM_LINE_BUF_SIZE: t.CDefine = 4096
|
||||
LLVMIR_MAX_OPS: t.CDefine = 16
|
||||
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
|
||||
define ASM_MAX_CLOBBERS = 32
|
||||
define ASM_TEXT_BUF_SIZE = 2048
|
||||
define ASM_CONST_BUF_SIZE = 512
|
||||
define ASM_ARGS_BUF_SIZE = 512
|
||||
define ASM_LINE_BUF_SIZE = 4096
|
||||
define LLVMIR_MAX_OPS = 16
|
||||
define LLVMIR_TEMPLATE_BUF = 512
|
||||
|
||||
|
||||
# ============================================================
|
||||
# CallGenCBuiltin - c.*/asm/llvmir 内建
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
"""c.* 内建 + 内联汇编 + LLVMIR 翻译(继承 Base)"""
|
||||
|
||||
|
||||
def translate_c_deref(self, pool: memhub.MemBuddy*,
|
||||
builder: llvmlite.IRBuilder*,
|
||||
mod: llvmlite.LLVMModule*,
|
||||
cl: ast.Call*,
|
||||
trans: HT.Translator* = None) -> llvmlite.Value*:
|
||||
"""c.Deref(ptr) → load,宽度只由 ptr 的 pointee 类型决定
|
||||
|
||||
pointee 是 i8(t.CPtr / void* / str / bytes)恒读 1 字节;不再按赋值
|
||||
目标注解(CurAssignAnnot)反推宽度——那会让同一处 c.Deref(i8*) 的读取
|
||||
宽度取决于它是否恰好出现在带注解赋值的 RHS 里。需要按更宽类型读时,
|
||||
@@ -958,7 +951,13 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
# 与操作数上限解耦——长 clobber 集如 vipersimd ×8 的 21 项不得截断,
|
||||
# 否则硬编码 GPR(rcx/r8-r11)声明丢失 → 输入被 llc 错分配进被 clobber
|
||||
# 的寄存器 → 寄存器错乱/零页崩溃)
|
||||
clobbers: str | t.CPtr = pool.alloc(8 * ASM_MAX_CLOBBERS)
|
||||
# 类型必须是**单级**裸缓冲(t.CPtr = i8*):pool.alloc 返回 t.CPtr、
|
||||
# string.memset 首参也是 t.CPtr;每槽按 8 字节字符串指针写入由下方的
|
||||
# `cl_ptr: str | t.CPtr = (str | t.CPtr)(cl_addr)` 显式 cast 完成
|
||||
# (与 includes/_dict.vp 的一致模式:缓冲单级、槽视图 str | t.CPtr)。
|
||||
# 此前声明成 str | t.CPtr(=i8**) 与 alloc/memset 层数不符,隐式指针转换
|
||||
# 禁止"层数不同",首行即报错。
|
||||
clobbers: t.CPtr = pool.alloc(8 * ASM_MAX_CLOBBERS)
|
||||
if clobbers is None:
|
||||
return None
|
||||
string.memset(clobbers, 0, 8 * ASM_MAX_CLOBBERS)
|
||||
|
||||
Reference in new issue
Block a user