diff --git a/App/lib/core/Handles/HandlesExprCall.vp b/App/lib/core/Handles/HandlesExprCall.vp index d3a06ec..7a31b3e 100644 --- a/App/lib/core/Handles/HandlesExprCall.vp +++ b/App/lib/core/Handles/HandlesExprCall.vp @@ -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: diff --git a/App/lib/core/Handles/HandlesFunctions.vp b/App/lib/core/Handles/HandlesFunctions.vp index 9a4a6ca..9a829b0 100644 --- a/App/lib/core/Handles/HandlesFunctions.vp +++ b/App/lib/core/Handles/HandlesFunctions.vp @@ -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) diff --git a/App/lib/core/Handles/HandlesReturn.vp b/App/lib/core/Handles/HandlesReturn.vp index cde6062..ce08fbc 100644 --- a/App/lib/core/Handles/HandlesReturn.vp +++ b/App/lib/core/Handles/HandlesReturn.vp @@ -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 类型与函数返回类型匹配