feat(tpv): translate_unaryop 支持单目 * / &(Deref/AddrOf)

This commit is contained in:
TermiNexus committed 2026-08-28 07:35:03 +08:00
1 parent d971bae7cd
commit 6daec5fa58
1 file changed
+96
+96
View File
@@ -692,6 +692,102 @@ class ExprGenOps(ExprGenBase.ExprGenBase):
if operand_bits_inv == 64:
neg1 = llvmlite.const_int64(pool, -1)
return llvmlite.build_xor(builder, operand, neg1)
elif uo.op == ast.OpKind.Deref:
# *p → load 按 pointee 类型读取(对齐 translate_c_deref)
if self.Gen.ExprGenBase.is_ptr_type(operand.Ty) != 0:
d_pointee: llvmlite.LLVMType | t.CPtr = operand.Ty.Pointee
if d_pointee is not None:
return llvmlite.build_load(builder, d_pointee, operand)
# 非指针即类型推断退化:fail-fast,绝不按 i8 兜底读取
self.Gen.TypeGenErr.fatal_error(
node, "单目 '*' 解引用的操作数必须是指针类型(类型推断退化)", "TypeError")
return None
elif uo.op == ast.OpKind.AddrOf:
# &x → 左值地址(不 load):Name 变量 alloca / 模块全局 / 模块函数 /
# Attribute 字段 GEP / Subscript 元素地址(对齐 translate_c_addr 语义)
if trans is None:
return None
if uo.operand.kind() == ast.ASTKind.Name:
nm_ao: ast.Name | t.CPtr = (ast.Name | t.CPtr)(uo.operand)
if nm_ao.id is not None:
# self/cls 对象引用:返回对象指针本身(Ptr(Struct))而非
# 指针变量的地址(Ptr(Ptr(Struct)))
if string.strcmp(nm_ao.id, "self") == 0 or string.strcmp(nm_ao.id, "cls") == 0:
se_ao: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_ao.id)
if se_ao is not None and se_ao.Alloca is not None and se_ao.Alloca.Ty is not None:
match se_ao.Alloca.Ty:
case llvmlite.LLVMType.Ptr(sa1):
match sa1:
case llvmlite.LLVMType.Ptr(sa2):
obj_ty_sa: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, sa2)
return llvmlite.build_load(builder, obj_ty_sa, se_ao.Alloca)
case _:
pass
case _:
pass
v_ao: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_var(trans.SymTab, nm_ao.id)
if v_ao is None and mod is not None:
# 模块全局变量:经 make_global_ref 转成带引号的 Ptr(Ty) 引用
gv_ao: llvmlite.GlobalVariable | t.CPtr = self.Gen.ExprGenAttr.find_global_in_module(mod, nm_ao.id)
if gv_ao is not None and gv_ao.Name is not None and gv_ao.Ty is not None:
v_ao = self.Gen.ExprGenAttr.make_global_ref(pool, gv_ao.Name, gv_ao.Ty)
if v_ao is not None and v_ao.Ty is not None:
# 对象指针变量(alloca 是 Ptr(Ptr(Struct)),存对象指针):
# 变量语义即对象,返回对象指针(load 一次),对齐 translate_c_addr
match v_ao.Ty:
case llvmlite.LLVMType.Ptr(ao1):
match ao1:
case llvmlite.LLVMType.Ptr(ao2):
match ao2:
case llvmlite.LLVMType.Struct(_, _, _):
obj_ty_ao: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, ao2)
return llvmlite.build_load(builder, obj_ty_ao, v_ao)
case _:
pass
case _:
pass
case _:
pass
return v_ao
# 模块函数地址:函数符号本身
if v_ao is None and mod is not None:
f_ao: llvmlite.Function | t.CPtr = self.Gen.CallGenBase.find_func_in_module(mod, nm_ao.id)
if f_ao is not None:
fname_ao: str = llvmlite.function_get_name(f_ao)
if fname_ao is not None:
p_head_ao: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(f_ao)
p_cnt_ao: t.CSizeT = 0
p_cur_ao: llvmlite.Param | t.CPtr = p_head_ao
while p_cur_ao is not None:
p_cnt_ao += 1
p_cur_ao = llvmlite.param_get_next(p_cur_ao)
fn_ty_ao: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, f_ao.RetTy, p_head_ao, p_cnt_ao)
# 函数引用名按需加引号(数字开头/含 '.' 的 sha1 前缀名)
fnlen_ao: t.CSizeT = string.strlen(fname_ao)
needs_q_ao: int = self.Gen.ClassGenVTable._vtable_name_needs_quote(fname_ao)
fbuf_ao: str = pool.alloc(fnlen_ao + 4)
if fbuf_ao is not None and fn_ty_ao is not None:
if needs_q_ao != 0:
viperlib.snprintf(fbuf_ao, fnlen_ao + 4, "@\"%s\"", fname_ao)
else:
viperlib.snprintf(fbuf_ao, fnlen_ao + 4, "@%s", fname_ao)
return llvmlite.SSAValue(pool, llvmlite.Ptr(pool, fn_ty_ao), fbuf_ao)
elif uo.operand.kind() == ast.ASTKind.Attribute:
# 字段地址(GEP,不 load)
fptr_ao: llvmlite.Value | t.CPtr = self.Gen.ExprGenAttr.get_attribute_ptr(
builder, pool, mod, uo.operand, trans)
if fptr_ao is not None:
return fptr_ao
elif uo.operand.kind() == ast.ASTKind.Subscript:
# 元素地址(GEP,不 load)
sptr_ao: llvmlite.Value | t.CPtr = self.Gen.ExprGenName.get_subscript_ptr(
builder, pool, mod, uo.operand, trans)
if sptr_ao is not None:
return sptr_ao
self.Gen.TypeGenErr.fatal_error(
node, "单目 '&' 取地址的操作数必须是左值(Name/Attribute/Subscript)", "TypeError")
return None
return operand
# ============================================================
# 翻译布尔运算 BoolOp(op, values) — 短路求值,返回 i1