feat(tpv): translate_unaryop 支持单目 * / &(Deref/AddrOf)
This commit is contained in:
1 parent
d971bae7cd
commit
6daec5fa58
1 file changed
+96
@@ -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
|
||||
|
||||
Reference in new issue
Block a user