diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index 43c2d3f..28bbc2d 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -6,6 +6,7 @@ import memhub import string import stdlib import lib.core.Gen.Translator as HT +import lib.core.Gen.GenTypes as GenTypes import lib.Stub.StubGen.VpiReader as VpiReader import lib.core.Gen.GenApi as GenApi @@ -718,6 +719,36 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): mc_src1: llvmlite.Value* = None mc_num1: llvmlite.Value* = None + # 省略参数补齐用的默认参数表查询(与 CallGenMixin 非 kwargs 路径同一真源)。 + # 根因:本路径此前对"位置/关键字均未提供的形参"直接跳过 → 调用实参数 < + # define 形参数,被调函数按 x64 ABI 读未写寄存器/栈槽(remote.one(x = 1) + # 的 cap 读成 0/垃圾,DefaultArgTest 断言失败)。 + # 定义模块 SHA1 取 found_func 的 mangled 名前缀 "{sha1}.func"(普通跨模块/ + # 同模块函数),取不到再回退当前模块 SHA1(同模块调用)。默认值表按 + # 「名 + 定义模块 SHA1」登记(_register_global_defaults),注册时已对常量 + # 快照,跨 1b reset 永久存活 ⇒ 跨模块也能取到定义处的真实默认值。 + kw_callee_sha: str = None + kw_found_name: str = llvmlite.function_get_name(found_func) + if kw_found_name is not None: + if GenApi.sha1_prefix_len(kw_found_name) != 0: + kw_sha_buf: str = pool.alloc(17) + if kw_sha_buf is not None: + string.strncpy(kw_sha_buf, kw_found_name, 16) + kw_sha_buf[16] = '\0' + kw_callee_sha = kw_sha_buf + if kw_callee_sha is None and self.Gen.TypeGenBase is not None: + kw_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 + kw_gd: GenTypes.FuncDefaultsEntry* = None + if kw_callee_sha is not None: + kw_gd = self.Gen.CallGenLeafKit.find_func_defaults(func_name, kw_callee_sha) + kw_default_count: int = 0 + kw_default_off: int = 0 + if kw_gd is not None: + kw_default_count = kw_gd.DefaultCount + kw_default_off = kw_gd.ParamCount - kw_gd.DefaultCount + if kw_default_off < 0: + kw_default_off = 0 + # 遍历函数参数链表(使用访问器获取 Head) param_idx: sizet = 0 cur_param: llvmlite.Param* = llvmlite.function_get_param_head(found_func) @@ -742,6 +773,25 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, kw.value, None, 0, trans, param_ty) break + # 位置/关键字均未提供该形参:用**定义处**的默认值补齐(默认值右对齐, + # 索引 = param_idx - param_count + default_count)。缺省且定义处无默认值 + # 可用时 fail-fast——绝不静默漏参或填零(漏参会令被调函数按 ABI 读垃圾)。 + if arg_val is None: + if kw_default_count > 0 and int(param_idx) >= kw_default_off: + kw_di: int = int(param_idx) - kw_default_off + if kw_di >= 0 and kw_di < kw_default_count: + arg_val = self.Gen.CallGenLeafKit._build_const_from_snapshot( + pool, mod, kw_gd, kw_di, trans, builder) + if arg_val is None: + kw_node: ast.AST* = None + if keywords is not None and kw_count > 0: + kw_node = keywords.get(0) + self.Gen.TypeGenErr.fatal_error( + kw_node, + f"调用 '{func_name}' 的某个形参既未按位置/关键字传入," + f"定义处也无默认值可填充(拒绝静默漏参/填零)", + "TypeError") + if arg_val is not None: # 类型转换(按参数类型,使用访问器) if param_ty is not None: