fix(TPV): c.Set 实现赋值语义 a=b(三形态: c.Deref左值/Name/Attribute), 修复 undefined reference to Set; 函数默认返回/裸return按返回类型生成浮点零值(ConstFloat 0.0, 修复 llc value doesn't match)

This commit is contained in:
TermiNexus committed 2026-08-08 21:35:59 +08:00
1 parent 59ae99f6d7
commit 57d6ffefad
3 files changed
+126 -1

No files matched your search

+109
View File
@@ -15,6 +15,7 @@ import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
@@ -750,6 +751,110 @@ def translate_c_derefas(pool: memhub.MemBuddy | t.CPtr,
llvmlite.build_store(builder, val, casted_ptr)
return val
# ============================================================
# c.Set(a, b) — 赋值语义 a = b(与 c.DerefAs 的指针语义不同)
#
# c.DerefAs(ptr, val) 是 *ptr = val(指针解引用写);
# c.Set(a, b) 是 a = b(a 为左值),a 支持三种形态:
# 1. c.Deref(ptr) → *ptr = b(zlib/vipermath 的 c.Set(c.Deref(p), v) 用法)
# 2. Name 变量 → 变量赋值(含 global/nonlocal/局部)
# 3. Attribute → 字段赋值(GEP + store)
# ============================================================
def translate_c_set(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.Set(a, b) → a = b(赋值语义,a 为左值)"""
if cl is None:
return None
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
if cargs is None or cargs.__len__() < 2:
return None
a_node: ast.AST | t.CPtr = cargs.get(0)
b_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, cargs.get(1), None, 0, trans)
if b_val is None:
return None
# 形态 1: c.Set(c.Deref(ptr), b) → *ptr = b
if a_node is not None and a_node.kind() == ast.ASTKind.Call:
d_call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(a_node)
if d_call.func is not None and d_call.func.kind() == ast.ASTKind.Attribute:
d_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(d_call.func)
if d_at.attr is not None and string.strcmp(d_at.attr, "Deref") == 0:
d_args: list[ast.AST | t.CPtr] | t.CPtr = d_call.args
if d_args is not None and d_args.__len__() >= 1:
ptr_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, d_args.get(0), None, 0, trans)
if ptr_val is not None:
val_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, b_val.Ty)
casted_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, ptr_val, val_ptr_ty)
if casted_ptr is not None:
llvmlite.build_store(builder, b_val, casted_ptr)
return b_val
# 其他 Call 形态不可作左值
return b_val
# 形态 2: Name 变量赋值
if a_node is not None and a_node.kind() == ast.ASTKind.Name and trans is not None:
nm_set: ast.Name | t.CPtr = (ast.Name | t.CPtr)(a_node)
if nm_set.id is not None:
if HT.is_global_name(trans, nm_set.id) != 0:
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
trans.SymTab, nm_set.id)
if mod_alloca is not None:
tg_ty: llvmlite.LLVMType | t.CPtr = None
if mod_alloca.Ty is not None:
tg_ty = mod_alloca.Ty.Pointee
sv: llvmlite.Value | t.CPtr = b_val
if tg_ty is not None:
sv = HandlesExpr.coerce_to_type(builder, b_val, tg_ty, a_node)
llvmlite.build_store(builder, sv, mod_alloca)
return b_val
if HT.is_nonlocal_name(trans, nm_set.id) != 0:
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
trans, nm_set.id)
if nl_ptr is not None:
nl_ty: llvmlite.LLVMType | t.CPtr = None
if nl_ptr.Ty is not None:
nl_ty = nl_ptr.Ty.Pointee
sv2: llvmlite.Value | t.CPtr = b_val
if nl_ty is not None:
sv2 = HandlesExpr.coerce_to_type(builder, b_val, nl_ty, a_node)
llvmlite.build_store(builder, sv2, nl_ptr)
return b_val
alloca: llvmlite.Value | t.CPtr = HandlesVar.get_or_create_sym(
trans.SymTab, pool, builder, nm_set.id, b_val.Ty)
if alloca is not None:
ac_ty: llvmlite.LLVMType | t.CPtr = None
if alloca.Ty is not None:
ac_ty = alloca.Ty.Pointee
sv3: llvmlite.Value | t.CPtr = b_val
if ac_ty is not None:
sv3 = HandlesExpr.coerce_to_type(builder, b_val, ac_ty, a_node)
llvmlite.build_store(builder, sv3, alloca)
return b_val
return b_val
# 形态 3: Attribute 字段赋值
if a_node is not None and a_node.kind() == ast.ASTKind.Attribute:
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
builder, pool, mod, a_node, trans)
if field_ptr is not None:
fd_ty: llvmlite.LLVMType | t.CPtr = None
if field_ptr.Ty is not None:
fd_ty = field_ptr.Ty.Pointee
sv4: llvmlite.Value | t.CPtr = b_val
if fd_ty is not None:
sv4 = HandlesExpr.coerce_to_type(builder, b_val, fd_ty, a_node)
llvmlite.build_store(builder, sv4, field_ptr)
return b_val
return b_val
# ============================================================
# c.Addr(var) — 取变量地址,返回 alloca 指针(不 load)
#
@@ -4351,6 +4456,10 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
return translate_c_derefas(pool, builder, mod, cl, trans)
elif string.strcmp(func_name, "Addr") == 0:
return translate_c_addr(pool, builder, mod, cl, trans)
elif string.strcmp(func_name, "Set") == 0:
# c.Set(a, b) = a = b(赋值语义,非指针解引用)。
# 若当普通函数调用会生成 @Set 引用导致链接失败(undefined reference to `Set')。
return translate_c_set(pool, builder, mod, cl, trans)
elif string.strcmp(func_name, "Load") == 0:
return translate_c_load(pool, builder, mod, cl, trans)
elif string.strcmp(func_name, "Asm") == 0:
+8
View File
@@ -794,19 +794,27 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
if last_is_return == 0:
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
# 根据返回类型生成正确的零值返回
# 必须覆盖浮点返回类型:double/float 函数生成 ConstFloat(0.0),
# 否则默认 ret i32 0 类型不匹配(llc: value doesn't match function result type)
_is_void: int = 0
_is_ptr: int = 0
_is_float: int = 0
if ret_ty is not None:
match ret_ty:
case llvmlite.LLVMType.Void():
_is_void = 1
case llvmlite.LLVMType.Ptr(_pe):
_is_ptr = 1
case llvmlite.LLVMType.Float(_fb):
_is_float = 1
if _is_void != 0:
llvmlite.build_ret_void(func_builder)
elif _is_ptr != 0:
_null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null")
llvmlite.build_ret(func_builder, _null_val)
elif _is_float != 0:
_zero_f: llvmlite.Value | t.CPtr = llvmlite.ConstFloat(pool, ret_ty, 0.0)
llvmlite.build_ret(func_builder, _zero_f)
else:
_zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
llvmlite.build_ret(func_builder, _zero_val)
+9 -1
View File
@@ -67,11 +67,13 @@ class ReturnHandle(HandlesBase.Mixin):
# val 为 None 时(裸 return):检查当前函数返回类型
# void 函数(如 __init__/__before_init__)生成 ret void,
# ptr 函数生成 ret ptr null,否则 ret i32 0
# ptr 函数生成 ret ptr null,浮点函数生成 ConstFloat(0.0),
# 否则 ret i32 0(浮点漏处理会报 llc: value doesn't match function result type)
if val is None:
cur_func: llvmlite.Function | t.CPtr = self.Trans._cur_func
is_void_ret: int = 0
is_ptr_ret: int = 0
is_float_ret: int = 0
ret_ty: llvmlite.LLVMType | t.CPtr = None
if cur_func is not None:
ret_ty = llvmlite.function_get_ret_ty(cur_func)
@@ -81,6 +83,8 @@ class ReturnHandle(HandlesBase.Mixin):
is_void_ret = 1
case llvmlite.LLVMType.Ptr(_pe):
is_ptr_ret = 1
case llvmlite.LLVMType.Float(_fb):
is_float_ret = 1
if is_void_ret != 0:
llvmlite.build_ret_void(builder)
return 0
@@ -88,6 +92,10 @@ class ReturnHandle(HandlesBase.Mixin):
null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null")
llvmlite.build_ret(builder, null_val)
return 0
if is_float_ret != 0:
zero_f: llvmlite.Value | t.CPtr = llvmlite.ConstFloat(pool, ret_ty, 0.0)
llvmlite.build_ret(builder, zero_f)
return 0
val = llvmlite.const_int32(pool, 0)
# 类型转换:确保 val 类型与函数返回类型匹配