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:
1 parent
59ae99f6d7
commit
57d6ffefad
3 files changed
+126
-1
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 类型与函数返回类型匹配
|
||||
|
||||
Reference in new issue
Block a user